for Linux.
2. My Linux environment
-Linux kernel: 2.4.0 / 2.2.18
-pcmcia-cs: 3.1.24
-gcc: gcc-2.95.2
+Linux kernel: 2.4.7 / 2.2.19
+pcmcia-cs: 3.1.27
+gcc: gcc-2.95.4
PC card: I-O data PCSC-F (NinjaSCSI-3)
I-O data CBSC-II in 16 bit mode (NinjaSCSI-32Bi)
SCSI device: I-O data CDPS-PX24 (CD-ROM drive)
[4] Extract this driver's archive somewhere, and edit Makefile, then do make.
$ tar -zxvf nsp_cs-x.x.tar.gz
$ cd nsp_cs-x.x
+$ emacs Makefile
+...
$ make
[5] Copy nsp_cs.o to suitable plase, like /lib/modules/<Kernel version>/pcmcia/ .
bind "nsp_cs"
-------------------------------------
-[7] Boot (or reboot) pcmcia-cs.
+[7] Start (or restart) pcmcia-cs.
# /etc/rc.d/rc.pcmcia start (BSD style)
or
# /etc/init.d/pcmcia start (SYSV style)
your data. Please backup your data when you use this driver.
6. Known Bugs
- Some write error occurs when you use slow device.
+ In 2.4 kernel, you can't use 640MB Optical disk. This error comes from
+high level SCSI driver.
7. Testing
Please send me some reports(bug reports etc..) of this software.
See GPL.
-2001/02/01 yokota@netlab.is.tsukuba.ac.jp <YOKOTA Hiroshi>
+2001/08/08 yokota@netlab.is.tsukuba.ac.jp <YOKOTA Hiroshi>
<description of your architecture>
Please follow this format - it is an automated system. You should
- receive a reply within one day.
+ receive a reply in short order.
---
Russell King (26/01/2001)
--- /dev/null
+ADS Bitsy Single Board Computer
+(It is different from Bitsy(iPAQ) of Compaq)
+
+For more details, contact Applied Data Systems or see
+http://www.applieddata.net/products.html
+
+The Linux support for this product has been provided by
+Woojung Huh <whuh@applieddata.net>
+
+Use 'make adsbitsy_config' before any 'make config'.
+This will set up defaults for ADS Bitsy support.
+
+The kernel zImage is linked to be loaded and executed at 0xc0400000.
+
+Linux can be used with the ADS BootLoader that ships with the
+newer rev boards. See their documentation on how to load Linux.
+
+Supported peripherals:
+- SA1100 LCD frame buffer (8/16bpp...sort of)
+- SA1111 USB Master
+- SA1100 serial port
+- pcmcia, compact flash
+- touchscreen(ucb1200)
+- console on LCD screen
+- serial ports (ttyS[0-2])
+ - ttyS0 is default for serial console
+
+To do:
+- everything else! :-)
+
+Notes:
+
+- The flash on board is divided into 3 partitions.
+ You should be careful to use flash on board.
+ It's partition is different from GraphicsClient Plus and GraphicsMaster
+
+- 16bpp mode requires a different cable than what ships with the board.
+ Contact ADS or look through the manual to wire your own. Currently,
+ if you compile with 16bit mode support and switch into a lower bpp
+ mode, the timing is off so the image is corrupted. This will be
+ fixed soon.
+
+Any contribution can be sent to nico@cam.org and will be greatly welcome!
--- /dev/null
+ADS GraphicsMaster Single Board Computer
+
+For more details, contact Applied Data Systems or see
+http://www.applieddata.net/products.html
+
+The original Linux support for this product has been provided by
+Nicolas Pitre <nico@cam.org>. Continued development work by
+Woojung Huh <whuh@applieddata.net>
+
+Use 'make graphicsmaster_config' before any 'make config'.
+This will set up defaults for GraphicsMaster support.
+
+The kernel zImage is linked to be loaded and executed at 0xc0400000.
+
+Linux can be used with the ADS BootLoader that ships with the
+newer rev boards. See their documentation on how to load Linux.
+
+Supported peripherals:
+- SA1100 LCD frame buffer (8/16bpp...sort of)
+- SA1111 USB Master
+- on-board SMC 92C96 ethernet NIC
+- SA1100 serial port
+- flash memory access (MTD/JFFS)
+- pcmcia, compact flash
+- touchscreen(ucb1200)
+- ps/2 keyboard
+- console on LCD screen
+- serial ports (ttyS[0-2])
+ - ttyS0 is default for serial console
+- Smart I/O (ADC, keypad, digital inputs, etc)
+ See http://www.applieddata.com/developers/linux for IOCTL documentation
+ and example user space code. ps/2 keybd is multiplexed through this driver
+
+To do:
+- everything else! :-)
+
+Notes:
+
+- The flash on board is divided into 3 partitions. mtd0 is where
+ the zImage is stored. It's been marked as read-only to keep you
+ from blasting over the bootloader. :) mtd1 is
+ for the ramdisk.gz image. mtd2 is user flash space and can be
+ utilized for either JFFS or if you're feeling crazy, running ext2
+ on top of it. If you're not using the ADS bootloader, you're
+ welcome to blast over the mtd1 partition also.
+
+- 16bpp mode requires a different cable than what ships with the board.
+ Contact ADS or look through the manual to wire your own. Currently,
+ if you compile with 16bit mode support and switch into a lower bpp
+ mode, the timing is off so the image is corrupted. This will be
+ fixed soon.
+
+Any contribution can be sent to nico@cam.org and will be greatly welcome!
by Dialogue Technology (http://www.dialogue.com.tw/).
It has EISA slots for ease of configuration with SDRAM/Flash
memory card, USB/Serial/Audio card, Compact Flash card,
-and TFT-LCD card.
+PCMCIA/IDE card and TFT-LCD card.
To compile for Pangolin, you must issue the following commands:
- UDA1341 sound driver
- SA1100 LCD controller for 800x600 16bpp TFT-LCD
- MQ-200 driver for 800x600 16bpp TFT-LCD
+- Penmount(touch panel) driver
+- PCMCIA driver
+- SMC91C94 LAN driver
+- IDE driver (experimental)
* SA 5300
* SA 5i
* SA 532
+ * SA 5312
-If notes are not already created in the /dev/cciss directory
+If nodes are not already created in the /dev/cciss directory
# mkdev.cciss [ctlrs]
/dev/cciss/c1d1p1 Controller 1, disk 1, partition 1
/dev/cciss/c1d1p2 Controller 1, disk 1, partition 2
/dev/cciss/c1d1p3 Controller 1, disk 1, partition 3
+
+SCSI tape drive and medium changer support
+------------------------------------------
+
+SCSI sequential access devices and medium changer devices are supported and
+appropriate device nodes are automatically created. (e.g.
+/dev/st0, /dev/st1, etc. See the "st" man page for more details.)
+You must enable "SCSI tape drive support for Smart Array 5xxx" and
+"SCSI support" in your kernel configuration to be able to use SCSI
+tape drives with your Smart Array 5xxx controller.
+
+Additionally, note that the driver will not engage the SCSI core at init
+time. The driver must be directed to dynamically engage the SCSI core via
+the /proc filesystem entry which the "block" side of the driver creates as
+/proc/driver/cciss/cciss* at runtime. This is because at driver init time,
+the SCSI core may not yet be initialized (because the driver is a block
+driver) and attempting to register it with the SCSI core in such a case
+would cause a hang. This is best done via an initialization script
+(typically in /etc/init.d, but could vary depending on distibution).
+For example:
+
+ for x in /proc/driver/cciss/cciss[0-9]*
+ do
+ echo "engage scsi" > $x
+ done
+
+Once the SCSI core is engaged by the driver, it cannot be disengaged
+(except by unloading the driver, if it happens to be linked as a module.)
+
+Note also that if no sequential access devices or medium changers are
+detected, the SCSI core will not be engaged by the action of the above
+script.
+
+Hot plug support for SCSI tape drives
+-------------------------------------
+
+Hot plugging of SCSI tape drives is supported, with some caveats.
+The cciss driver must be informed that changes to the SCSI bus
+have been made, in addition to and prior to informing the the SCSI
+mid layer. This may be done via the /proc filesystem. For example:
+
+ echo "rescan" > /proc/scsi/cciss0/1
+
+This causes the adapter to query the adapter about changes to the
+physical SCSI buses and/or fibre channel arbitrated loop and the
+driver to make note of any new or removed sequential access devices
+or medium changers. The driver will output messages indicating what
+devices have been added or removed and the controller, bus, target and
+lun used to address the device. Once this is done, the SCSI mid layer
+can be informed of changes to the virtual SCSI bus which the driver
+presents to it in the usual way. For example:
+
+ echo add-single-device 3 2 1 0 > /proc/scsi/scsi
+
+to add a device on controller 3, bus 2, target 1, lun 0. Note that
+the driver makes an effort to preserve the devices positions
+in the virtual SCSI bus, so if you are only moving tape drives
+around on the same adapter and not adding or removing tape drives
+from the adapter, informing the SCSI mid layer may not be necessary.
+
+Note that the naming convention of the /proc filesystem entries
+contains a number in addition to the driver name. (E.g. "cciss0"
+instead of just "cciss" which you might expect.) This is because
+of changes to the 2.4 kernel PCI interface related to PCI hot plug
+that imply the driver must register with the SCSI mid layer once per
+adapter instance rather than once per driver.
+
+Note: ONLY sequential access devices and medium changers are presented
+as SCSI devices to the SCSI mid layer by the cciss driver. Specifically,
+physical SCSI disk drives are NOT presented to the SCSI mid layer. The
+physical SCSI disk drives are controlled directly by the array controller
+hardware and it is important to prevent the OS from attempting to directly
+access these devices too, as if the array controller were merely a SCSI
+controller in the same way that we are allowing it to access SCSI tape drives.
+
/* buf[0] contains the read byte */
}
+IMPORTANT: because of the use of inline functions, you *have* to use
+'-O' or some variation when you compile your program!
+
Full interface description
==========================
-This is an explanation of what i2c is, and what is supported.
+This is an explanation of what i2c is, and what is supported in this package.
I2C and SMBus
=============
-I2C (pronounce: I square C) is a protocol developed by Philips. It is a
+I2C (pronounce: I squared C) is a protocol developed by Philips. It is a
slow two-wire protocol (10-100 kHz), but it suffices for many types of
devices.
Adapter
Device -> Driver
Client
+
An Algorithm driver contains general code that can be used for a whole class
of I2C adapters. Each specific adapter driver depends on one algorithm
driver.
For a given configuration, you will need a driver for your I2C bus (usually
a separate Adapter and Algorithm driver), and drivers for your I2C devices
-(usually one driver for each device).
+(usually one driver for each device). There are no I2C device drivers
+in this package. See the lm_sensors project http://www.lm-sensors.nu
+for device drivers.
+
+Included Bus Drivers
+====================
+Note that not only stable drivers are patched into the kernel by 'mkpatch'.
-Included Drivers
-================
Base modules
------------
i2c-core: The basic I2C code, including the /proc interface
i2c-dev: The /dev interface
+i2c-proc: The /proc interface for device (client) drivers
Algorithm drivers
-----------------
-i2c-algo-bit: A bit-banging algorithm
-i2c-algo-pcf: A PCF 8584 style algorithm
+i2c-algo-8xx: An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT)
+i2c-algo-bit: A bit-banging algorithm
+i2c-algo-pcf: A PCF 8584 style algorithm
+i2c-algo-ppc405: An algorithm for the I2C device in IBM 405xx processors (NOT BUILT BY DEFAULT)
Adapter drivers
---------------
i2c-elektor: Elektor ISA card (uses i2c-algo-pcf)
i2c-elv: ELV parallel port adapter (uses i2c-algo-bit)
+i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (BROKEN - missing i2c-pcf-epp.h)
i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit)
+i2c-ppc405: IBM 405xx processor I2C device (uses i2c-algo-ppc405) (NOT BUILT BY DEFAULT)
+i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit)
+i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT)
i2c-velleman: Velleman K9000 parallel port adapter (uses i2c-algo-bit)
/* detach_client */ &foo_detach_client,
/* command */ &foo_command, /* May be NULL */
/* inc_use */ &foo_inc_use, /* May be NULL */
- /* dec_use */ &foo_dev_use /* May be NULL */
+ /* dec_use */ &foo_dec_use /* May be NULL */
}
The name can be chosen freely, and may be upto 40 characters long. Please
detection algorithm.
You do not have to use this parameter interface; but don't try to use
-function i2c_probe() (or sensors_detect()) if you don't.
+function i2c_probe() (or i2c_detect()) if you don't.
NOTE: If you want to write a `sensors' driver, the interface is slightly
different! See below.
return i2c_probe(adapter,&addr_data,&foo_detect_client);
}
-For `sensors' drivers, use the sensors_detect function instead:
+For `sensors' drivers, use the i2c_detect function instead:
int foo_attach_adapter(struct i2c_adapter *adapter)
{
- return sensors_detect(adapter,&addr_data,&foo_detect_client);
+ return i2c_detect(adapter,&addr_data,&foo_detect_client);
}
Remember, structure `addr_data' is defined by the macros explained above,
so you do not have to define it yourself.
-The i2c_probe or sensors_detect function will call the foo_detect_client
+The i2c_probe or i2c_detect function will call the foo_detect_client
function only for those i2c addresses that actually have a device on
them (unless a `force' parameter was used). In addition, addresses that
are already in use (by some other registered client) are skipped.
The detect client function
--------------------------
-The detect client function is called by i2c_probe or sensors_detect.
+The detect client function is called by i2c_probe or i2c_detect.
The `kind' parameter contains 0 if this call is due to a `force'
-parameter, and 0 otherwise (for sensors_detect, it contains 0 if
+parameter, and 0 otherwise (for i2c_detect, it contains 0 if
this call is due to the generic `force' parameter, and the chip type
number if it is due to a specific `force' parameter).
/* SENSORS ONLY BEGIN */
/* Register a new directory entry with module sensors. See below for
the `template' structure. */
- if ((i = sensors_register_entry(new_client, type_name,
+ if ((i = i2c_register_entry(new_client, type_name,
foo_dir_table_template,THIS_MODULE)) < 0) {
err = i;
goto ERROR4;
int err,i;
/* SENSORS ONLY START */
- /* Deregister with the `sensors' module. */
- sensors_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
+ /* Deregister with the `i2c-proc' module. */
+ i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
/* SENSORS ONLY END */
/* Try to detach the client from i2c space */
First, I will give an example definition.
static ctl_table foo_dir_table_template[] = {
- { FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &sensors_proc_real,
- &sensors_sysctl_real,NULL,&foo_func },
- { FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &sensors_proc_real,
- &sensors_sysctl_real,NULL,&foo_func },
- { FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &sensors_proc_real,
- &sensors_sysctl_real,NULL,&foo_data },
+ { FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real,NULL,&foo_func },
+ { FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real,NULL,&foo_func },
+ { FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real,NULL,&foo_data },
{ 0 }
};
fourth should always be 0. The fifth is the mode of the /proc file;
0644 is safe, as the file will be owned by root:root.
-The seventh and eighth parameters should be &sensors_proc_real and
-&sensors_sysctl_real if you want to export lists of reals (scaled
+The seventh and eighth parameters should be &i2c_proc_real and
+&i2c_sysctl_real if you want to export lists of reals (scaled
integers). You can also use your own function for them, as usual.
Finally, the last parameter is the call-back to gather the data
(see below) if you use the *_proc_real functions.
the device driver will be notified if possible, so the device will become
available to the system.
+ You can also add ranges of devices to be ignored by piping to
+ /proc/cio_ignore; "add <devnorange>, <devnorange>, ..." will ignore the
+ specified devices.
+
+ Note: Already known devices cannot be ignored; this also applies to devices
+ which are gone after a machine check.
+
+ For example, if device abcd is already known and all other devices a000-afff
+ are not known, "echo add 0xa000-0xaccc, 0xaf00-0xafff > /proc/cio_ignore"
+ will add af00-afff to the list of ignored devices and skip a000-accc.
+
* /proc/s390dbf/cio_*/ (S/390 debug feature)
/proc/s390dbf/cio_*/level a number between 0 and 6; see the documentation on
the S/390 debug feature (Documentation/s390/s390dbf.txt) for details.
+* /proc/irq_count
+
+ This entry counts how many times s390_process_IRQ has been called for each
+ CPU. This info is in /proc/interrupts on other architectures.
.B (ctc|escon|lcs|osad|qeth)<devif_num>,
read_devno,write_devno,<data_devno,memory_usage_in_k,port_no/protocol_no,checksum_received_ip_pkts,use_hw_stats>
.It
-devif_num of -1 indicates you don't care what device interface number is chosen, omitting it indicates this is a range of devices for which you want to force to be detected as a particular type.
-The data_devno field is only valid for qeth devices when not forcing a range of devices.
-all parameters after & including memory_usage_in_k can be set optionally if not set they
+devif_num of -1 indicates you don't care what device interface number is chosen, omitting it indicates this is a range of devices for which you want to force to be detected as a particular type, qeth devices can't be forced as a range as it makes no sense for them.
+The data_devno field is only valid for qeth devices, all parameters including & after memory_usage_in_k can be set optionally, if not set they
go to default values. memory_usage_in_k ( 0 the default ) means let the driver choose,checksum_received_ip_pkts & use_hw_stats are set to false
.It
e.g. ctc0,0x7c00,0x7c01
.It
Tells the channel layer to force ctc0 if detected to use cuu's 7c00 & 7c01 port,port_no is the relative adapter no on lcs, on ctc/escon this field is the ctc/escon protocol number ( default 0 ), don't do checksumming on received ip packets & as ctc doesn't have hardware stats so it ignores this parameter. This can be used for instance to force a device if it presents bad sense data to the IO layer & thus autodetection fails.
.It
-qeth,0x7c00,0x7d00,-1,4096
-All devices between 0x7c00 & 7d00 should be detected as gigabit ethernet, let the driver use 4096k for each instance, don't care what port relative adapter number is chosen, don't checksum received ip packets & use hw stats .
+lcs,0x7c00,0x7d00,-1,4096
+All devices between 0x7c00 & 7d00 should be detected as lcs, let the driver use 4096k for each instance, don't care what port relative adapter number is chosen, don't checksum received ip packets & use hw stats .
.It
qeth1,0x7c00,0x7c01,0x7c02
.It
Force drivers modules to stay loaded even if no device is found,
this is useful for debugging & one wishes to examine debug entries in
/proc/s390dbf/ to find out why a module failed to load.
+.It
+e.g.
+.It
+persist,-1 forces all devices to persist.
+.It
+persist,0 forces all channel devices to be non persistent.
.El
.It
Example:
> ls /proc/s390dbf/dasd
-hex_ascii level raw
+flush hex_ascii level raw
> cat /proc/s390dbf/dasd/hex_ascii | sort +1
00 00974733272:680099 2 - 02 0006ad7e 07 ea 4a 90 | ....
00 00974733272:682210 2 - 02 0006ade6 46 52 45 45 | FREE
> cat /proc/s390dbf/dasd/level
5
+Flushing debug areas
+--------------------
+Debug areas can be flushed with piping the number of the desired
+area (0...n) to the proc file "flush". When using "-" all debug areas
+are flushed.
+
+Examples:
+
+1. Flush debug area 0:
+> echo "0" > /proc/s390dbf/dasd/flush
+
+2. Flush all debug areas:
+> echo "-" > /proc/s390dbf/dasd/flush
+
lcrash Interface
----------------
It is planned that the dump analysis tool lcrash gets an additional command
- capture button events (only on Vaio Picturebook series)
- Fn keys
- bluetooth button (only on C1VR model)
+ - back button (PCG-GR7/K model)
+ - lid open/close events (Z600NE model)
Those events (see linux/sonypi.h) can be polled using the character device node
/dev/sonypi (major 10, minor auto allocated or specified as a option).
Module options:
---------------
+Several options can be passed to the sonypi driver, either by adding them
+to /etc/modules.conf file, when the driver is compiled as a module or by
+adding the following to the kernel command line (in your bootloader):
+
+ sonypi=minor[[[[,camera],fnkeyinit],verbose],compat]
+
+where:
+
minor: minor number of the misc device /dev/sonypi,
default is -1 (automatic allocation, see /proc/misc
or kernel logs)
verbose: print unknown events from the sonypi device
+ compat: uses some compatibility code for enabling the sonypi
+ events. If the driver worked for you in the past
+ (prior to version 1.5) and does not work anymore,
+ add this option and report to the author.
+
Module use:
-----------
+++ /dev/null
-Iomega Buz Driver for Linux
-===========================
-
-by Rainer Johanni <Rainer@Johanni.de>
-
-Compiling and Loading the Driver
-================================
-
-You must run a 2.2.x kernel in order to use this driver.
-
-To compile the driver, just type make.
-
-Besides the files in this directory, the driver needs the
-'videodev' and the 'i2c' module from the Linux kernel.
-In order to get these modules available, enable module support
-for VIDEODEV and BTTV (which implies i2c) in your kernel
-configuration. You find these devices in the menu
-"Character Devices" in your Kernel Configuration.
-
-Before you load the driver you must have a video device
-at major device node 81. If you don't have it yet, do the
-following (as root!):
-
-cd /dev
-mknod video0 c 81 0
-ln -s video0 video
-
-Edit the 'update' script if you want to give the driver
-special options and then type (as root)
-
-./update
-
-to insert all the necessary modules into the kernel.
-
-If you want to make full use of the Video for Linux uncompressed
-grabbing facilities, you must either
-
-- obtain and install the "big_physarea patch" for your kernel and
- set aside the necessary memory during boot time.
- There seem to be several versions of this patch against
- various kernel versions floating around in the net,
- you may obtain one e.g. from:
- http://www.polyware.nl/~middelin/patch/bigphysarea-2.2.1.tar.gz
- You also have to compile your driver AFTER installing that patch
- in order to get it working
-
- or
-
-- start your kernel with the mem=xxx option, where xxx is your
- real memory minus the memory needed for the buffers.
- For doing this add an entry in lilo.conf (if you use lilo):
- append "mem=xxxM"
- or add a line in your linux.par file (if you use loadlin):
- mem=xxxM
-
-The second method is by far easier, however it is dangerous
-if more than one driver at a time has the idea to use the memory
-leftover by setting the mem=xxx parameter below the actual
-memory size.
-
-Read also below how to use this memory!
-
-
-
-Driver Options
-==============
-
-You are able to customize the behavior of the driver by giving
-it some options at start time.
-
-default_input, default_norm
----------------------------
-
-As soon as the driver is loaded, the Buz samples video signals
-from one of its input ports and displays it on its output.
-The driver uses the Composite Input and the video norm PAL for this.
-If you want to change this default behavior, set default_input=1
-(for S-VHS input) or default_norm=1 for NTSC.
-
-v4l_nbufs, v4l_bufsize
-----------------------
-
-In order to make to make full use of the Video for Linux picture
-grabbing facilities of the driver (which are needed by many
-Video for Linux applications), the driver needs a set of
-physically contiguous buffers for grabbing. These parameters
-determine how many buffers of which size the driver will
-allocate at open (the open will fail if it is unable to do so!).
-
-These values do not affect the MJPEG grabbing facilities of the driver,
-they are needed for uncompressed image grabbing only!!!
-
-v4l_nbufs is the number of buffers to allocate, a value of 2 (the default)
-should be sufficient in almost all cases. Only special applications
-(streaming captures) will need more buffers and then mostly the
-MJPEG capturing features of the Buz will be more appropriate.
-So leave this parameter at it's default unless you know what you do.
-
-The things for v4l_bufsize are more complicated:
-v4l_bufsize is set by default to 128 [KB] which is the maximum
-amount of physically contiguous memory Linux is able to allocate
-without kernel changes. This is sufficient for grabbing 24 bit color images
-up to sizes of approx. 240x180 pixels (240*180*3 = 129600, 128 KB = 131072).
-
-In order to be able to capture bigger images you have either to
-- obtain and install the "big_physarea patch" and set aside
- the necessary memory during boot time or
-- start your kernel with the mem=xxx option, where xxx is your
- real memory minus the memory needed for the buffers.
-In that case, useful settings for v4l_bufsize are
-- 1296 [Kb] for grabbing 24 bit images of max size 768*576
-- 1728 [Kb] for 32bit images of same size (4*768*576 = 1728 Kb!)
-You may reduce these numbers accordingly if you know you are only
-grabbing 720 pixels wide images or NTSC images (max height 480).
-
-In some cases it may happen that Linux isn't even able to obtain
-the default 128 KB buffers. If you don't need uncompressed image
-grabbing at all, set v4l_bufsize to an arbitrary small value (e.g. 4)
-in order to be able to open the video device.
-
-vidmem
-------
-
-The video mem address of the video card.
-The driver has a little database for some videocards
-to determine it from there. If your video card is not in there
-you have either to give it to the driver as a parameter
-or set in in a VIDIOCSFBUF ioctl
-
-The videocard database is contained in the file "videocards.h"
-Gernot Ziegler wants to keep an actual version of that file.
-If your card is not contained in that file, look at
-http://www.lysator.liu.se/~gz/buz/ for an actual version of
-"videocards.h".
-
-triton, natoma
---------------
-
-The driver tries to detect if you have a triton or natome chipset
-in order to take special measures for these chipsets.
-If this detection fails but you are sure you have such a chipset,
-set the corresponding variable to 1.
-This is a very special option and may go away in the future.
-
-
-
-Programming interface
-=====================
-
-This driver should be fully compliant to Video for Linux, so all
-tools working with Video for Linux should work with (hopefully)
-no problems.
-
-A description of the Video for Linux programming interface can be found at:
-http://roadrunner.swansea.linux.org.uk/v4lapi.shtml
-
-Besides the Video for Linux interface, the driver has a "proprietary"
-interface for accessing the Buz's MJPEG capture and playback facilities.
-
-The ioctls for that interface are as follows:
-
-BUZIOC_G_PARAMS
-BUZIOC_S_PARAMS
-
-Get and set the parameters of the buz. The user should always
-do a BUZIOC_G_PARAMS (with a struct buz_params) to obtain the default
-settings, change what he likes and then make a BUZIOC_S_PARAMS call.
-A typical application should at least set the members
-input, norm and decimation of the struct buz_params.
-For a full description of all members see "buz.h"
-
-BUZIOC_REQBUFS
-
-Before being able to capture/playback, the user has to request
-the buffers he is wanting to use. Fill the structure
-buz_requestbuffers with the size (recommended: 256*1024) and
-the number (recommended 32 up to 256). There are no such restrictions
-as for the Video for Linux buffers, you should LEAVE SUFFICIENT
-MEMORY for your system however, else strange things will happen ....
-On return, the buz_requestbuffers structure contains number and
-size of the actually allocated buffers.
-You should use these numbers for doing a mmap of the buffers
-into the user space.
-The BUZIOC_REQBUFS ioctl also makes it happen, that the next mmap
-maps the MJPEG buffer instead of the V4L buffers.
-
-BUZIOC_QBUF_CAPT
-BUZIOC_QBUF_PLAY
-
-Queue a buffer for capture or playback. The first call also starts
-streaming capture. When streaming capture is going on, you may
-only queue further buffers or issue syncs until streaming
-capture is switched off again with a argument of -1 to
-a BUZIOC_QBUF_CAPT/BUZIOC_QBUF_PLAY ioctl.
-
-BUZIOC_SYNC
-
-Issue this ioctl when all buffers are queued. This ioctl will
-block until the first buffer becomes free for saving its
-data to disk (after BUZIOC_QBUF_CAPT) or for reuse (after BUZIOC_QBUF_PLAY).
-
-BUZIOC_G_STATUS
-
-Get the status of the input lines (video source connected/norm).
-This ioctl may be subject to change.
-
-
-
-
-
-See the examples directory delivered with this driver
-for actual coding examples!
Copyright (C) 2000 Andrew Tridgell <tridge@samba.org>
This driver enable the use of video4linux compatible applications with the
-Motion Eye camera.
+Motion Eye camera. This driver requires the "Sony Vaio Programmable I/O
+Control Device" driver (which can be found in the "Character drivers"
+section of the kernel configuration utility) to be compiled and installed
+(using its "camera=1" parameter).
It can do at maximum 30 fps @ 320x240 or 15 fps @ 640x480.
L: linux-net@vger.kernel.org
S: Maintained
+NINJA SCSI-3 / NINJA SCSI-32Bi PCMCIA SCSI HOST ADAPTER DRIVER
+P: YOKOTA Hiroshi
+M: yokota@netlab.is.tsukuba.ac.jp
+W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
+S: Maintained
+
NON-IDE/NON-SCSI CDROM DRIVERS [GENERAL] (come on, crew - mark your responsibility)
P: Eberhard Moenkeberg
M: emoenke@gwdg.de
W: http://www.linuxtr.net
S: Maintained
+TOSHIBA SMM DRIVER
+P: Jonathan Buzzard
+M: jonathan@buzzard.org.uk
+L: tlinux-users@tce.toshiba-dme.co.jp
+W: http://www.buzzard.org.uk/toshiba/
+S: Maintained
+
TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
P: Ollie Lho
M: ollie@sis.com.tw
VERSION = 2
PATCHLEVEL = 4
-SUBLEVEL = 12
-EXTRAVERSION =
+SUBLEVEL = 13
+EXTRAVERSION =-pre1
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu
-LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
-
ifeq ($(CONFIG_CPU_26),y)
PROCESSOR = armo
ifeq ($(CONFIG_ROM_KERNEL),y)
endif
ifeq ($(CONFIG_ARCH_CLPS711X),y)
-TEXTADDR = 0xc0018000
+TEXTADDR = 0xc0028000
MACHINE = clps711x
endif
MACHINE = anakin
endif
-export LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS
+export MACHINE PROCESSOR TEXTADDR GZFLAGS
# Only set INCDIR if its not already defined above
# Grr, ?= doesn't work as all the other assignment operators do. Make bug?
SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe \
arch/arm/fastfpe
CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
-LIBS := arch/arm/lib/lib.a $(LIBS) $(LIBGCC)
+LIBS := arch/arm/lib/lib.a $(LIBS)
ifeq ($(CONFIG_FPE_NWFPE),y)
LIBS := arch/arm/nwfpe/math-emu.o $(LIBS)
ZBSSADDR = 0xf03e0000
endif
-ifeq ($(CONFIG_ARCH_P720T),y)
-ZTEXTADDR = 0xc0018000
+# The standard locations for stuff on CLPS711x type processors
+ifeq ($(CONFIG_ARCH_CLPS711X),y)
+ZTEXTADDR = 0xc0028000
PARAMS_PHYS = 0xc0000100
+endif
+
+# Should probably have some agreement on these...
+ifeq ($(CONFIG_ARCH_P720T),y)
INITRD_PHYS = 0xc0400000
INITRD_VIRT = 0xc0400000
endif
+ifeq ($(CONFIG_ARCH_CDB89712),y)
+INITRD_PHYS = 0x00700000
+INITRD_VIRT = 0xc0300000
+endif
ifeq ($(CONFIG_ARCH_SA1100),y)
ZTEXTADDR = 0xc0008000
ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
ZTEXTADDR = 0xC0200000
endif
+ifeq ($(CONFIG_SA1100_GRAPHICSMASTER),y)
+ ZTEXTADDR = 0xC0400000
+endif
+ifeq ($(CONFIG_SA1100_ADSBITSY),y)
+ ZTEXTADDR = 0xC0400000
+endif
ifeq ($(CONFIG_SA1100_YOPY),y)
ZTEXTADDR = 0x00080000
ZBSSADDR = 0xc0200000
#
ZSYSTEM =$(TOPDIR)/arch/arm/boot/zImage
-INITRD =$(ZSYSTEM)
ZLDFLAGS =-p -X -T bootp.lds \
--defsym initrd_addr=$(INITRD_PHYS) \
--defsym initrd_virt=$(INITRD_VIRT) \
* method by looking at the first word; this should either indicate a page
* size of 4K, 16K or 32K.
*/
- ldmia r13, {r5-r8} @ get size and addr of initrd
+ ldmia r13, {r4-r8} @ get size and addr of initrd
@ r5 = ATAG_INITRD
@ r6 = initrd start
@ r7 = initrd end
teq r9, #0x1000 @ 4K?
teqne r9, #0x4000 @ 16K?
teqne r9, #0x8000 @ 32K?
- beq no_taglist
+ beq param_struct
+
+ ldr r9, [r8, #4] @ get first tag
+ teq r9, r4
+ bne taglist @ ok, we have a tag list
+
+/*
+ * We didn't find a valid tag list - create one.
+ */
+ str r4, [r8, #4]
+ mov r4, #8
+ str r4, [r8, #0]
+ mov r4, #0
+ str r4, [r8, #8]
/*
* find the end of the tag list, and then add an INITRD tag on the end.
+ * If there is already an INITRD tag, then we ignore it; the last INITRD
+ * tag takes precidence.
*/
taglist: ldr r9, [r8, #0] @ tag length
teq r9, #0 @ last tag?
stmia r8, {r4, r5, r6, r7, r9}
mov pc, r12 @ call kernel
-no_taglist: add r8, r8, #16*4
+/*
+ * We found a param struct. Modify the param struct for the initrd
+ */
+param_struct: add r8, r8, #16*4
stmia r8, {r6,r7} @ save in param_struct
mov pc, r12 @ call kernel
.word kernel_addr
.word kernel_len
+ .word 0x54410001 @ r4 = ATAG_CORE
.word 0x54410005 @ r5 = ATAG_INITRD
.word initrd_virt @ r6
.word initrd_len @ r7
endif
ifeq ($(CONFIG_ARCH_SA1100),y)
-OBJS += head-sa1100.o setup-sa1100.o
+OBJS += head-sa1100.o
ifeq ($(CONFIG_SA1100_NANOENGINE),y)
OBJS += hw-bse.o
endif
SEDFLAGS += s/BSS_START/ALIGN(4)/
endif
+LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
+
all: vmlinux
vmlinux: $(HEAD) $(OBJS) piggy.o vmlinux.lds
@ Preserve r8/r7 i.e. kernel entry values
+#if defined(CONFIG_SA1100_GRAPHICSCLIENT) && !defined(CONFIG_ANGELBOOT)
+ mov r7, #MACH_TYPE_GRAPHICSCLIENT
+ mov r8, #0
+#endif
+#if defined(CONFIG_SA1100_GRAPHICSMASTER) && !defined(CONFIG_ANGELBOOT)
+ mov r7, #MACH_TYPE_GRAPHICSMASTER
+ mov r8, #0
+#endif
+#if defined(CONFIG_SA1100_ADSBITSY) && !defined(CONFIG_ANGELBOOT)
+ mov r7, #MACH_TYPE_ADSBITSY
+ mov r8, #0
+#endif
+
+#ifdef CONFIG_SA1100_PFS168
+ @ REVISIT_PFS168: Temporary until firmware updated to use assigned machine number
+ mov r7, #MACH_TYPE_PFS168
+#endif
+
#ifdef CONFIG_SA1100_VICTOR
teq r7, #MACH_TYPE_VICTOR
bne 10f
bic r0, r0, #0x1000 @ clear Icache
mcr p15, 0, r0, c1, c0, 0
-#ifdef CONFIG_ANGELBOOT
/*
* Pause for a short time so that we give enough time
* for the host to start a terminal up.
mov r0, #0x00200000
1: subs r0, r0, #1
bne 1b
-#endif
+++ /dev/null
-/*
- * linux/arch/arm/boot/compressed/setup-sa1100.S
- *
- * Copyright (C) 2000 Nicolas Pitre <nico@cam.org>
- *
- * SA1100 setup routines, to be used after BSS has been cleared.
- *
- * John G Dorsey <john+@cs.cmu.edu> 2000/05/25 :
- * Runtime test for Neponset added.
- */
-
-#include <linux/linkage.h>
-#include <linux/config.h>
-#include <asm/mach-types.h>
-
- .text
-
-GPIO_BASE: .long 0x90040000
-#define GPLR 0x00
-#define GPDR 0x04
-#define GPSR 0x08
-#define GAFR 0x1c
-
-PPC_BASE: .long 0x90060000
-#define PPAR 0x08
-
-IC_BASE: .long 0x90050000
-#define ICMR 0x04
-
-UART1_BASE: .long 0x80010000
-UART3_BASE: .long 0x80050000
-#define UTCR0 0x00
-#define UTCR1 0x04
-#define UTCR2 0x08
-#define UTCR3 0x0c
-#define UTSR0 0x1c
-#define UTSR1 0x20
-
-#ifndef CONFIG_SA1100_DEFAULT_BAUDRATE
-#define CONFIG_SA1100_DEFAULT_BAUDRATE 9600
-#endif
-
-#define BAUD_DIV ((230400/CONFIG_SA1100_DEFAULT_BAUDRATE)-1)
-
-SCR_loc: .long SYMBOL_NAME(SCR_value)
-#define GPIO_2_9 0x3fc
-
-
-/*
- * void sa1100_setup( int arch_id );
- *
- * This is called from decompress_kernel() with the arch_decomp_setup() macro.
- */
-
-ENTRY(sa1100_setup)
- mov r3, r0 @ keep machine type in r3
-
- @ Clear all interrupt sources
- ldr r0, IC_BASE
- mov r1, #0
- str r1, [r0, #ICMR]
-
-@ Read System Configuration "Register" for Assabet.
-@ (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
-@ User's Guide," p.4-9)
-
- teq r3, #MACH_TYPE_ASSABET
- bne skip_SCR
-
- ldr r0, GPIO_BASE
- ldr r1, [r0, #GPDR]
- and r1, r1, #GPIO_2_9
- str r1, [r0, #GPDR]
- mov r1, #GPIO_2_9
- str r1, [r0, #GPSR]
- ldr r1, [r0, #GPDR]
- bic r1, r1, #GPIO_2_9
- str r1, [r0, #GPDR]
-
- mov r2, #100
-1: ldr r1, [r0, #GPLR]
- subs r2, r2, #1
- bne 1b
-
- and r2, r1, #GPIO_2_9
- ldr r1, SCR_loc
- str r2, [r1]
-
- ldr r1, [r0, #GPDR]
- and r1, r1, #GPIO_2_9
- str r1, [r0, #GPDR]
-
-skip_SCR:
-
- @ Initialize UART (if bootloader has not done it yet)...
- teq r3, #MACH_TYPE_BRUTUS
- teqne r3, #MACH_TYPE_ASSABET
- teqne r3, #MACH_TYPE_ITSY
- teqne r3, #MACH_TYPE_OMNIMETER
- teqne r3, #MACH_TYPE_JORNADA720
- teqne r3, #MACH_TYPE_GRAPHICSCLIENT
- teqne r3, #MACH_TYPE_FLEXANET
- bne skip_uart
-
- @ UART3 if Assabet is used with Neponset
- teq r3, #MACH_TYPE_ASSABET @ if Assabet
- tsteq r2, #(1 << 9) @ ... and Neponset present
- ldreq r0, UART3_BASE
- beq uart_init
-
- @ UART3 on GraphicsClient
- teq r3, #MACH_TYPE_GRAPHICSCLIENT
- ldreq r0, UART3_BASE
- beq uart_init
-
- @ At least for Brutus, the UART1 is used through
- @ the alternate GPIO function...
- teq r3, #MACH_TYPE_BRUTUS
- bne uart1
-
-alt_GPIO_uart: ldr r0, GPIO_BASE
- ldr r1, [r0, #GPDR]
- bic r1, r1, #1<<15
- orr r1, r1, #1<<14
- str r1, [r0, #GPDR]
- ldr r1, [r0, #GAFR]
- orr r1, r1, #(1<<15)|(1<<14)
- str r1, [r0, #GAFR]
- ldr r0, PPC_BASE
- ldr r1, [r0, #PPAR]
- orr r1, r1, #1<<12
- str r1, [r0, #PPAR]
-
-uart1: ldr r0, UART1_BASE
-
-uart_init:
-1: ldr r1, [r0, #UTSR1]
- tst r1, #1<<0 @ TBY
- bne 1b
- mov r1, #0
- str r1, [r0, #UTCR3]
- mov r1, #0x08 @ 8N1
- str r1, [r0, #UTCR0]
- mov r1, #BAUD_DIV
- str r1, [r0, #UTCR2]
- mov r1, r1, lsr #8
- str r1, [r0, #UTCR1]
- mov r1, #0x03 @ RXE + TXE
- str r1, [r0, #UTCR3]
- mov r1, #0xff @ flush status reg
- str r1, [r0, #UTSR0]
-skip_uart:
-
- @ Extra specific setup calls
- @ The machine type is passed in r0
- mov r0, r3
-#ifdef CONFIG_SA1100_NANOENGINE
- teq r0, #MACH_TYPE_NANOENGINE
- beq SYMBOL_NAME(bse_setup)
-#endif
-
-out: mov pc, lr
-
define_bool CONFIG_UID16 y
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+define_bool CONFIG_GENERIC_BUST_SPINLOCK n
mainmenu_option next_comment
comment 'SA11x0 Implementations'
dep_bool ' Assabet' CONFIG_SA1100_ASSABET $CONFIG_ARCH_SA1100
dep_bool ' Include support for Neponset' CONFIG_ASSABET_NEPONSET $CONFIG_SA1100_ASSABET
+dep_bool ' ADS Bitsy' CONFIG_SA1100_ADSBITSY $CONFIG_ARCH_SA1100
dep_bool ' Brutus' CONFIG_SA1100_BRUTUS $CONFIG_ARCH_SA1100
dep_bool ' CerfBoard' CONFIG_SA1100_CERF $CONFIG_ARCH_SA1100
if [ "$CONFIG_SA1100_CERF" = "y" ]; then
bool ' 32MB Cerf support' CONFIG_SA1100_CERF_32MB
fi
-dep_bool ' Compaq iPAQ H3600 (Bitsy)' CONFIG_SA1100_BITSY $CONFIG_ARCH_SA1100
+dep_bool ' Compaq iPAQ H3600' CONFIG_SA1100_H3600 $CONFIG_ARCH_SA1100
#dep_bool ' Empeg' CONFIG_SA1100_EMPEG $CONFIG_ARCH_SA1100
dep_bool ' Extenex HandHeld Theater (Squashtail)' CONFIG_SA1100_EXTENEX1 $CONFIG_ARCH_SA1100
if [ "$CONFIG_SA1100_EXTENEX1" = "y" ]; then
dep_bool ' FlexaNet' CONFIG_SA1100_FLEXANET $CONFIG_ARCH_SA1100
dep_bool ' FreeBird-v1.1' CONFIG_SA1100_FREEBIRD $CONFIG_ARCH_SA1100
dep_bool ' GraphicsClient Plus' CONFIG_SA1100_GRAPHICSCLIENT $CONFIG_ARCH_SA1100
+dep_bool ' GraphicsMaster' CONFIG_SA1100_GRAPHICSMASTER $CONFIG_ARCH_SA1100
dep_bool ' HP Jornada 720' CONFIG_SA1100_JORNADA720 $CONFIG_ARCH_SA1100
dep_bool ' HuW WebPanel' CONFIG_SA1100_HUW_WEBPANEL $CONFIG_ARCH_SA1100
dep_bool ' Itsy' CONFIG_SA1100_ITSY $CONFIG_ARCH_SA1100
if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \
"$CONFIG_SA1100_JORNADA720" = "y" -o \
"$CONFIG_SA1100_PFS168" = "y" -o \
- "$CONFIG_SA1100_XP860" = "y" ]; then
+ "$CONFIG_SA1100_XP860" = "y" -o \
+ "$CONFIG_SA1100_GRAPHICSMASTER" = "y" -o \
+ "$CONFIG_SA1100_ADSBITSY" = "y" ]; then
define_bool CONFIG_SA1111 y
+ define_int CONFIG_FORCE_MAX_ZONEORDER 9
fi
endmenu
mainmenu_option next_comment
comment 'CLPS711X/EP721X Implementations'
+dep_bool ' CDB89712' CONFIG_ARCH_CDB89712 $CONFIG_ARCH_CLPS711X
+dep_bool ' CLEP7312' CONFIG_ARCH_CLEP7312 $CONFIG_ARCH_CLPS711X
+dep_bool ' EDB7211' CONFIG_ARCH_EDB7211 $CONFIG_ARCH_CLPS711X
dep_bool ' P720T' CONFIG_ARCH_P720T $CONFIG_ARCH_CLPS711X
+
+# XXX Maybe these should indicate register compatibility
+# instead of being mutually exclusive.
+if [ "$CONFIG_ARCH_EDB7211" = "y" ]; then
+ define_bool CONFIG_ARCH_EP7211 y
+else
+ define_bool CONFIG_ARCH_EP7211 n
+fi
+if [ "$CONFIG_ARCH_P720T" = "y" ]; then
+ define_bool CONFIG_ARCH_EP7212 y
+else
+ define_bool CONFIG_ARCH_EP7212 n
+fi
+
+if [ "$CONFIG_ARCH_EP7211" = "y" -o \
+ "$CONFIG_ARCH_EP7212" = "y" ]; then
+ bool ' EP72xx ROM boot' CONFIG_EP72XX_ROM_BOOT
+fi
endmenu
# Definitions to make life easier
fi
# ARM720T
-if [ "$CONFIG_ARCH_CLPS711X" = "y" -o "$CONFIG_ARCH_L7200" = "y" ]; then
+if [ "$CONFIG_ARCH_CLPS711X" = "y" -o \
+ "$CONFIG_ARCH_L7200" = "y" -o \
+ "$CONFIG_ARCH_CDB89712" = "y" ]; then
define_bool CONFIG_CPU_ARM720T y
else
if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
define_bool CONFIG_CPU_SA1100 n
fi
-#if [ "$CONFIG_CPU_32" = "y" ]; then
-# bool 'Support Thumb instructions' CONFIG_ARM_THUMB
-#fi
+if [ "$CONFIG_CPU_32" = "y" ]; then
+ dep_bool 'Support Thumb instructions (experimental)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
+fi
# Select various configuration options depending on the machine type
-if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
+if [ "$CONFIG_ARCH_EDB7211" = "y" -o \
+ "$CONFIG_ARCH_SA1100" = "y" ]; then
define_bool CONFIG_DISCONTIGMEM y
else
define_bool CONFIG_DISCONTIGMEM n
"$CONFIG_ARCH_SHARK" = "y" -o \
"$CONFIG_ARCH_CLPS7500" = "y" -o \
"$CONFIG_ARCH_EBSA110" = "y" -o \
+ "$CONFIG_ARCH_CDB89712" = "y" -o \
+ "$CONFIG_ARCH_EDB7211" = "y" -o \
"$CONFIG_ARCH_SA1100" = "y" ]; then
define_bool CONFIG_ISA y
else
bool 'System V IPC' CONFIG_SYSVIPC
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
bool 'Sysctl support' CONFIG_SYSCTL
+comment 'At least one math emulation must be selected'
tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE
dep_tristate 'FastFPE math emulation (experimental)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL
choice 'Kernel core (/proc/kcore) format' \
"$CONFIG_ARCH_PERSONAL_SERVER" = "y" -o \
"$CONFIG_ARCH_CATS" = "y" -o \
"$CONFIG_ARCH_P720T" = "y" -o \
+ "$CONFIG_ARCH_CDB89712" = "y" -o \
"$CONFIG_ARCH_ANAKIN" = "y" ]; then
string 'Default kernel command string' CONFIG_CMDLINE ""
fi
"$CONFIG_ARCH_CO285" = "y" -o \
"$CONFIG_ARCH_SA1100" = "y" -o \
"$CONFIG_ARCH_INTEGRATOR" = "y" -o \
+ "$CONFIG_ARCH_CDB89712" = "y" -o \
"$CONFIG_ARCH_P720T" = "y" ]; then
bool 'Timer and CPU usage LEDs' CONFIG_LEDS
if [ "$CONFIG_LEDS" = "y" ]; then
source drivers/ieee1394/Config.in
-source drivers/i2o/Config.in
+source drivers/message/i2o/Config.in
mainmenu_option next_comment
comment 'ISDN subsystem'
endmenu
fi
+source drivers/misc/Config.in
+
source drivers/usb/Config.in
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
export-objs := armksyms.o dma.o ecard.o fiq.o io.o oldlatches.o time.o
no-irq-arch := $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \
- $(CONFIG_ARCH_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
+ $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
$(CONFIG_ARCH_SA1100)
ifneq ($(findstring y,$(no-irq-arch)),y)
* compiler... (prototypes are not correct though, but that
* doesn't really matter since they're not versioned).
*/
-extern void __gcc_bcmp(void);
extern void __ashldi3(void);
extern void __ashrdi3(void);
-extern void __cmpdi2(void);
-extern void __divdi3(void);
extern void __divsi3(void);
extern void __lshrdi3(void);
-extern void __moddi3(void);
extern void __modsi3(void);
extern void __muldi3(void);
-extern void __negdi2(void);
extern void __ucmpdi2(void);
extern void __udivdi3(void);
extern void __udivmoddi4(void);
extern void __udivsi3(void);
-extern void __umoddi3(void);
extern void __umodsi3(void);
extern void ret_from_exception(void);
EXPORT_SYMBOL(uaccess_user);
#endif
+EXPORT_SYMBOL_NOVERS(__get_user_1);
+EXPORT_SYMBOL_NOVERS(__get_user_2);
+EXPORT_SYMBOL_NOVERS(__get_user_4);
+EXPORT_SYMBOL_NOVERS(__get_user_8);
+
+EXPORT_SYMBOL_NOVERS(__put_user_1);
+EXPORT_SYMBOL_NOVERS(__put_user_2);
+EXPORT_SYMBOL_NOVERS(__put_user_4);
+EXPORT_SYMBOL_NOVERS(__put_user_8);
+
/* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__gcc_bcmp);
EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__cmpdi2);
-EXPORT_SYMBOL_NOVERS(__divdi3);
EXPORT_SYMBOL_NOVERS(__divsi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__moddi3);
EXPORT_SYMBOL_NOVERS(__modsi3);
EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__negdi2);
EXPORT_SYMBOL_NOVERS(__ucmpdi2);
EXPORT_SYMBOL_NOVERS(__udivdi3);
EXPORT_SYMBOL_NOVERS(__udivmoddi4);
EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
EXPORT_SYMBOL_NOVERS(__umodsi3);
/* bitops */
if (dev) {
for (i = 0; i < 3; i++) {
- bus->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
- bus->resource[i]->name = bus->name;
+ if(root->resource[i]) {
+ bus->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ bus->resource[i]->end = root->resource[i]->end;
+ bus->resource[i]->name = bus->name;
+ }
}
bus->resource[0]->flags |= pci_bridge_check_io(dev);
bus->resource[1]->flags |= IORESOURCE_MEM;
* published by the Free Software Foundation.
*
* We keep the old params compatibility cruft in one place (here)
- * so we don't end up with lots of
+ * so we don't end up with lots of mess around other places.
*/
#include <linux/config.h>
#include <linux/types.h>
void __init isa_init_dma(dma_t *dma)
{
- int dmac_found;
-
+ /*
+ * Try to autodetect presence of an ISA DMA controller.
+ * We do some minimal initialisation, and check that
+ * channel 0's DMA address registers are writeable.
+ */
outb(0xff, 0x0d);
outb(0xff, 0xda);
+ /*
+ * Write high and low address, and then read them back
+ * in the same order.
+ */
outb(0x55, 0x00);
outb(0xaa, 0x00);
- dmac_found = inb(0x00) == 0x55 && inb(0x00) == 0xaa;
-
- if (dmac_found) {
+ if (inb(0) == 0x55 && inb(0) == 0xaa) {
int channel, i;
for (channel = 0; channel < 8; channel++) {
.endm
#elif defined(CONFIG_ARCH_L7200)
+#include <asm/hardware.h>
.equ irq_base_addr, IO_BASE_2
* This routine must not corrupt r9
*/
#ifdef MULTI_CPU
- ldr r2, .LCprocfns
- mov lr, pc
+ ldr r2, .LCprocfns @ pass r0, r3 to
+ mov lr, pc @ processor code
ldr pc, [r2] @ call processor specific code
#else
bl cpu_data_abort
.align 5
__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia sp, {r0 - r12} @ save r0 - r12
- ldr r4, .LCabt
- add r3, sp, #S_PC
- ldmia r4, {r0 - r2} @ Get USR pc, cpsr
- stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0
- stmdb r3, {sp, lr}^
- alignment_trap r4, r7, __temp_abt
+ ldr r7, .LCabt
+ add r5, sp, #S_PC
+ ldmia r7, {r0, r3, r4} @ Get USR pc, cpsr
+ stmia r5, {r0, r3, r4} @ Save USR pc, cpsr, old_r0
+ stmdb r5, {sp, lr}^
+ alignment_trap r7, r7, __temp_abt
zero_fp
#ifdef MULTI_CPU
- ldr r2, .LCprocfns
- mov lr, pc
+ ldr r2, .LCprocfns @ pass r0, r3 to
+ mov lr, pc @ processor code
ldr pc, [r2] @ call processor specific code
#else
bl cpu_data_abort
.align 5
ENTRY(vector_swi)
save_user_regs
- mask_pc lr, lr
zero_fp
- ldr scno, [lr, #-4] @ get SWI instruction
+ get_scno
arm710_bug_check scno, ip
#ifdef CONFIG_ALIGNMENT_TRAP
stmia sp, {r0 - r12} @ Calling r0 - r12
add r8, sp, #S_PC
stmdb r8, {sp, lr}^ @ Calling sp, lr
- mrs r7, spsr
+ mrs r8, spsr @ called from non-FIQ mode, so ok.
str lr, [sp, #S_PC] @ Save calling PC
- str r7, [sp, #S_PSR] @ Save CPSR
+ str r8, [sp, #S_PSR] @ Save CPSR
str r0, [sp, #S_OLD_R0] @ Save OLD_R0
.endm
#endif
+
/*
* These are the registers used in the syscall handler, and allow us to
- * have in theory up to 7 arguments to a function. Note that tbl == why
- * is intentional.
+ * have in theory up to 7 arguments to a function - r0 to r6.
+ *
+ * r7 is reserved for the system call number for thumb mode.
+ *
+ * Note that tbl == why is intentional.
*
* We must set at least "tsk" and "why" when calling ret_with_reschedule.
*/
-scno .req r9 @ syscall number
+scno .req r7 @ syscall number
tbl .req r8 @ syscall table pointer
why .req r8 @ Linux syscall (!= 0)
-tsk .req r7 @ current task
+tsk .req r9 @ current task
+
+/*
+ * Get the system call number.
+ */
+ .macro get_scno
+#ifdef CONFIG_ARM_THUMB
+ tst r8, #T_BIT @ this is SPSR from save_user_regs
+ addne scno, r7, #OS_NUMBER << 20 @ put OS number in
+ ldreq scno, [lr, #-4]
+#else
+ mask_pc lr, lr
+ ldr scno, [lr, #-4] @ get SWI instruction
+#endif
+ .endm
mov r7, #0 @ unknown architecture
mov pc, lr
2: ldmib r4, {r5, r6, r7} @ found, get results
- mov r7, r7, lsr #18 @ pagetable byte offset
mov pc, lr
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct resource *res;
int i;
- kernel_code.start = __virt_to_bus(init_mm.start_code);
- kernel_code.end = __virt_to_bus(init_mm.end_code - 1);
- kernel_data.start = __virt_to_bus(init_mm.end_code);
- kernel_data.end = __virt_to_bus(init_mm.brk - 1);
+ kernel_code.start = __virt_to_phys(init_mm.start_code);
+ kernel_code.end = __virt_to_phys(init_mm.end_code - 1);
+ kernel_data.start = __virt_to_phys(init_mm.end_code);
+ kernel_data.end = __virt_to_phys(init_mm.brk - 1);
for (i = 0; i < mi->nr_banks; i++) {
unsigned long virt_start, virt_end;
#endif
}
-int get_cpuinfo(char * buffer)
+static const char *hwcap_str[] = {
+ "swp",
+ "half",
+ "thumb",
+ "26bit",
+ "fastmult",
+ "fpa",
+ "vfp",
+ "edsp",
+ NULL
+};
+
+/*
+ * get_cpuinfo - Get information on one CPU for use by the procfs.
+ *
+ * Prints info on the next CPU into buffer. Beware, doesn't check for
+ * buffer overflow. Current implementation of procfs assumes that the
+ * resulting data is <= 1K.
+ *
+ * Args:
+ * buffer -- you guessed it, the data buffer
+ * cpu_np -- Input: next cpu to get (start at 0). Output: Updated.
+ *
+ * Returns number of bytes written to buffer.
+ */
+
+int get_cpuinfo(char *buffer, unsigned *cpu_np)
{
char *p = buffer;
+ unsigned n;
+ int i;
+
+ /* No SMP at the moment, so just toggle 0/1 */
+ n = *cpu_np;
+ *cpu_np = 1;
+ if (n != 0) {
+ return (0);
+ }
p += sprintf(p, "Processor\t: %s %s rev %d (%s)\n",
proc_info.manufacturer, proc_info.cpu_name,
loops_per_jiffy / (500000/HZ),
(loops_per_jiffy / (5000/HZ)) % 100);
+ /* dump out the processor features */
+ p += sprintf(p, "Features\t: ");
+
+ for (i = 0; hwcap_str[i]; i++)
+ if (elf_hwcap & (1 << i))
+ p += sprintf(p, "%s ", hwcap_str[i]);
+
+ p += sprintf(p, "\n\n");
+
p += sprintf(p, "Hardware\t: %s\n", machine_name);
p += sprintf(p, "Revision\t: %04x\n",
/*
* linux/arch/arm/kernel/signal.c
*
- * Copyright (C) 1995, 1996 Russell King
+ * Copyright (C) 1995-2001 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <linux/ptrace.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
+#include <linux/personality.h>
#include <linux/tty.h>
+#include <linux/elf.h>
#include <asm/pgalloc.h>
#include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn))
-#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn))
+/*
+ * For ARM syscalls, we encode the syscall number into the instruction.
+ */
+#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn))
+#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn))
+
+/*
+ * For Thumb syscalls, we pass the syscall number via r7. We therefore
+ * need two 16-bit instructions.
+ */
+#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
+#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
+
+static const unsigned long retcodes[4] = {
+ SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
+ SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
+};
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
sigset_t set;
/*
- * Since we stacked the signal on a word boundary,
+ * Since we stacked the signal on a 64-bit boundary,
* then 'sp' should be word aligned here. If it's
* not, then the user is trying to mess with us.
*/
- if (regs->ARM_sp & 3)
+ if (regs->ARM_sp & 7)
goto badframe;
frame = (struct sigframe *)regs->ARM_sp;
sigset_t set;
/*
- * Since we stacked the signal on a word boundary,
+ * Since we stacked the signal on a 64-bit boundary,
* then 'sp' should be word aligned here. If it's
* not, then the user is trying to mess with us.
*/
- if (regs->ARM_sp & 3)
+ if (regs->ARM_sp & 7)
goto badframe;
frame = (struct rt_sigframe *)regs->ARM_sp;
return err;
}
-static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
- unsigned long framesize)
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
{
unsigned long sp = regs->ARM_sp;
sp = current->sas_ss_sp + current->sas_ss_size;
/*
- * No matter what happens, 'sp' must be word
- * aligned otherwise nasty things could happen
+ * ATPCS B01 mandates 8-byte alignment
*/
- /* ATPCS B01 mandates 8-byte alignment */
return (void *)((sp - framesize) & ~7);
}
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
+static int
+setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+ unsigned long *rc, void *frame, int usig)
{
- struct sigframe *frame;
+ unsigned long handler = (unsigned long)ka->sa.sa_handler;
unsigned long retcode;
- int err = 0;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- goto segv_and_exit;
-
- err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
+ int thumb = 0;
+#ifdef CONFIG_CPU_32
+ unsigned long cpsr = regs->ARM_cpsr;
- if (_NSIG_WORDS > 1) {
- err |= __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ /*
+ * Maybe we need to deliver a 32-bit signal to a 26-bit task.
+ */
+ if (ka->sa.sa_flags & SA_THIRTYTWO)
+ cpsr = (cpsr & ~MODE_MASK) | USR_MODE;
+
+#ifdef CONFIG_ARM_THUMB
+ if (elf_hwcap & HWCAP_THUMB) {
+ /*
+ * The LSB of the handler determines if we're going to
+ * be using THUMB or ARM mode for this signal handler.
+ */
+ thumb = handler & 1;
+
+ if (thumb)
+ cpsr |= T_BIT;
+ else
+ cpsr &= ~T_BIT;
}
+#endif
+#endif
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
retcode = (unsigned long)ka->sa.sa_restorer;
} else {
- retcode = (unsigned long)&frame->retcode;
- __put_user_error(SWI_SYS_SIGRETURN, &frame->retcode, err);
- flush_icache_range(retcode, retcode + 4);
- }
+ unsigned int idx = thumb;
- if (err)
- goto segv_and_exit;
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ idx += 2;
- if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32)
- regs->ARM_r0 = current->exec_domain->signal_invmap[sig];
- else
- regs->ARM_r0 = sig;
+ if (__put_user(retcodes[idx], rc))
+ return 1;
+
+ flush_icache_range((unsigned long)rc,
+ (unsigned long)(rc + 1));
+
+ retcode = ((unsigned long)rc) + thumb;
+ }
+
+ regs->ARM_r0 = usig;
regs->ARM_sp = (unsigned long)frame;
regs->ARM_lr = retcode;
- regs->ARM_pc = (unsigned long)ka->sa.sa_handler;
-#if defined(CONFIG_CPU_32)
- /* Maybe we need to deliver a 32-bit signal to a 26-bit task. */
- if (ka->sa.sa_flags & SA_THIRTYTWO)
- regs->ARM_cpsr = USR_MODE;
+ regs->ARM_pc = handler & (thumb ? ~1 : ~3);
+
+#ifdef CONFIG_CPU_32
+ regs->ARM_cpsr = cpsr;
#endif
- if (valid_user_regs(regs))
- return;
-segv_and_exit:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ return 0;
}
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int
+setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs)
{
- struct rt_sigframe *frame;
- unsigned long retcode;
+ struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ return 1;
+
+ err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
+
+ if (_NSIG_WORDS > 1) {
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
+ }
+
+ if (err == 0)
+ err = setup_return(regs, ka, &frame->retcode, frame, usig);
+
+ return err;
+}
+
+static int
+setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
+ int err = 0;
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- goto segv_and_exit;
+ return 1;
__put_user_error(&frame->info, &frame->pinfo, err);
__put_user_error(&frame->uc, &frame->puc, err);
regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- retcode = (unsigned long)ka->sa.sa_restorer;
- } else {
- retcode = (unsigned long)&frame->retcode;
- __put_user_error(SWI_SYS_RT_SIGRETURN, &frame->retcode, err);
- flush_icache_range(retcode, retcode + 4);
+ if (err == 0)
+ err = setup_return(regs, ka, &frame->retcode, frame, usig);
+
+ if (err == 0) {
+ /*
+ * For realtime signals we must also set the second and third
+ * arguments for the signal handler.
+ * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
+ */
+ regs->ARM_r1 = (unsigned long)frame->pinfo;
+ regs->ARM_r2 = (unsigned long)frame->puc;
}
- if (err)
- goto segv_and_exit;
-
- if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32)
- regs->ARM_r0 = current->exec_domain->signal_invmap[sig];
- else
- regs->ARM_r0 = sig;
-
- /*
- * For realtime signals we must also set the second and third
- * arguments for the signal handler.
- * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
- */
- regs->ARM_r1 = (unsigned long)frame->pinfo;
- regs->ARM_r2 = (unsigned long)frame->puc;
-
- regs->ARM_sp = (unsigned long)frame;
- regs->ARM_lr = retcode;
- regs->ARM_pc = (unsigned long)ka->sa.sa_handler;
-#if defined(CONFIG_CPU_32)
- /* Maybe we need to deliver a 32-bit signal to a 26-bit task. */
- if (ka->sa.sa_flags & SA_THIRTYTWO)
- regs->ARM_cpsr = USR_MODE;
-#endif
- if (valid_user_regs(regs))
- return;
-
-segv_and_exit:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ return err;
}
/*
handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
- /* Set up the stack frame */
+ struct task_struct *tsk = current;
+ int usig = sig;
+ int ret;
+
+ /*
+ * translate the signal
+ */
+ if (usig < 32 && tsk->exec_domain && tsk->exec_domain->signal_invmap)
+ usig = tsk->exec_domain->signal_invmap[usig];
+
+ /*
+ * Set up the stack frame
+ */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(usig, ka, info, oldset, regs);
else
- setup_frame(sig, ka, oldset, regs);
-
- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
+ ret = setup_frame(usig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(¤t->sigmask_lock);
- sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
- sigaddset(¤t->blocked,sig);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
+ /*
+ * Check that the resulting registers are actually sane.
+ */
+ ret |= !valid_user_regs(regs);
+
+ if (ret == 0) {
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&tsk->sigmask_lock);
+ sigorsets(&tsk->blocked, &tsk->blocked,
+ &ka->sa.sa_mask);
+ sigaddset(&tsk->blocked, sig);
+ recalc_sigpending(tsk);
+ spin_unlock_irq(&tsk->sigmask_lock);
+ }
+ return;
}
+
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, tsk);
}
/*
#include <asm/hardware.h>
extern int setup_arm_irq(int, struct irqaction *);
-extern void setup_timer(void);
extern rwlock_t xtime_lock;
extern unsigned long wall_jiffies;
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/elf.h>
+#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/atomic.h>
printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, 4096+(unsigned long)tsk);
- if (!user_mode(regs)) {
+ if (!user_mode(regs) || in_interrupt()) {
mm_segment_t fs;
/*
asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode)
{
- unsigned long addr;
+ unsigned long *pc;
siginfo_t info;
/*
* whether we're in Thumb mode or not.
*/
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
- addr = instruction_pointer(regs);
+ pc = (unsigned long *)instruction_pointer(regs);
#ifdef CONFIG_DEBUG_USER
- printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
- current->comm, current->pid, addr);
+ printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
+ current->comm, current->pid, pc);
dump_instr(regs);
#endif
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = ILL_ILLOPC;
- info.si_addr = (void *)addr;
+ info.si_addr = pc;
force_sig_info(SIGILL, &info, current);
copy_page.o delay.o findbit.o memchr.o memcpy.o \
memset.o memzero.o setbit.o strncpy_from_user.o \
strnlen_user.o strchr.o strrchr.o testchangebit.o \
- testclearbit.o testsetbit.o uaccess.o
+ testclearbit.o testsetbit.o uaccess.o getuser.o \
+ putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+ ucmpdi2.o udivdi3.o lib1funcs.o
obj-m :=
obj-n :=
+obj-$(CONFIG_VT)+= kbd.o
+
obj-arc := ecard.o io-acorn.o floppydma.o
obj-rpc := ecard.o io-acorn.o floppydma.o
obj-clps7500 := io-acorn.o
obj-l7200 := io-acorn.o
obj-shark := io-shark.o
+obj-edb7211 := io-acorn.o
obj-y += $(obj-$(MACHINE))
--- /dev/null
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License.
+ */
+/* support functions required by the kernel. based on code from gcc-2.95.3 */
+/* I Molton 29/07/01 */
+
+#include "gcclib.h"
+
+DItype
+__ashldi3 (DItype u, word_type b)
+{
+ DIunion w;
+ word_type bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0)
+ {
+ w.s.low = 0;
+ w.s.high = (USItype)uu.s.low << -bm;
+ }
+ else
+ {
+ USItype carries = (USItype)uu.s.low >> bm;
+ w.s.low = (USItype)uu.s.low << b;
+ w.s.high = ((USItype)uu.s.high << b) | carries;
+ }
+
+ return w.ll;
+}
+
--- /dev/null
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License.
+ */
+/* support functions required by the kernel. based on code from gcc-2.95.3 */
+/* I Molton 29/07/01 */
+
+#include "gcclib.h"
+
+DItype
+__ashrdi3 (DItype u, word_type b)
+{
+ DIunion w;
+ word_type bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0)
+ {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
+ w.s.low = uu.s.high >> -bm;
+ }
+ else
+ {
+ USItype carries = (USItype)uu.s.high << bm;
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((USItype)uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
--- /dev/null
+/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
+/* I Molton 29/07/01 */
+
+#define BITS_PER_UNIT 8
+#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef int word_type __attribute__ ((mode (__word__)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+#if 0 /* FIXME: endian test here!!! */
+ struct DIstruct {SItype high, low;};
+#else
+ struct DIstruct {SItype low, high;};
+#endif
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
--- /dev/null
+/*
+ * linux/arch/arm/lib/getuser.S
+ *
+ * Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
+ *
+ * These functions have a non-standard call interface to make them more
+ * efficient, especially as they return an error value in addition to
+ * the "real" return value.
+ *
+ * __get_user_X
+ *
+ * Inputs: r0 contains the address
+ * Outputs: r0 is the error code
+ * r1, r2 contains the zero-extended value
+ * lr corrupted
+ *
+ * No other registers must be altered. (see include/asm-arm/uaccess.h
+ * for specific ASM register usage).
+ *
+ * Note that ADDR_LIMIT is either 0 or 0xc0000000.
+ * Note also that it is intended that __get_user_bad is not global.
+ */
+#include <asm/constants.h>
+
+ .global __get_user_1
+__get_user_1:
+ bic r1, sp, #0x1f00
+ bic r1, r1, #0x00ff
+ ldr r1, [r1, #TSK_ADDR_LIMIT]
+ sub r1, r1, #1
+ cmp r0, r1
+1: ldrlsbt r1, [r0]
+ movls r0, #0
+ movls pc, lr
+ b __get_user_bad
+
+ .global __get_user_2
+__get_user_2:
+ bic r2, sp, #0x1f00
+ bic r2, r2, #0x00ff
+ ldr r2, [r2, #TSK_ADDR_LIMIT]
+ sub r2, r2, #2
+ cmp r0, r2
+2: ldrlsbt r1, [r0], #1
+3: ldrlsbt r2, [r0]
+ orrls r1, r1, r2, lsl #8
+ movls r0, #0
+ movls pc, lr
+ b __get_user_bad
+
+ .global __get_user_4
+__get_user_4:
+ bic r1, sp, #0x1f00
+ bic r1, r1, #0x00ff
+ ldr r1, [r1, #TSK_ADDR_LIMIT]
+ sub r1, r1, #4
+ cmp r0, r1
+4: ldrlst r1, [r0]
+ movls r0, #0
+ movls pc, lr
+ b __get_user_bad
+
+ .global __get_user_8
+__get_user_8:
+ bic r2, sp, #0x1f00
+ bic r2, r2, #0x00ff
+ ldr r2, [r2, #TSK_ADDR_LIMIT]
+ sub r2, r2, #8
+ cmp r0, r2
+5: ldrlst r1, [r0], #4
+6: ldrlst r2, [r0]
+ movls r0, #0
+ movls pc, lr
+
+ /* fall through */
+
+__get_user_bad:
+ mov r2, #0
+ mov r1, #0
+ mov r0, #-14
+ mov pc, lr
+
+.section __ex_table, "a"
+ .long 1b, __get_user_bad
+ .long 2b, __get_user_bad
+ .long 3b, __get_user_bad
+ .long 4b, __get_user_bad
+ .long 5b, __get_user_bad
+ .long 6b, __get_user_bad
+.previous
--- /dev/null
+#include <linux/config.h>
+#include <linux/kd.h>
+
+int (*k_setkeycode)(unsigned int, unsigned int);
+int (*k_getkeycode)(unsigned int);
+int (*k_translate)(unsigned char, unsigned char *, char);
+char (*k_unexpected_up)(unsigned char);
+void (*k_leds)(unsigned char);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+int k_sysrq_key;
+unsigned char *k_sysrq_xlate;
+#endif
--- /dev/null
+@ libgcc1 routines for ARM cpu.
+@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+
+/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License.
+ */
+/* This code is derived from gcc 2.95.3 */
+/* I Molton 29/07/01 */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <linux/config.h>
+
+#ifdef CONFIG_CPU_26
+#define RET movs
+#define RETc(x) mov##x##s
+#define RETCOND ^
+#else
+#define RET mov
+#define RETc(x) mov##x
+#define RETCOND
+#endif
+
+dividend .req r0
+divisor .req r1
+result .req r2
+overdone .req r2
+curbit .req r3
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+
+ENTRY(__udivsi3)
+ cmp divisor, #0
+ beq Ldiv0
+ mov curbit, #1
+ mov result, #0
+ cmp dividend, divisor
+ bcc Lgot_result_udivsi3
+1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc 1b
+
+2:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc 2b
+
+3:
+ @ Test for possible subtractions, and note which bits
+ @ are done in the result. On the final pass, this may subtract
+ @ too much from the dividend, but the result will be ok, since the
+ @ "bit" will have been shifted out at the bottom.
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ orrcs result, result, curbit
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs result, result, curbit, lsr #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs result, result, curbit, lsr #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs result, result, curbit, lsr #3
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne 3b
+Lgot_result_udivsi3:
+ mov r0, result
+ RET pc, lr
+
+Ldiv0:
+ str lr, [sp, #-4]!
+ bl __div0
+ mov r0, #0 @ about as wrong as it could be
+ ldmia sp!, {pc}RETCOND
+
+/* __umodsi3 ----------------------- */
+
+ENTRY(__umodsi3)
+ cmp divisor, #0
+ beq Ldiv0
+ mov curbit, #1
+ cmp dividend, divisor
+ RETc(cc) pc, lr
+1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc 1b
+
+2:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc 2b
+
+3:
+ @ Test for possible subtractions. On the final pass, this may
+ @ subtract too much from the dividend, so keep track of which
+ @ subtractions are done, we can fix them up afterwards...
+ mov overdone, #0
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs overdone, overdone, curbit, ror #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs overdone, overdone, curbit, ror #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs overdone, overdone, curbit, ror #3
+ mov ip, curbit
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne 3b
+
+ @ Any subtractions that we should not have done will be recorded in
+ @ the top three bits of "overdone". Exactly which were not needed
+ @ are governed by the position of the bit, stored in ip.
+ @ If we terminated early, because dividend became zero,
+ @ then none of the below will match, since the bit in ip will not be
+ @ in the bottom nibble.
+ ands overdone, overdone, #0xe0000000
+ RETc(eq) pc, lr @ No fixups needed
+ tst overdone, ip, ror #3
+ addne dividend, dividend, divisor, lsr #3
+ tst overdone, ip, ror #2
+ addne dividend, dividend, divisor, lsr #2
+ tst overdone, ip, ror #1
+ addne dividend, dividend, divisor, lsr #1
+ RET pc, lr
+
+ENTRY(__divsi3)
+ eor ip, dividend, divisor @ Save the sign of the result.
+ mov curbit, #1
+ mov result, #0
+ cmp divisor, #0
+ rsbmi divisor, divisor, #0 @ Loops below use unsigned.
+ beq Ldiv0
+ cmp dividend, #0
+ rsbmi dividend, dividend, #0
+ cmp dividend, divisor
+ bcc Lgot_result_divsi3
+
+1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc 1b
+
+2:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc 2b
+
+3:
+ @ Test for possible subtractions, and note which bits
+ @ are done in the result. On the final pass, this may subtract
+ @ too much from the dividend, but the result will be ok, since the
+ @ "bit" will have been shifted out at the bottom.
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ orrcs result, result, curbit
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs result, result, curbit, lsr #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs result, result, curbit, lsr #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs result, result, curbit, lsr #3
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne 3b
+Lgot_result_divsi3:
+ mov r0, result
+ cmp ip, #0
+ rsbmi r0, r0, #0
+ RET pc, lr
+
+ENTRY(__modsi3)
+ mov curbit, #1
+ cmp divisor, #0
+ rsbmi divisor, divisor, #0 @ Loops below use unsigned.
+ beq Ldiv0
+ @ Need to save the sign of the dividend, unfortunately, we need
+ @ ip later on; this is faster than pushing lr and using that.
+ str dividend, [sp, #-4]!
+ cmp dividend, #0
+ rsbmi dividend, dividend, #0
+ cmp dividend, divisor
+ bcc Lgot_result_modsi3
+
+1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc 1b
+
+2:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc 2b
+
+3:
+ @ Test for possible subtractions. On the final pass, this may
+ @ subtract too much from the dividend, so keep track of which
+ @ subtractions are done, we can fix them up afterwards...
+ mov overdone, #0
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs overdone, overdone, curbit, ror #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs overdone, overdone, curbit, ror #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs overdone, overdone, curbit, ror #3
+ mov ip, curbit
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne 3b
+
+ @ Any subtractions that we should not have done will be recorded in
+ @ the top three bits of "overdone". Exactly which were not needed
+ @ are governed by the position of the bit, stored in ip.
+ @ If we terminated early, because dividend became zero,
+ @ then none of the below will match, since the bit in ip will not be
+ @ in the bottom nibble.
+ ands overdone, overdone, #0xe0000000
+ beq Lgot_result_modsi3
+ tst overdone, ip, ror #3
+ addne dividend, dividend, divisor, lsr #3
+ tst overdone, ip, ror #2
+ addne dividend, dividend, divisor, lsr #2
+ tst overdone, ip, ror #1
+ addne dividend, dividend, divisor, lsr #1
+Lgot_result_modsi3:
+ ldr ip, [sp], #4
+ cmp ip, #0
+ rsbmi dividend, dividend, #0
+ RET pc, lr
--- /dev/null
+/* longlong.h -- based on code from gcc-2.95.3
+
+ definitions for mixed size 32/64 bit arithmetic.
+ Copyright (C) 1991, 92, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc.
+
+ This definition file is free software; you can redistribute it
+ and/or modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2, or (at your option) any later version.
+
+ This definition file is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Borrowed from GCC 2.95.3, I Molton 29/07/01 */
+
+#ifndef SI_TYPE_SIZE
+#define SI_TYPE_SIZE 32
+#endif
+
+#define __BITS4 (SI_TYPE_SIZE / 4)
+#define __ll_B (1L << (SI_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
+#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+
+/* Define auxiliary asm macros.
+
+ 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
+ multiplies two USItype integers MULTIPLER and MULTIPLICAND,
+ and generates a two-part USItype product in HIGH_PROD and
+ LOW_PROD.
+
+ 2) __umulsidi3(a,b) multiplies two USItype integers A and B,
+ and returns a UDItype product. This is just a variant of umul_ppmm.
+
+ 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator) divides a two-word unsigned integer, composed by the
+ integers HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and
+ places the quotient in QUOTIENT and the remainder in REMAINDER.
+ HIGH_NUMERATOR must be less than DENOMINATOR for correct operation.
+ If, in addition, the most significant bit of DENOMINATOR must be 1,
+ then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1.
+
+ 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator). Like udiv_qrnnd but the numbers are signed. The
+ quotient is rounded towards 0.
+
+ 5) count_leading_zeros(count, x) counts the number of zero-bits from
+ the msb to the first non-zero bit. This is the number of steps X
+ needs to be shifted left to set the msb. Undefined for X == 0.
+
+ 6) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+ high_addend_2, low_addend_2) adds two two-word unsigned integers,
+ composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and
+ LOW_ADDEND_2 respectively. The result is placed in HIGH_SUM and
+ LOW_SUM. Overflow (i.e. carry out) is not stored anywhere, and is
+ lost.
+
+ 7) sub_ddmmss(high_difference, low_difference, high_minuend,
+ low_minuend, high_subtrahend, low_subtrahend) subtracts two
+ two-word unsigned integers, composed by HIGH_MINUEND_1 and
+ LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and LOW_SUBTRAHEND_2
+ respectively. The result is placed in HIGH_DIFFERENCE and
+ LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
+ and is lost.
+
+ If any of these macros are left undefined for a particular CPU,
+ C macros are used. */
+
+#if defined (__arm__)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("adds %1, %4, %5
+ adc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subs %1, %4, %5
+ sbc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)))
+#define umul_ppmm(xh, xl, a, b) \
+{register USItype __t0, __t1, __t2; \
+ __asm__ ("%@ Inlined umul_ppmm
+ mov %2, %5, lsr #16
+ mov %0, %6, lsr #16
+ bic %3, %5, %2, lsl #16
+ bic %4, %6, %0, lsl #16
+ mul %1, %3, %4
+ mul %4, %2, %4
+ mul %3, %0, %3
+ mul %0, %2, %0
+ adds %3, %4, %3
+ addcs %0, %0, #65536
+ adds %1, %1, %3, lsl #16
+ adc %0, %0, %3, lsr #16" \
+ : "=&r" ((USItype) (xh)), \
+ "=r" ((USItype) (xl)), \
+ "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
+ : "r" ((USItype) (a)), \
+ "r" ((USItype) (b)));}
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+#endif /* __arm__ */
+
+#define __umulsidi3(u, v) \
+ ({DIunion __w; \
+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
+ __w.ll; })
+
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+ do { \
+ USItype __d1, __d0, __q1, __q0; \
+ USItype __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (USItype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (USItype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (USItype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+
+extern const UQItype __clz_tab[];
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __xr = (x); \
+ USItype __a; \
+ \
+ if (SI_TYPE_SIZE <= 32) \
+ { \
+ __a = __xr < ((USItype)1<<2*__BITS4) \
+ ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
+ : (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
+ } \
+ else \
+ { \
+ for (__a = SI_TYPE_SIZE - 8; __a > 0; __a -= 8) \
+ if (((__xr >> __a) & 0xff) != 0) \
+ break; \
+ } \
+ \
+ (count) = SI_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
+ } while (0)
--- /dev/null
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License.
+ */
+/* support functions required by the kernel. based on code from gcc-2.95.3 */
+/* I Molton 29/07/01 */
+
+#include "gcclib.h"
+
+DItype
+__lshrdi3 (DItype u, word_type b)
+{
+ DIunion w;
+ word_type bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0)
+ {
+ w.s.high = 0;
+ w.s.low = (USItype)uu.s.high >> -bm;
+ }
+ else
+ {
+ USItype carries = (USItype)uu.s.high << bm;
+ w.s.high = (USItype)uu.s.high >> b;
+ w.s.low = ((USItype)uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+
--- /dev/null
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License.
+ */
+/* support functions required by the kernel. based on code from gcc-2.95.3 */
+/* I Molton 29/07/01 */
+
+#include "gcclib.h"
+
+#define umul_ppmm(xh, xl, a, b) \
+{register USItype __t0, __t1, __t2; \
+ __asm__ ("%@ Inlined umul_ppmm
+ mov %2, %5, lsr #16
+ mov %0, %6, lsr #16
+ bic %3, %5, %2, lsl #16
+ bic %4, %6, %0, lsl #16
+ mul %1, %3, %4
+ mul %4, %2, %4
+ mul %3, %0, %3
+ mul %0, %2, %0
+ adds %3, %4, %3
+ addcs %0, %0, #65536
+ adds %1, %1, %3, lsl #16
+ adc %0, %0, %3, lsr #16" \
+ : "=&r" ((USItype) (xh)), \
+ "=r" ((USItype) (xl)), \
+ "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
+ : "r" ((USItype) (a)), \
+ "r" ((USItype) (b)));}
+
+
+#define __umulsidi3(u, v) \
+ ({DIunion __w; \
+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
+ __w.ll; })
+
+
+DItype
+__muldi3 (DItype u, DItype v)
+{
+ DIunion w;
+ DIunion uu, vv;
+
+ uu.ll = u,
+ vv.ll = v;
+
+ w.ll = __umulsidi3 (uu.s.low, vv.s.low);
+ w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ + (USItype) uu.s.high * (USItype) vv.s.low);
+
+ return w.ll;
+}
+
--- /dev/null
+/*
+ * linux/arch/arm/lib/putuser.S
+ *
+ * Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
+ *
+ * These functions have a non-standard call interface to make
+ * them more efficient, especially as they return an error
+ * value in addition to the "real" return value.
+ *
+ * __put_user_X
+ *
+ * Inputs: r0 contains the address
+ * r1, r2 contains the value
+ * Outputs: r0 is the error code
+ * lr corrupted
+ *
+ * No other registers must be altered. (see include/asm-arm/uaccess.h
+ * for specific ASM register usage).
+ *
+ * Note that ADDR_LIMIT is either 0 or 0xc0000000
+ * Note also that it is intended that __put_user_bad is not global.
+ */
+#include <asm/constants.h>
+
+ .global __put_user_1
+__put_user_1:
+ bic r2, sp, #0x1f00
+ bic r2, r2, #0x00ff
+ ldr r2, [r2, #TSK_ADDR_LIMIT]
+ sub r2, r2, #1
+ cmp r0, r2
+1: strlsbt r1, [r0]
+ movls r0, #0
+ movls pc, lr
+ b __put_user_bad
+
+ .global __put_user_2
+__put_user_2:
+ bic r2, sp, #0x1f00
+ bic r2, r2, #0x00ff
+ ldr r2, [r2, #TSK_ADDR_LIMIT]
+ sub r2, r2, #2
+ cmp r0, r2
+2: strlsbt r1, [r0], #1
+ movls r1, r1, lsr #8
+3: strlsbt r1, [r0]
+ movls r0, #0
+ movls pc, lr
+ b __put_user_bad
+
+ .global __put_user_4
+__put_user_4:
+ bic r2, sp, #0x1f00
+ bic r2, r2, #0x00ff
+ ldr r2, [r2, #TSK_ADDR_LIMIT]
+ sub r2, r2, #4
+ cmp r0, r2
+4: strlst r1, [r0]
+ movls r0, #0
+ movls pc, lr
+ b __put_user_bad
+
+ .global __put_user_8
+__put_user_8:
+ bic ip, sp, #0x1f00
+ bic ip, ip, #0x00ff
+ ldr ip, [ip, #TSK_ADDR_LIMIT]
+ sub ip, ip, #8
+ cmp r0, ip
+5: strlst r1, [r0], #4
+6: strlst r2, [r0]
+ movls r0, #0
+ movls pc, lr
+
+ /* fall through */
+
+__put_user_bad:
+ mov r0, #-14
+ mov pc, lr
+
+.section __ex_table, "a"
+ .long 1b, __put_user_bad
+ .long 2b, __put_user_bad
+ .long 3b, __put_user_bad
+ .long 4b, __put_user_bad
+ .long 5b, __put_user_bad
+ .long 6b, __put_user_bad
+.previous
--- /dev/null
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License.
+ */
+/* support functions required by the kernel. based on code from gcc-2.95.3 */
+/* I Molton 29/07/01 */
+
+#include "gcclib.h"
+
+word_type
+__ucmpdi2 (DItype a, DItype b)
+{
+ DIunion au, bu;
+
+ au.ll = a, bu.ll = b;
+
+ if ((USItype) au.s.high < (USItype) bu.s.high)
+ return 0;
+ else if ((USItype) au.s.high > (USItype) bu.s.high)
+ return 2;
+ if ((USItype) au.s.low < (USItype) bu.s.low)
+ return 0;
+ else if ((USItype) au.s.low > (USItype) bu.s.low)
+ return 2;
+ return 1;
+}
+
--- /dev/null
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License.
+ */
+/* support functions required by the kernel. based on code from gcc-2.95.3 */
+/* I Molton 29/07/01 */
+
+#include "gcclib.h"
+#include "longlong.h"
+
+static const UQItype __clz_tab[] =
+{
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
+
+UDItype
+__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
+{
+ DIunion ww;
+ DIunion nn, dd;
+ DIunion rr;
+ USItype d0, d1, n0, n1, n2;
+ USItype q0, q1;
+ USItype b, bm;
+
+ nn.ll = n;
+ dd.ll = d;
+
+ d0 = dd.s.low;
+ d1 = dd.s.high;
+ n0 = nn.s.low;
+ n1 = nn.s.high;
+
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm != 0)
+ {
+ /* Normalize, i.e. make the most significant bit of the
+ denominator set. */
+
+ d0 = d0 << bm;
+ n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
+ n0 = n0 << bm;
+ }
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0 >> bm. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm == 0)
+ {
+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ leading quotient digit q1 = 1).
+
+ This special case is necessary, not an optimization.
+ (Shifts counts of SI_TYPE_SIZE are undefined.) */
+
+ n1 -= d0;
+ q1 = 1;
+ }
+ else
+ {
+ /* Normalize. */
+
+ b = SI_TYPE_SIZE - bm;
+
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q1, n1, n2, n1, d0);
+ }
+
+ /* n1 != d0... */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0 >> bm. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0 >> bm;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ if (d1 > n1)
+ {
+ /* 00 = nn / DD */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* Remainder in n1n0. */
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ /* 0q = NN / dd */
+
+ count_leading_zeros (bm, d1);
+ if (bm == 0)
+ {
+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ quotient digit q0 = 0 or 1).
+
+ This special case is necessary, not an optimization. */
+
+ /* The condition on the next line takes advantage of that
+ n1 >= d1 (true due to program flow). */
+ if (n1 > d1 || n0 >= d0)
+ {
+ q0 = 1;
+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
+ }
+ else
+ q0 = 0;
+
+ q1 = 0;
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ USItype m1, m0;
+ /* Normalize. */
+
+ b = SI_TYPE_SIZE - bm;
+
+ d1 = (d1 << bm) | (d0 >> b);
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q0, n1, n2, n1, d1);
+ umul_ppmm (m1, m0, q0, d0);
+
+ if (m1 > n1 || (m1 == n1 && m0 > n0))
+ {
+ q0--;
+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
+ }
+
+ q1 = 0;
+
+ /* Remainder in (n1n0 - m1m0) >> bm. */
+ if (rp != 0)
+ {
+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
+ rr.s.low = (n1 << b) | (n0 >> bm);
+ rr.s.high = n1 >> bm;
+ *rp = rr.ll;
+ }
+ }
+ }
+ }
+
+ ww.s.low = q0;
+ ww.s.high = q1;
+ return ww.ll;
+}
+
+UDItype
+__udivdi3 (UDItype n, UDItype d)
+{
+ return __udivmoddi4 (n, d, (UDItype *) 0);
+}
__raw_readsb(ISAIO_BASE + off, from, len);
}
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(insb);
+
void outsw(unsigned int port, const void *from, int len)
{
u32 off;
__raw_readsw(ISAIO_BASE + off, from, len);
}
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(insw);
+
void outsl(unsigned int port, const void *from, int len)
{
panic("outsl not supported on this architecture");
*
* Copyright (C) 2001 Deep Blue Solutions Ltd.
*
- * $Id: cpu.c,v 1.1 2001/06/17 10:12:37 rmk Exp $
+ * $Id: cpu.c,v 1.2 2001/09/22 12:11:17 rmk Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* Validate the speed in khz. If it is outside our
* range, then return the lowest.
*/
-unsigned int cpufreq_validatespeed(unsigned int freq_khz)
+unsigned int integrator_validatespeed(unsigned int freq_khz)
{
struct vco vco;
return vco_to_freq(vco, 1);
}
-void cpufreq_setspeed(unsigned int freq_khz)
+void integrator_setspeed(unsigned int freq_khz)
{
struct vco vco = freq_to_vco(freq_khz, 1);
u_int cm_osc;
#ifdef CONFIG_CPU_FREQ
cpufreq_init(cpu_freq_khz);
+ cpufreq_setfunctions(integrator_validatespeed, integrator_setspeed);
#endif
cm_stat = __raw_readl(CM_STAT);
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/mman.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
obj-n :=
obj- :=
-export-objs := assabet.o bitsy.o freebird.o huw_webpanel.o yopy.o \
+export-objs := assabet.o h3600.o freebird.o huw_webpanel.o yopy.o \
generic.o hwtimer.o irq.o usb_ctl.o usb_recv.o usb_send.o \
- dma-sa1100.o dma-sa1111.o pcipool.o
+ dma-sa1100.o dma-sa1111.o pcipool.o sa1111-pcibuf.o
# Common support (must be linked before board specific support)
obj-y += generic.o irq.o dma-sa1100.o
-obj-$(CONFIG_SA1111) += sa1111.o dma-sa1111.o sa1111-pcibuf.o pcipool.o
# This needs to be cleaned up. We probably need to have SA1100
# and SA1110 config symbols.
+#
+# We link the CPU support next, so that RAM timings can be tuned.
ifeq ($(CONFIG_CPU_FREQ),y)
obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o
endif
+# Next, the SA1111 stuff.
+obj-$(CONFIG_SA1111) += sa1111.o dma-sa1111.o
+obj-$(CONFIG_USB_OHCI_SA1111) += sa1111-pcibuf.o pcipool.o
+
# Specific board support
+obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o
obj-$(CONFIG_SA1100_ASSABET) += assabet.o
obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o
-obj-$(CONFIG_SA1100_BITSY) += bitsy.o
obj-$(CONFIG_SA1100_BRUTUS) += brutus.o
obj-$(CONFIG_SA1100_CERF) += cerf.o
obj-$(CONFIG_SA1100_EMPEG) += empeg.o
obj-$(CONFIG_SA1100_FLEXANET) += flexanet.o
obj-$(CONFIG_SA1100_FREEBIRD) += freebird.o
obj-$(CONFIG_SA1100_GRAPHICSCLIENT) += graphicsclient.o
+obj-$(CONFIG_SA1100_GRAPHICSMASTER) += graphicsmaster.o
+obj-$(CONFIG_SA1100_H3600) += h3600.o
obj-$(CONFIG_SA1100_HUW_WEBPANEL) += huw_webpanel.o
obj-$(CONFIG_SA1100_ITSY) += itsy.o
obj-$(CONFIG_SA1100_JORNADA720) += jornada720.o
leds-$(CONFIG_SA1100_GRAPHICSCLIENT) += leds-graphicsclient.o
leds-$(CONFIG_SA1100_LART) += leds-lart.o
leds-$(CONFIG_SA1100_PFS168) += leds-pfs168.o
+leds-$(CONFIG_SA1100_GRAPHICSMASTER) += leds-graphicsmaster.o
obj-$(CONFIG_LEDS) += $(leds-y)
include $(TOPDIR)/Rules.make
--- /dev/null
+/*
+ * linux/arch/arm/mach-sa1100/adsbitsy.c
+ *
+ * Author: Woojung Huh
+ *
+ * Pieces specific to the ADS Bitsy
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/serial_core.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <asm/arch/irq.h>
+
+#include "generic.h"
+#include "sa1111.h"
+
+static int __init adsbitsy_init(void)
+{
+ int ret;
+
+ if (!machine_is_adsbitsy())
+ return -ENODEV;
+
+ /*
+ * Ensure that the memory bus request/grant signals are setup,
+ * and the grant is held in its inactive state
+ */
+ sa1110_mb_disable();
+
+ /*
+ * Reset SA1111
+ */
+ GPCR |= GPIO_GPIO26;
+ udelay(1000);
+ GPSR |= GPIO_GPIO26;
+
+ /*
+ * Probe for SA1111.
+ */
+ ret = sa1111_probe();
+ if (ret < 0)
+ return ret;
+
+ /*
+ * We found it. Wake the chip up.
+ */
+ sa1111_wake();
+
+ /*
+ * The SDRAM configuration of the SA1110 and the SA1111 must
+ * match. This is very important to ensure that SA1111 accesses
+ * don't corrupt the SDRAM. Note that this ungates the SA1111's
+ * MBGNT signal, so we must have called sa1110_mb_disable()
+ * beforehand.
+ */
+ sa1111_configure_smc(1,
+ FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
+ FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
+
+ /*
+ * Enable PWM control for LCD
+ */
+ SKPCR |= SKPCR_PWMCLKEN;
+ SKPWM0 = 0x7F; // VEE
+ SKPEN0 = 1;
+ SKPWM1 = 0x01; // Backlight
+ SKPEN1 = 1;
+
+ /*
+ * We only need to turn on DCLK whenever we want to use the
+ * DMA. It can otherwise be held firmly in the off position.
+ */
+ SKPCR |= SKPCR_DCLKEN;
+
+ /*
+ * Enable the SA1110 memory bus request and grant signals.
+ */
+ sa1110_mb_enable();
+
+ set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_RISING_EDGE);
+ sa1111_init_irq(SA1100_GPIO_TO_IRQ(0));
+
+ return 0;
+}
+
+__initcall(adsbitsy_init);
+
+static void __init adsbitsy_init_irq(void)
+{
+ /* First the standard SA1100 IRQs */
+ sa1100_init_irq();
+}
+
+
+/*
+ * Initialization fixup
+ */
+
+static void __init
+fixup_adsbitsy(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+ SET_BANK( 0, 0xc0000000, 32*1024*1024 );
+ mi->nr_banks = 1;
+
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+ setup_ramdisk( 1, 0, 0, 8192 );
+ setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
+}
+
+static struct map_desc adsbitsy_io_desc[] __initdata = {
+ /* virtual physical length domain r w c b */
+ { 0xe8000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
+ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1111 */
+ LAST_DESC
+};
+
+static int adsbitsy_uart_open(struct uart_port *port, struct uart_info *info)
+{
+ if (port->mapbase == _Ser1UTCR0) {
+ Ser1SDCR0 |= SDCR0_UART;
+ // Set RTS Output and High (should be done in the set_mctrl fn)
+ GPDR |= GPIO_GPIO15;
+ GPCR |= GPIO_GPIO15;
+ // Set CTS Input
+ GPDR &= ~GPIO_GPIO14;
+ } else if (port->mapbase == _Ser2UTCR0) {
+ Ser2UTCR4 = Ser2HSCR0 = 0;
+ // Set RTS Output and High (should be done in the set_mctrl fn)
+ GPDR |= GPIO_GPIO17;
+ GPCR |= GPIO_GPIO17;
+ // Set CTS Input
+ GPDR &= ~GPIO_GPIO16;
+ } else if (port->mapbase == _Ser2UTCR0) {
+ // Set RTS Output and High (should be done in the set_mctrl fn)
+ GPDR |= GPIO_GPIO19;
+ GPCR |= GPIO_GPIO19;
+ // Set CTS Input
+ GPDR &= ~GPIO_GPIO18;
+ }
+ return 0;
+}
+
+static struct sa1100_port_fns adsbitsy_port_fns __initdata = {
+ open: adsbitsy_uart_open,
+};
+
+static void __init adsbitsy_map_io(void)
+{
+ sa1100_map_io();
+ iotable_init(adsbitsy_io_desc);
+
+ sa1110_register_uart_fns(&adsbitsy_port_fns);
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1);
+ sa1100_register_uart(2, 2);
+}
+
+MACHINE_START(ADSBITSY, "ADS Bitsy")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ FIXUP(fixup_adsbitsy)
+ MAPIO(adsbitsy_map_io)
+ INITIRQ(adsbitsy_init_irq)
+MACHINE_END
* or BCR_clear().
*/
BCR = BCR_value = BCR_DB1111;
+ NCR_0 = 0;
#ifndef CONFIG_ASSABET_NEPONSET
printk( "Warning: Neponset detected but full support "
SCR_value = scr;
}
+extern void convert_to_tag_list(struct param_struct *params, int mem_init);
+
static void __init
fixup_assabet(struct machine_desc *desc, struct param_struct *params,
char **cmdline, struct meminfo *mi)
if (machine_has_neponset())
printk("Neponset expansion board detected\n");
+ /*
+ * Apparantly bootldr uses a param_struct. Groan.
+ */
+ if (t->hdr.tag != ATAG_CORE)
+ convert_to_tag_list(params, 1);
+
if (t->hdr.tag != ATAG_CORE) {
t->hdr.tag = ATAG_CORE;
t->hdr.size = tag_size(tag_core);
neponset_map_io();
#endif
- sa1100_register_uart(1, 2);
if (machine_has_neponset()) {
/*
* When Neponset is attached, the first UART should be
* excessive power drain. --rmk
*/
GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
- GPCR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
+ GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
}
+++ /dev/null
-/*
- * linux/arch/arm/mach-sa1100/bitsy.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/setup.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
-#include <linux/serial_core.h>
-
-#include "generic.h"
-
-
-/*
- * Bitsy has extended, write-only memory-mapped GPIO's
- */
-
-static int bitsy_egpio = EGPIO_BITSY_RS232_ON;
-
-void clr_bitsy_egpio(unsigned long x)
-{
- bitsy_egpio &= ~x;
- BITSY_EGPIO = bitsy_egpio;
-}
-
-void set_bitsy_egpio(unsigned long x)
-{
- bitsy_egpio |= x;
- BITSY_EGPIO = bitsy_egpio;
-}
-
-EXPORT_SYMBOL(clr_bitsy_egpio);
-EXPORT_SYMBOL(set_bitsy_egpio);
-
-
-/*
- * low-level UART features
- */
-
-static void bitsy_uart_set_mctrl(struct uart_port *port, u_int mctrl)
-{
- if (port->mapbase == _Ser3UTCR0) {
- if (mctrl & TIOCM_RTS)
- GPCR = GPIO_BITSY_COM_RTS;
- else
- GPSR = GPIO_BITSY_COM_RTS;
- }
-}
-
-static int bitsy_uart_get_mctrl(struct uart_port *port)
-{
- int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
-
- if (port->mapbase == _Ser3UTCR0) {
- int gplr = GPLR;
- if (gplr & GPIO_BITSY_COM_DCD)
- ret &= ~TIOCM_CD;
- if (gplr & GPIO_BITSY_COM_CTS)
- ret &= ~TIOCM_CTS;
- }
-
- return ret;
-}
-
-static void bitsy_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct uart_info *info = dev_id;
- /* Note: should only call this if something has changed */
- uart_handle_dcd_change(info, GPLR & GPIO_BITSY_COM_DCD);
-}
-
-static void bitsy_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct uart_info *info = dev_id;
- /* Note: should only call this if something has changed */
- uart_handle_cts_change(info, GPLR & GPIO_BITSY_COM_CTS);
-}
-
-static void bitsy_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
-{
- if (port->mapbase == _Ser2UTCR0) {
- if (state == 0) {
- set_bitsy_egpio(EGPIO_BITSY_IR_ON);
- } else {
- clr_bitsy_egpio(EGPIO_BITSY_IR_ON);
- }
- } else if (port->mapbase == _Ser3UTCR0) {
- if (state == 0) {
- set_bitsy_egpio(EGPIO_BITSY_RS232_ON);
- } else {
- clr_bitsy_egpio(EGPIO_BITSY_RS232_ON);
- }
- }
-}
-
-static int bitsy_uart_open(struct uart_port *port, struct uart_info *info)
-{
- int ret = 0;
-
- if (port->mapbase == _Ser2UTCR0) {
- Ser2UTCR4 = UTCR4_HSE;
- Ser2HSCR0 = 0;
- Ser2HSSR0 = HSSR0_EIF | HSSR0_TUR |
- HSSR0_RAB | HSSR0_FRE;
- } else if (port->mapbase == _Ser3UTCR0) {
- GPDR &= ~(GPIO_BITSY_COM_DCD|GPIO_BITSY_COM_CTS);
- GPDR |= GPIO_BITSY_COM_RTS;
- set_GPIO_IRQ_edge(GPIO_BITSY_COM_DCD|GPIO_BITSY_COM_CTS,
- GPIO_BOTH_EDGES);
-
- ret = request_irq(IRQ_GPIO_BITSY_COM_DCD, bitsy_dcd_intr,
- 0, "RS232 DCD", info);
- if (ret)
- return ret;
-
- ret = request_irq(IRQ_GPIO_BITSY_COM_CTS, bitsy_cts_intr,
- 0, "RS232 CTS", info);
- if (ret)
- free_irq(IRQ_GPIO_BITSY_COM_DCD, info);
- }
- return ret;
-}
-
-static void bitsy_uart_close(struct uart_port *port, struct uart_info *info)
-{
- if (port->mapbase == _Ser3UTCR0) {
- free_irq(IRQ_GPIO_BITSY_COM_DCD, info);
- free_irq(IRQ_GPIO_BITSY_COM_CTS, info);
- }
-}
-
-static struct sa1100_port_fns bitsy_port_fns __initdata = {
- set_mctrl: bitsy_uart_set_mctrl,
- get_mctrl: bitsy_uart_get_mctrl,
- pm: bitsy_uart_pm,
- open: bitsy_uart_open,
- close: bitsy_uart_close,
-};
-
-static struct map_desc bitsy_io_desc[] __initdata = {
- /* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x49000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
- { 0xf1000000, 0x10000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 */
- { 0xf3000000, 0x40000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 */
- LAST_DESC
-};
-
-static void __init bitsy_map_io(void)
-{
- sa1100_map_io();
- iotable_init(bitsy_io_desc);
-
- sa1100_register_uart_fns(&bitsy_port_fns);
- sa1100_register_uart(0, 3);
- sa1100_register_uart(1, 1); /* isn't this one driven elsewhere? */
- sa1100_register_uart(2, 2);
-}
-
-MACHINE_START(BITSY, "Compaq iPAQ")
- BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
- BOOT_PARAMS(0xc0000100)
- MAPIO(bitsy_map_io)
- INITIRQ(sa1100_init_irq)
-MACHINE_END
*
* Copyright (C) 2001 Russell King
*
- * $Id: cpu-sa1110.c,v 1.3 2001/08/12 15:41:53 rmk Exp $
+ * $Id: cpu-sa1110.c,v 1.5 2001/09/10 13:25:58 rmk Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
{
struct sdram_params *sdram = NULL;
unsigned int cur_freq = cpufreq_get(smp_processor_id());
- int ret = -ENODEV;
if (machine_is_assabet())
sdram = &tc59sm716_cl3_params;
if (sdram) {
printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
- " twr: %d refresh: %d cas_latency: %d",
+ " twr: %d refresh: %d cas_latency: %d\n",
sdram->tck, sdram->trcd, sdram->trp,
sdram->twr, sdram->refresh, sdram->cas_latency);
{
dma_regs_t *regs = dma->regs;
int status;
- int use_bufa;
status = regs->RdDCSR;
/* If both DMA buffers are started, there's nothing else we can do. */
- if ((status & DCSR_STRTA) && (status & DCSR_STRTB)) {
+ if ((status & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB)) {
DPRINTK("start: st %#x busy\n", status);
return -EBUSY;
}
- use_bufa = (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
- (!(status & DCSR_BIU) && !(status & DCSR_STRTA)));
- if (use_bufa) {
- regs->ClrDCSR = DCSR_DONEA | DCSR_STRTA;
+ if (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
+ (!(status & DCSR_BIU) && !(status & DCSR_STRTA))) {
+ if (status & DCSR_DONEA) {
+ /* give a chance for the interrupt to be processed */
+ goto irq_pending;
+ }
regs->DBSA = dma_ptr;
regs->DBTA = size;
regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN;
DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size);
} else {
- regs->ClrDCSR = DCSR_DONEB | DCSR_STRTB;
+ if (status & DCSR_DONEB) {
+ /* give a chance for the interrupt to be processed */
+ goto irq_pending;
+ }
regs->DBSB = dma_ptr;
regs->DBTB = size;
regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN;
}
return 0;
+
+irq_pending:
+ return -EAGAIN;
}
DPRINTK("IRQ: b=%#x st=%#x\n", (int) dma->curr->id, status);
- dma->regs->ClrDCSR = DCSR_ERROR | DCSR_DONEA | DCSR_DONEB;
- if (!(status & (DCSR_DONEA | DCSR_DONEB)))
- return;
+ if (status & (DCSR_ERROR)) {
+ printk(KERN_ERR "DMA on \"%s\" caused an error\n", dma->device_id);
+ dma->regs->ClrDCSR = DCSR_ERROR;
+ }
- sa1100_dma_done (dma);
+ dma->regs->ClrDCSR = status & (DCSR_DONEA | DCSR_DONEB);
+ if (status & DCSR_DONEA)
+ sa1100_dma_done (dma);
+ if (status & DCSR_DONEB)
+ sa1100_dma_done (dma);
}
dma->curr = NULL;
}
dma->spin_ref = 0;
- dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB;
+ dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_DONEA|DCSR_DONEB;
process_dma(dma);
local_irq_restore(flags);
return 0;
if (dma->stopped) {
int flags;
save_flags_cli(flags);
- dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_RUN|DCSR_IE;
dma->stopped = 0;
dma->spin_ref = 0;
process_dma(dma);
if (channel_is_sa1111_sac(channel))
sa1111_reset_sac_dma(channel);
else
- dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_RUN|DCSR_IE;
+ dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_DONEA|DCSR_DONEB|DCSR_RUN|DCSR_IE;
buf = dma->curr;
if (!buf)
buf = dma->tail;
if(physaddr<(1<<20))
return 0;
- switch(FExtr(SMCR, SMCR_DRAC)){
+ switch(FExtr(SBI_SMCR, SMCR_DRAC)){
case 01: /* 10 row + bank address bits, A<20> must not be set */
if(physaddr & (1<<20))
return -1;
break;
default:
printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%o\n",
- __FUNCTION__, FExtr(SMCR, SMCR_DRAC));
+ __FUNCTION__, FExtr(SBI_SMCR, SMCR_DRAC));
return -1;
}
* Validate the speed in khz. If we can't generate the precise
* frequency requested, round it down (to be on the safe side).
*/
-unsigned int cpufreq_validatespeed(unsigned int khz)
+unsigned int sa1100_validatespeed(unsigned int khz)
{
int i;
* above, we can match for an exact frequency. If we don't find
* an exact match, we will to set the lowest frequency to be safe.
*/
-void cpufreq_setspeed(unsigned int khz)
+void sa1100_setspeed(unsigned int khz)
{
int i;
static int __init sa1100_init_clock(void)
{
cpufreq_init(get_cclk_frequency() * 100);
+ cpufreq_setfunctions(sa1100_validatespeed, sa1100_setspeed);
return 0;
}
mi->nr_banks = 2;
ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
- setup_ramdisk( 1, 0, 0, 4096 );
+ setup_ramdisk( 1, 0, 0, 8192 );
setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
}
static struct map_desc graphicsclient_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
+ { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
{ 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+ { 0xf1000000, 0x18000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CAN */
LAST_DESC
};
--- /dev/null
+/*
+ * linux/arch/arm/mach-sa1100/graphicsmaster.c
+ *
+ * Pieces specific to the GraphicsMaster board
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <asm/arch/irq.h>
+
+#include "generic.h"
+#include "sa1111.h"
+
+static int __init graphicsmaster_init(void)
+{
+ int ret;
+
+ if (!machine_is_graphicsmaster())
+ return -ENODEV;
+
+ /*
+ * Ensure that the memory bus request/grant signals are setup,
+ * and the grant is held in its inactive state
+ */
+ sa1110_mb_disable();
+
+ /*
+ * Probe for SA1111.
+ */
+ ret = sa1111_probe();
+ if (ret < 0)
+ return ret;
+
+ /*
+ * We found it. Wake the chip up.
+ */
+ sa1111_wake();
+
+ /*
+ * The SDRAM configuration of the SA1110 and the SA1111 must
+ * match. This is very important to ensure that SA1111 accesses
+ * don't corrupt the SDRAM. Note that this ungates the SA1111's
+ * MBGNT signal, so we must have called sa1110_mb_disable()
+ * beforehand.
+ */
+ sa1111_configure_smc(1,
+ FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
+ FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
+
+ /*
+ * Enable PWM control for LCD
+ */
+ SKPCR |= SKPCR_PWMCLKEN;
+ SKPWM0 = 0x7F; // VEE
+ SKPEN0 = 1;
+ SKPWM1 = 0x01; // Backlight
+ SKPEN1 = 1;
+
+ /*
+ * We only need to turn on DCLK whenever we want to use the
+ * DMA. It can otherwise be held firmly in the off position.
+ */
+ SKPCR |= SKPCR_DCLKEN;
+
+ /*
+ * Enable the SA1110 memory bus request and grant signals.
+ */
+ sa1110_mb_enable();
+
+ sa1111_init_irq(ADS_EXT_IRQ(0));
+
+ return 0;
+}
+
+__initcall(graphicsmaster_init);
+
+/*
+ * Handlers for GraphicsMaster's external IRQ logic
+ */
+
+static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+{
+ int i;
+
+ while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){
+ for( i = 0; i < 16; i++ )
+ if( irq & (1<<i) ) {
+ do_IRQ( ADS_EXT_IRQ(i), regs );
+ }
+ }
+}
+
+static struct irqaction ADS_ext_irq = {
+ name: "ADS_ext_IRQ",
+ handler: ADS_IRQ_demux,
+ flags: SA_INTERRUPT
+};
+
+static void ADS_mask_and_ack_irq0(unsigned int irq)
+{
+ int mask = (1 << (irq - ADS_EXT_IRQ(0)));
+ ADS_INT_EN1 &= ~mask;
+ ADS_INT_ST1 = mask;
+}
+
+static void ADS_mask_irq0(unsigned int irq)
+{
+ ADS_INT_ST1 = (1 << (irq - ADS_EXT_IRQ(0)));
+}
+
+static void ADS_unmask_irq0(unsigned int irq)
+{
+ ADS_INT_EN1 |= (1 << (irq - ADS_EXT_IRQ(0)));
+}
+
+static void ADS_mask_and_ack_irq1(unsigned int irq)
+{
+ int mask = (1 << (irq - ADS_EXT_IRQ(8)));
+ ADS_INT_EN2 &= ~mask;
+ ADS_INT_ST2 = mask;
+}
+
+static void ADS_mask_irq1(unsigned int irq)
+{
+ ADS_INT_ST2 = (1 << (irq - ADS_EXT_IRQ(8)));
+}
+
+static void ADS_unmask_irq1(unsigned int irq)
+{
+ ADS_INT_EN2 |= (1 << (irq - ADS_EXT_IRQ(8)));
+}
+
+static void __init graphicsmaster_init_irq(void)
+{
+ int irq;
+
+ /* First the standard SA1100 IRQs */
+ sa1100_init_irq();
+
+ /* disable all IRQs */
+ ADS_INT_EN1 = 0;
+ ADS_INT_EN2 = 0;
+ /* clear all IRQs */
+ ADS_INT_ST1 = 0xff;
+ ADS_INT_ST2 = 0xff;
+
+ for (irq = ADS_EXT_IRQ(0); irq <= ADS_EXT_IRQ(7); irq++) {
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = ADS_mask_and_ack_irq0;
+ irq_desc[irq].mask = ADS_mask_irq0;
+ irq_desc[irq].unmask = ADS_unmask_irq0;
+ }
+ for (irq = ADS_EXT_IRQ(8); irq <= ADS_EXT_IRQ(15); irq++) {
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = ADS_mask_and_ack_irq1;
+ irq_desc[irq].mask = ADS_mask_irq1;
+ irq_desc[irq].unmask = ADS_unmask_irq1;
+ }
+ GPDR &= ~GPIO_GPIO0;
+ set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
+ setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
+}
+
+
+/*
+ * Initialization fixup
+ */
+
+static void __init
+fixup_graphicsmaster(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+ SET_BANK( 0, 0xc0000000, 16*1024*1024 );
+ mi->nr_banks = 1;
+ SET_BANK( 1, 0xc8000000, 16*1024*1024 );
+ mi->nr_banks = 2;
+
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+ setup_ramdisk( 1, 0, 0, 8192 );
+ setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
+}
+
+static struct map_desc graphicsmaster_io_desc[] __initdata = {
+ /* virtual physical length domain r w c b */
+ { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
+ { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CPLD */
+ { 0xf1000000, 0x40000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CAN */
+ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ LAST_DESC
+};
+
+static void __init graphicsmaster_map_io(void)
+{
+ sa1100_map_io();
+ iotable_init(graphicsmaster_io_desc);
+
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1);
+ sa1100_register_uart(2, 2);
+}
+
+MACHINE_START(GRAPHICSMASTER, "ADS GraphicsMaster")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ FIXUP(fixup_graphicsmaster)
+ MAPIO(graphicsmaster_map_io)
+ INITIRQ(graphicsmaster_init_irq)
+MACHINE_END
--- /dev/null
+/*
+ * linux/arch/arm/mach-sa1100/h3600.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+#include <linux/serial_core.h>
+
+#include "generic.h"
+
+
+/*
+ * Bitsy has extended, write-only memory-mapped GPIO's
+ */
+
+static int h3600_egpio = EGPIO_H3600_RS232_ON;
+
+void clr_h3600_egpio(unsigned long x)
+{
+ h3600_egpio &= ~x;
+ H3600_EGPIO = h3600_egpio;
+}
+
+void set_h3600_egpio(unsigned long x)
+{
+ h3600_egpio |= x;
+ H3600_EGPIO = h3600_egpio;
+}
+
+EXPORT_SYMBOL(clr_h3600_egpio);
+EXPORT_SYMBOL(set_h3600_egpio);
+
+
+/*
+ * Low-level UART features.
+ *
+ * Note that RTS, CTS and DCD are all active low.
+ */
+
+static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ if (port->mapbase == _Ser3UTCR0) {
+ if (mctrl & TIOCM_RTS)
+ GPCR = GPIO_H3600_COM_RTS;
+ else
+ GPSR = GPIO_H3600_COM_RTS;
+ }
+}
+
+static int h3600_uart_get_mctrl(struct uart_port *port)
+{
+ int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
+
+ if (port->mapbase == _Ser3UTCR0) {
+ int gplr = GPLR;
+ if (gplr & GPIO_H3600_COM_DCD)
+ ret &= ~TIOCM_CD;
+ if (gplr & GPIO_H3600_COM_CTS)
+ ret &= ~TIOCM_CTS;
+ }
+
+ return ret;
+}
+
+static void h3600_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_info *info = dev_id;
+ /* Note: should only call this if something has changed */
+ uart_handle_dcd_change(info, !(GPLR & GPIO_H3600_COM_DCD));
+}
+
+static void h3600_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_info *info = dev_id;
+ /* Note: should only call this if something has changed */
+ uart_handle_cts_change(info, !(GPLR & GPIO_H3600_COM_CTS));
+}
+
+static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
+{
+ if (port->mapbase == _Ser2UTCR0) {
+ if (state == 0) {
+ set_h3600_egpio(EGPIO_H3600_IR_ON);
+ } else {
+ clr_h3600_egpio(EGPIO_H3600_IR_ON);
+ }
+ } else if (port->mapbase == _Ser3UTCR0) {
+ if (state == 0) {
+ set_h3600_egpio(EGPIO_H3600_RS232_ON);
+ } else {
+ clr_h3600_egpio(EGPIO_H3600_RS232_ON);
+ }
+ }
+}
+
+static int h3600_uart_open(struct uart_port *port, struct uart_info *info)
+{
+ int ret = 0;
+
+ if (port->mapbase == _Ser2UTCR0) {
+ Ser2UTCR4 = UTCR4_HSE;
+ Ser2HSCR0 = 0;
+ Ser2HSSR0 = HSSR0_EIF | HSSR0_TUR |
+ HSSR0_RAB | HSSR0_FRE;
+ } else if (port->mapbase == _Ser3UTCR0) {
+ GPDR &= ~(GPIO_H3600_COM_DCD|GPIO_H3600_COM_CTS);
+ GPDR |= GPIO_H3600_COM_RTS;
+ set_GPIO_IRQ_edge(GPIO_H3600_COM_DCD|GPIO_H3600_COM_CTS,
+ GPIO_BOTH_EDGES);
+
+ ret = request_irq(IRQ_GPIO_H3600_COM_DCD, h3600_dcd_intr,
+ 0, "RS232 DCD", info);
+ if (ret)
+ return ret;
+
+ ret = request_irq(IRQ_GPIO_H3600_COM_CTS, h3600_cts_intr,
+ 0, "RS232 CTS", info);
+ if (ret)
+ free_irq(IRQ_GPIO_H3600_COM_DCD, info);
+ }
+ return ret;
+}
+
+static void h3600_uart_close(struct uart_port *port, struct uart_info *info)
+{
+ if (port->mapbase == _Ser3UTCR0) {
+ free_irq(IRQ_GPIO_H3600_COM_DCD, info);
+ free_irq(IRQ_GPIO_H3600_COM_CTS, info);
+ }
+}
+
+static struct sa1100_port_fns h3600_port_fns __initdata = {
+ set_mctrl: h3600_uart_set_mctrl,
+ get_mctrl: h3600_uart_get_mctrl,
+ pm: h3600_uart_pm,
+ open: h3600_uart_open,
+ close: h3600_uart_close,
+};
+
+static struct map_desc h3600_io_desc[] __initdata = {
+ /* virtual physical length domain r w c b */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf0000000, 0x49000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
+ { 0xf1000000, 0x10000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 */
+ { 0xf3000000, 0x40000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 */
+ LAST_DESC
+};
+
+static void __init h3600_map_io(void)
+{
+ sa1100_map_io();
+ iotable_init(h3600_io_desc);
+
+ sa1100_register_uart_fns(&h3600_port_fns);
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1); /* isn't this one driven elsewhere? */
+ sa1100_register_uart(2, 2);
+
+ /*
+ * Default GPIO settings.
+ */
+ GPCR = 0x0fffffff;
+ GPDR = 0x0401f3fc;
+
+ /*
+ * Ensure those pins are outputs and driving low.
+ */
+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+}
+
+MACHINE_START(H3600, "Compaq iPAQ")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ BOOT_PARAMS(0xc0000100)
+ MAPIO(h3600_map_io)
+ INITIRQ(sa1100_init_irq)
+MACHINE_END
PPDR |= PPC_LDD3 | PPC_LDD4;
/* initialize extra IRQs */
- sa1111_init_irq(1); /* chained on GPIO 1 */
+ set_GPIO_IRQ_edge(GPIO_GPIO(1), GPIO_RISING_EDGE);
+ sa1111_init_irq(SA1100_GPIO_TO_IRQ(1)); /* chained on GPIO 1 */
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
--- /dev/null
+/*
+ * linux/arch/arm/mach-sa1100/leds-graphicsmaster.c
+ *
+ * GraphicsClient Plus LEDs support
+ * Woojung Huh, Feb 13, 2001
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED 1
+#define LED_STATE_CLAIMED 2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_TIMER ADS_LED0 /* green heartbeat */
+#define LED_USER ADS_LED1 /* amber, boots to on */
+#define LED_IDLE ADS_LED2 /* red has the idle led, if any */
+
+#define LED_MASK (ADS_LED0|ADS_LED1|ADS_LED2)
+
+void graphicsmaster_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ save_flags_cli(flags);
+
+ switch (evt) {
+ case led_start:
+ hw_led_state = 0; /* gc leds are positive logic */
+ led_state = LED_STATE_ENABLED;
+ break;
+
+ case led_stop:
+ led_state &= ~LED_STATE_ENABLED;
+ break;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = LED_MASK;
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ hw_led_state = LED_MASK;
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state ^= LED_TIMER;
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state &= ~LED_IDLE;
+ break;
+
+ case led_idle_end:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state |= LED_IDLE;
+ break;
+#endif
+
+ case led_green_on:
+ break;
+
+ case led_green_off:
+ break;
+
+ case led_amber_on:
+ hw_led_state |= LED_USER;
+ break;
+
+ case led_amber_off:
+ hw_led_state &= ~LED_USER;
+ break;
+
+ case led_red_on:
+ break;
+
+ case led_red_off:
+ break;
+
+ default:
+ break;
+ }
+
+ if (led_state & LED_STATE_ENABLED) {
+ GPSR = hw_led_state;
+ GPCR = hw_led_state ^ LED_MASK;
+ }
+
+ restore_flags(flags);
+}
leds_event = lart_leds_event;
if (machine_is_pfs168())
leds_event = pfs168_leds_event;
+ if (machine_is_graphicsmaster())
+ leds_event = graphicsmaster_leds_event;
leds_event(led_start);
return 0;
extern void graphicsclient_leds_event(led_event_t evt);
extern void lart_leds_event(led_event_t evt);
extern void pfs168_leds_event(led_event_t evt);
-
+extern void graphicsmaster_leds_event(led_event_t evt);
static int __init neponset_init(void)
{
- /* only on assabet */
+ int ret;
+
+ /*
+ * The Neponset is only present on the Assabet machine type.
+ */
if (!machine_is_assabet())
- return 0;
-
- if (machine_has_neponset()) {
- LEDS = WHOAMI;
-
- if (sa1111_init() < 0)
- return -EINVAL;
- /*
- * Assabet is populated by default with two Samsung
- * KM416S8030T-G8
- * 128Mb SDRAMs, which are organized as 12-bit (row addr) x
- * 9-bit
- * (column addr), according to the data sheet. Apparently, the
- * bank selects factor into the row address, as Angel sets up
- * the
- * SA-1110 to use 14x9 addresses. The SDRAM datasheet specifies
- * that when running at 100-125MHz, the CAS latency for -8
- * parts
- * is 3 cycles, which is consistent with Angel.
- */
- SMCR = (SMCR_DTIM | SMCR_MBGE |
- FInsrt(FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), SMCR_DRAC) |
- ((FExtr(MDCNFG, MDCNFG_SA1110_TDL0)==3) ? SMCR_CLAT : 0));
- SKPCR |= SKPCR_DCLKEN;
-
- neponset_init_irq();
- } else
- printk("Neponset expansion board not present\n");
+ return -ENODEV;
+
+ /*
+ * Ensure that the memory bus request/grant signals are setup,
+ * and the grant is held in its inactive state, whether or not
+ * we actually have a Neponset attached.
+ */
+ sa1110_mb_disable();
+
+ if (!machine_has_neponset()) {
+ printk(KERN_DEBUG "Neponset expansion board not present\n");
+ return -ENODEV;
+ }
+
+ if (WHOAMI != 0x11) {
+ printk(KERN_WARNING "Neponset board detected, but "
+ "wrong ID: %02x\n", WHOAMI);
+ return -ENODEV;
+ }
+
+ /*
+ * Neponset has SA1111 connected to CS4. We know that after
+ * reset the chip will be configured for variable latency IO.
+ */
+ /* FIXME: setup MSC2 */
+
+ /*
+ * Probe for a SA1111.
+ */
+ ret = sa1111_probe();
+ if (ret < 0)
+ return ret;
+
+ /*
+ * We found it. Wake the chip up.
+ */
+ sa1111_wake();
+
+ /*
+ * The SDRAM configuration of the SA1110 and the SA1111 must
+ * match. This is very important to ensure that SA1111 accesses
+ * don't corrupt the SDRAM. Note that this ungates the SA1111's
+ * MBGNT signal, so we must have called sa1110_mb_disable()
+ * beforehand.
+ */
+ sa1111_configure_smc(1,
+ FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
+ FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
+
+ /*
+ * We only need to turn on DCLK whenever we want to use the
+ * DMA. It can otherwise be held firmly in the off position.
+ */
+ SKPCR |= SKPCR_DCLKEN;
+
+ /*
+ * Enable the SA1110 memory bus request and grant signals.
+ */
+ sa1110_mb_enable();
+
+ neponset_init_irq();
return 0;
}
fixup_pangolin(struct machine_desc *desc, struct param_struct *params,
char **cmdline, struct meminfo *mi)
{
- SET_BANK( 0, 0xc0000000, 64*1024*1024 );
+ SET_BANK( 0, 0xc0000000, 128*1024*1024 );
mi->nr_banks = 1;
ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
static int __init pfs168_init(void)
{
- if (sa1111_init() < 0)
- return -EINVAL;
- SMCR = (SMCR_DTIM | SMCR_MBGE |
- FInsrt(FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), SMCR_DRAC) |
- ((FExtr(MDCNFG, MDCNFG_SA1110_TDL0)==3) ? SMCR_CLAT : 0));
+ int ret;
+
+ if (!machine_is_pfs168())
+ return -ENODEV;
+
+ /*
+ * Ensure that the memory bus request/grant signals are setup,
+ * and the grant is held in its inactive state
+ */
+ sa1110_mb_disable();
+
+ /*
+ * Probe for SA1111.
+ */
+ ret = sa1111_probe();
+ if (ret < 0)
+ return ret;
+
+ /*
+ * We found it. Wake the chip up.
+ */
+ sa1111_wake();
+
+ /*
+ * The SDRAM configuration of the SA1110 and the SA1111 must
+ * match. This is very important to ensure that SA1111 accesses
+ * don't corrupt the SDRAM. Note that this ungates the SA1111's
+ * MBGNT signal, so we must have called sa1110_mb_disable()
+ * beforehand.
+ */
+ sa1111_configure_smc(1,
+ FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
+ FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
+
+ /*
+ * We only need to turn on DCLK whenever we want to use the
+ * DMA. It can otherwise be held firmly in the off position.
+ */
SKPCR |= SKPCR_DCLKEN;
- sa1111_init_irq(25); /* SA1111 IRQ on GPIO 25 */
+ /*
+ * Enable the SA1110 memory bus request and grant signals.
+ */
+ sa1110_mb_enable();
+
+ set_GPIO_IRQ_edge(GPIO_GPIO(25), GPIO_RISING_EDGE);
+ sa1111_init_irq(SA1100_GPIO_TO_IRQ(25)); /* SA1111 IRQ on GPIO 25 */
return 0;
}
*
* 06/13/2001 - created.
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
return 0;
}
-static void
-free_safe_buffers(void)
-{
- pci_pool_destroy(small_buffer_cache);
- pci_pool_destroy(large_buffer_cache);
-}
-
/* allocate a 'safe' buffer and keep track of it */
static char *
alloc_safe_buffer(char *unsafe, int size, dma_addr_t *pbus)
* we assume calls to map_single are symmetric with calls to unmap_single...
*/
dma_addr_t
-pci_map_single(struct pci_dev *hwdev, void *virtptr,
+sa1111_map_single(struct pci_dev *hwdev, void *virtptr,
size_t size, int direction)
{
dma_addr_t busptr;
- /* hack; usb-ohci.c never sends hwdev==NULL, all others do */
- if (hwdev == NULL) {
- consistent_sync(virtptr, size, direction);
- return virt_to_bus(virtptr);
- }
-
mapped_alloc_size += size;
if (0) printk("pci_map_single(hwdev=%p,ptr=%p,size=%d,dir=%x) "
* (basically return things back to the way they should be)
*/
void
-pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+sa1111_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
size_t size, int direction)
{
char *safe, *unsafe;
}
}
-EXPORT_SYMBOL(pci_map_single);
-EXPORT_SYMBOL(pci_unmap_single);
+EXPORT_SYMBOL(sa1111_map_single);
+EXPORT_SYMBOL(sa1111_unmap_single);
-static void __init sa1111_init_safe_buffers(void)
+static int __init sa1111_init_safe_buffers(void)
{
printk("Initializing SA1111 buffer pool for DMA workaround\n");
init_safe_buffers(NULL);
+ return 0;
+}
+
+static void free_safe_buffers(void)
+{
+ pci_pool_destroy(small_buffer_cache);
+ pci_pool_destroy(large_buffer_cache);
}
-__initcall(sa1111_init_safe_buffers);
+module_init(sa1111_init_safe_buffers);
+module_exit(free_safe_buffers);
* All initialization functions provided here are intended to be called
* from machine specific code with proper arguments when required.
*/
-
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/mm.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include "sa1111.h"
-static int sa1111_ohci_hcd_init(void);
-
-/*
- * SA1111 initialization
- */
-
-int __init sa1111_init(void)
-{
- unsigned long id = SKID;
-
- if((id & SKID_ID_MASK) == SKID_SA1111_ID)
- printk( KERN_INFO "SA-1111 Microprocessor Companion Chip: "
- "silicon revision %lx, metal revision %lx\n",
- (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
- else {
- printk(KERN_ERR "Could not detect SA-1111!\n");
- return -EINVAL;
- }
-
- /*
- * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
- * (SA-1110 Developer's Manual, section 9.1.2.1)
- */
- GAFR |= GPIO_32_768kHz;
- GPDR |= GPIO_32_768kHz;
- TUCR = TUCR_3_6864MHz;
-
- /* Now, set up the PLL and RCLK in the SA-1111: */
- SKCR = SKCR_PLL_BYPASS | SKCR_RDYEN | SKCR_OE_EN;
- udelay(100);
- SKCR = SKCR_PLL_BYPASS | SKCR_RCLKEN | SKCR_RDYEN | SKCR_OE_EN;
-
- /*
- * SA-1111 Register Access Bus should now be available. Clocks for
- * any other SA-1111 functional blocks must be enabled separately
- * using the SKPCR.
- */
-
- /*
- * If the system is going to use the SA-1111 DMA engines, set up
- * the memory bus request/grant pins. Also configure the shared
- * memory controller on the SA-1111 (SA-1111 Developer's Manual,
- * section 3.2.3) and power up the DMA bus clock:
- */
- GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
- GPDR |= GPIO_MBGNT;
- GPDR &= ~GPIO_MBREQ;
- TUCR |= TUCR_MR;
-
-#ifdef CONFIG_USB_OHCI
- /* setup up sa1111 usb host controller h/w */
- sa1111_ohci_hcd_init();
-#endif
-
- return 0;
-}
-
-
/*
* SA1111 Interrupt support
*/
INTEN1 |= 1 << ((irq - SA1111_IRQ(32)));
}
-void __init sa1111_init_irq(int gpio_nr)
+void __init sa1111_init_irq(int irq_nr)
{
int irq;
for (irq = SA1111_IRQ(0); irq <= SA1111_IRQ(26); irq++) {
irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].probe_ok = 0;
irq_desc[irq].mask_ack = sa1111_mask_and_ack_lowirq;
irq_desc[irq].mask = sa1111_mask_lowirq;
irq_desc[irq].unmask = sa1111_unmask_lowirq;
}
for (irq = SA1111_IRQ(32); irq <= SA1111_IRQ(54); irq++) {
irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].probe_ok = 0;
irq_desc[irq].mask_ack = sa1111_mask_and_ack_highirq;
irq_desc[irq].mask = sa1111_mask_highirq;
irq_desc[irq].unmask = sa1111_unmask_highirq;
}
- /* Not every machines has the SA1111 interrupt routed to a GPIO */
- if (gpio_nr >= 0) {
- set_GPIO_IRQ_edge (GPIO_GPIO(gpio_nr), GPIO_RISING_EDGE);
- setup_arm_irq (SA1100_GPIO_TO_IRQ(gpio_nr), &sa1111_irq);
- }
+ /* Register SA1111 interrupt */
+ if (irq_nr >= 0)
+ setup_arm_irq(irq_nr, &sa1111_irq);
}
-/* ----------------- */
-
-#ifdef CONFIG_USB_OHCI
-
-#if defined(CONFIG_SA1100_XP860) || defined(CONFIG_ASSABET_NEPONSET) || defined(CONFIG_SA1100_PFS168)
-#define PwrSensePolLow 1
-#define PwrCtrlPolLow 1
-#else
-#define PwrSensePolLow 0
-#define PwrCtrlPolLow 0
-#endif
-
/*
- * The SA-1111 errata says that the DMA hardware needs to be exercised
- * before the clocks are turned on to work properly. This code does
- * a tiny dma transfer to prime to hardware.
+ * Probe for a SA1111 chip.
*/
-static void __init sa1111_dma_setup(void)
-{
- dma_addr_t vbuf;
- void * pbuf;
-
- /* DMA init & setup */
-
- /* WARNING: The SA-1111 L3 function is used as part of this
- * SA-1111 DMA errata workaround.
- *
- * N.B., When the L3 function is enabled, it uses GPIO_B<4:5>
- * and takes precedence over the PS/2 mouse and GPIO_B
- * functions. Refer to "Intel StrongARM SA-1111 Microprocessor
- * Companion Chip, Sect 10.2" for details. So this "fix" may
- * "break" support of either PS/2 mouse or GPIO_B if
- * precautions are not taken to avoid collisions in
- * configuration and use of these pins. AFAIK, no precautions
- * are taken at this time. So it is likely that the action
- * taken here may cause problems in PS/2 mouse and/or GPIO_B
- * pin use elsewhere.
- *
- * But wait, there's more... What we're doing here is
- * obviously altogether a bad idea. We're indiscrimanately bit
- * flipping config for a few different functions here which
- * are "owned" by other drivers. This needs to be handled
- * better than it is being done here at this time. */
-
- /* prime the dma engine with a tiny dma */
- SKPCR |= SKPCR_I2SCLKEN;
- SKAUD |= SKPCR_L3CLKEN | SKPCR_SCLKEN;
-
- SACR0 |= 0x00003305;
- SACR1 = 0x00000000;
-
- /* we need memory below 1mb */
- pbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &vbuf);
-
- SADTSA = (unsigned long)pbuf;
- SADTCA = 4;
-
- SADTCS |= 0x00000011;
- SKPCR |= SKPCR_DCLKEN;
-
- /* wait */
- udelay(100);
-
- SACR0 &= ~(0x00000002);
- SACR0 &= ~(0x00000001);
-
- /* */
- SACR0 |= 0x00000004;
- SACR0 &= ~(0x00000004);
- SKAUD &= ~(SKPCR_L3CLKEN | SKPCR_SCLKEN);
+int __init sa1111_probe(void)
+{
+ unsigned long id = SBI_SKID;
+ int ret = -ENODEV;
- SKPCR &= ~SKPCR_I2SCLKEN;
+ if ((id & SKID_ID_MASK) == SKID_SA1111_ID) {
+ printk(KERN_INFO "SA-1111 Microprocessor Companion Chip: "
+ "silicon revision %lx, metal revision %lx\n",
+ (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
+ ret = 0;
+ } else {
+ printk(KERN_DEBUG "SA-1111 not detected: ID = %08lx\n", id);
+ }
- consistent_free(pbuf, 4, vbuf);
+ return ret;
}
-#ifdef CONFIG_USB_OHCI
/*
- * reset the SA-1111 usb controller and turn on it's clocks
+ * Bring the SA1111 out of reset. This requires a set procedure:
+ * 1. nRESET asserted (by hardware)
+ * 2. CLK turned on from SA1110
+ * 3. nRESET deasserted
+ * 4. VCO turned on, PLL_BYPASS turned off
+ * 5. Wait lock time, then assert RCLKEn
+ * 7. PCR set to allow clocking of individual functions
+ *
+ * Until we've done this, the only registers we can access are:
+ * SBI_SKCR
+ * SBI_SMCR
+ * SBI_SKID
*/
-static int __init sa1111_ohci_hcd_init(void)
+void sa1111_wake(void)
{
- volatile unsigned long *Reset = (void *)SA1111_p2v(_SA1111(0x051c));
- volatile unsigned long *Status = (void *)SA1111_p2v(_SA1111(0x0518));
+ /*
+ * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
+ * (SA-1110 Developer's Manual, section 9.1.2.1)
+ */
+ GAFR |= GPIO_32_768kHz;
+ GPDR |= GPIO_32_768kHz;
+ TUCR = TUCR_3_6864MHz;
- /* turn on clocks */
- SKPCR |= SKPCR_UCLKEN;
- udelay(100);
+ /*
+ * Turn VCO on, and disable PLL Bypass.
+ */
+ SBI_SKCR &= ~SKCR_VCO_OFF;
+ SBI_SKCR |= SKCR_PLL_BYPASS | SKCR_OE_EN;
- /* force a reset */
- *Reset = 0x01;
- *Reset |= 0x02;
+ /*
+ * Wait lock time. SA1111 manual _doesn't_
+ * specify a figure for this! We choose 100us.
+ */
udelay(100);
- *Reset = 0;
+ /*
+ * Enable RCLK. We also ensure that RDYEN is set.
+ */
+ SBI_SKCR |= SKCR_RCLKEN | SKCR_RDYEN;
- /* take out of reset */
- /* set power sense and control lines (this from the diags code) */
- *Reset = ( PwrSensePolLow << 6 )
- | ( PwrCtrlPolLow << 7 );
+ /*
+ * Wait 14 RCLK cycles for the chip to finish coming out
+ * of reset. (RCLK=24MHz). This is 590ns.
+ */
+ udelay(1);
- *Status = 0;
+ /*
+ * Ensure all clocks are initially off.
+ */
+ SKPCR = 0;
+}
+
+void sa1111_doze(void)
+{
+ if (SKPCR & SKPCR_UCLKEN) {
+ printk("SA1111 doze mode refused\n");
+ return;
+ }
+ SBI_SKCR &= ~SKCR_RCLKEN;
+}
- udelay(10);
+/*
+ * Configure the SA1111 shared memory controller.
+ */
+void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency)
+{
+ unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
- /* compensate for dma bug */
- sa1111_dma_setup();
+ if (cas_latency == 3)
+ smcr |= SMCR_CLAT;
- return 0;
+ SBI_SMCR = smcr;
}
-void sa1111_ohci_hcd_cleanup(void)
+/*
+ * Disable the memory bus request/grant signals on the SA1110 to
+ * ensure that we don't receive spurious memory requests. We set
+ * the MBGNT signal false to ensure the SA1111 doesn't own the
+ * SDRAM bus.
+ */
+void __init sa1110_mb_disable(void)
{
- /* turn the USB clock off */
- SKPCR &= ~SKPCR_UCLKEN;
+ PGSR &= ~GPIO_MBGNT;
+ GPCR = GPIO_MBGNT;
+ GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+
+ GAFR &= ~(GPIO_MBGNT | GPIO_MBREQ);
+
}
-#endif
+/*
+ * If the system is going to use the SA-1111 DMA engines, set up
+ * the memory bus request/grant pins.
+ */
+void __init sa1110_mb_enable(void)
+{
+ PGSR &= ~GPIO_MBGNT;
+ GPCR = GPIO_MBGNT;
+ GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
-#endif /* CONFIG_USB_OHCI */
+ GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
+ TUCR |= TUCR_MR;
+}
* linux/arch/arm/mach-sa1100/sa1111.h
*/
-extern int __init sa1111_init(void);
-extern void __init sa1111_init_irq(int gpio_nr);
+/*
+ * These two don't really belong in here.
+ */
+extern void sa1110_mb_enable(void);
+extern void sa1110_mb_disable(void);
+
+/*
+ * Probe for a SA1111 chip.
+ */
+extern int sa1111_probe(void);
+
+/*
+ * Wake up a SA1111 chip.
+ */
+extern void sa1111_wake(void);
+
+/*
+ * Doze the SA1111 chip.
+ */
+extern void sa1111_doze(void);
+
+/*
+ * Configure the SA1111 shared memory controller.
+ */
+extern void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency);
+
+
+extern void sa1111_init_irq(int irq_nr);
extern void sa1111_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs );
while(1);
}
+/*
+ * Note: I replaced the sa1111_init() without the full SA1111 initialisation
+ * because this machine doesn't appear to use the DMA features. If this is
+ * wrong, please look at neponset.c to fix it properly.
+ */
static int __init xp860_init(void)
{
pm_power_off = xp860_power_off;
- sa1111_init();
+
+ /*
+ * Probe for SA1111.
+ */
+ ret = sa1111_probe();
+ if (ret < 0)
+ return ret;
+
+ /*
+ * We found it. Wake the chip up.
+ */
+ sa1111_wake();
+
return 0;
}
return 0;
}
+extern spinlock_t modlist_lock;
+
unsigned long
search_exception_table(unsigned long addr)
{
#ifndef CONFIG_MODULES
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
- if (ret) return ret;
#else
/* The kernel is the last "module" -- no need to treat it special. */
+ unsigned long flags;
struct module *mp;
+
+ ret = 0;
+ spin_lock_irqsave(&modlist_lock, flags);
for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->ex_table_start == NULL)
+ if (mp->ex_table_start == NULL ||
+ !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return ret;
+ if (ret)
+ break;
}
+ spin_unlock_irqrestore(&modlist_lock, flags);
#endif
- return 0;
+ return ret;
}
if (!inf->fn(addr, error_code, regs))
return;
bad:
- force_sig(inf->sig, current);
printk(KERN_ALERT "Unhandled fault: %s (%X) at 0x%08lx\n",
inf->name, fsr, addr);
show_pte(current->mm, addr);
+ force_sig(inf->sig, current);
die_if_kernel("Oops", regs, 0);
return;
tsk->thread.error_code = error_code;
tsk->thread.trap_no = 14;
force_sig(SIGBUS, tsk);
+#ifdef CONFIG_DEBUG_USER
+ printk(KERN_DEBUG "%s: sigbus at 0x%08lx, pc=0x%08lx\n",
+ current->comm, addr, instruction_pointer(regs));
+#endif
/* Kernel mode? Handle exceptions or die */
if (user_mode(regs))
if (addr < TASK_SIZE)
return do_page_fault(addr, error_code, regs);
- tsk = current;
- mm = tsk->active_mm;
-
offset = __pgd_offset(addr);
+ pgd = cpu_get_pgd() + offset;
pgd_k = init_mm.pgd + offset;
- pgd = mm->pgd + offset;
if (pgd_none(*pgd_k))
goto bad_area;
return 0;
bad_area:
+ tsk = current;
+ mm = tsk->active_mm;
+
do_bad_area(tsk, mm, addr, error_code, regs);
return 0;
}
}
#endif
+/* This is currently broken
+ * PG_skip is used on sparc/sparc64 architectures to "skip" certain
+ * parts of the address space.
+ *
+ * #define PG_skip 10
+ * #define PageSkip(page) (machine_is_riscpc() && test_bit(PG_skip, &(page)->flags))
+ * if (PageSkip(page)) {
+ * page = page->next_hash;
+ * if (page == NULL)
+ * break;
+ * }
+ */
void show_mem(void)
{
int free = 0, total = 0, reserved = 0;
- int shared = 0, cached = 0, node;
+ int shared = 0, cached = 0, slab = 0, node;
printk("Mem-info:\n");
show_free_areas();
end = page + NODE_DATA(node)->node_size;
do {
-/* This is currently broken
- * PG_skip is used on sparc/sparc64 architectures to "skip" certain
- * parts of the address space.
- *
- * #define PG_skip 10
- * #define PageSkip(page) (machine_is_riscpc() && test_bit(PG_skip, &(page)->flags))
- * if (PageSkip(page)) {
- * page = page->next_hash;
- * if (page == NULL)
- * break;
- * }
- */
total++;
if (PageReserved(page))
reserved++;
else if (PageSwapCache(page))
cached++;
+ else if (PageSlab(page))
+ slab++;
else if (!page_count(page))
free++;
else
printk("%d pages of RAM\n", total);
printk("%d free pages\n", free);
printk("%d reserved pages\n", reserved);
+ printk("%d slab pages\n", slab);
printk("%d pages shared\n", shared);
printk("%d pages swap cached\n", cached);
#ifndef CONFIG_NO_PGT_CACHE
*/
if (machine_is_archimedes() || machine_is_a5k())
reserve_bootmem_node(pgdat, 0x02000000, 0x00080000);
+ if (machine_is_edb7211())
+ reserve_bootmem_node(pgdat, 0xc0000000, 0x00020000);
if (machine_is_p720t())
reserve_bootmem_node(pgdat, PHYS_OFFSET, 0x00014000);
#ifdef CONFIG_SA1111
if (map_pg != bootmap_pfn + bootmap_pages)
BUG();
+
}
/*
zone_size[0] = bdata->node_low_pfn -
(bdata->node_boot_start >> PAGE_SHIFT);
+ /*
+ * If this zone has zero size, skip it.
+ */
+ if (!zone_size[0])
+ continue;
+
/*
* For each bank in this node, calculate the size of the
* holes. holes = node_size - sum(bank_sizes_in_node)
create_memmap_holes(&meminfo);
/* this will put all unused low memory onto the freelists */
- for (node = 0; node < numnodes; node++)
- totalram_pages += free_all_bootmem_node(NODE_DATA(node));
+ for (node = 0; node < numnodes; node++) {
+ pg_data_t *pgdat = NODE_DATA(node);
+
+ if (pgdat->node_size != 0)
+ totalram_pages += free_all_bootmem_node(pgdat);
+ }
#ifdef CONFIG_SA1111
/* now that our DMA memory is actually so designated, we can free it */
--- /dev/null
+/*
+ * linux/arch/arm/mm/mm-nexuspci.c
+ * from linux/arch/arm/mm/mm-ebsa110.c
+ *
+ * Copyright (C) 1998-1999 Phil Blundell
+ * Copyright (C) 1998-1999 Russell King
+ *
+ * Extra MM routines for the FTV/PCI architecture
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#include <asm/mach/map.h>
+
+static struct map_desc nexuspci_io_desc[] __initdata = {
+ { INTCONT_BASE, INTCONT_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { PLX_BASE, PLX_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { PCIO_BASE, PLX_IO_START, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
+ { DUART_BASE, DUART_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { STATUS_BASE, STATUS_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+void __init nexuspci_map_io(void)
+{
+ iotable_init(nexuspci_io_desc);
+}
+++ /dev/null
-/*
- * linux/arch/arm/mm/mm-nexuspci.c
- * from linux/arch/arm/mm/mm-ebsa110.c
- *
- * Copyright (C) 1998-1999 Phil Blundell
- * Copyright (C) 1998-1999 Russell King
- *
- * Extra MM routines for the FTV/PCI architecture
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/io.h>
-
-#include <asm/mach/map.h>
-
-static struct map_desc nexuspci_io_desc[] __initdata = {
- { INTCONT_BASE, INTCONT_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { PLX_BASE, PLX_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { PCIO_BASE, PLX_IO_START, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
- { DUART_BASE, DUART_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { STATUS_BASE, STATUS_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- LAST_DESC
-};
-
-void __init nexuspci_map_io(void)
-{
- iotable_init(nexuspci_io_desc);
-}
* Function: arm720_data_abort ()
*
* Params : r0 = address of aborted instruction
+ * : r3 = saved SPSR
*
* Purpose : obtain information about current aborted instruction
*
mov pc, lr
ENTRY(cpu_arm720_data_abort)
+ tst r3, #T_BIT
+ bne .data_thumb_abort
ldr r4, [r0] @ read instruction causing problem
tst r4, r4, lsr #21 @ C = bit 20
sbc r1, r1, r1 @ r1 = C - 1
Ldata_unknown: @ Part of jumptable
mov r0, r2
mov r1, r4
- mov r2, r3
+ mov r2, sp
bl baddataabort
b ret_from_exception
addeq r7, r0, r2
b Ldata_saver7
+.data_thumb_abort:
+ ldrh r4, [r0] @ read instruction
+ tst r4, r4, lsr #12 @ C = bit 11
+ sbc r1, r1, r1 @ r1 = C - 1
+ and r2, r4, #15 << 12
+ add pc, pc, r2, lsr #10 @ lookup in table
+ nop
+
+/* 0 */ b Ldata_unknown
+/* 1 */ b Ldata_unknown
+/* 2 */ b Ldata_unknown
+/* 3 */ b Ldata_unknown
+/* 4 */ b Ldata_unknown
+/* 5 */ b .data_thumb_reg
+/* 6 */ b Ldata_simple
+/* 7 */ b Ldata_simple
+/* 8 */ b Ldata_simple
+/* 9 */ b Ldata_simple
+/* A */ b Ldata_unknown
+/* B */ b .data_thumb_pushpop
+/* C */ b .data_thumb_ldmstm
+/* D */ b Ldata_unknown
+/* E */ b Ldata_unknown
+/* F */ b Ldata_unknown
+
+.data_thumb_reg:
+ tst r4, #1 << 9
+ beq Ldata_simple
+ tst r4, #1 << 10 @ If 'S' (signed) bit is set
+ movne r1, #0 @ it must be a load instr
+ b Ldata_simple
+
+.data_thumb_pushpop:
+ tst r4, #1 << 10
+ beq Ldata_unknown
+ mov r7, #0x11
+ and r0, r4, r7
+ and r2, r4, r7, lsl #1
+ add r0, r0, r2, lsr #1
+ and r2, r4, r7, lsl #2
+ add r0, r0, r2, lsr #2
+ and r2, r4, r7, lsl #3
+ add r0, r0, r2, lsr #3
+ add r0, r0, r0, lsr #4
+ and r2, r4, #0x0100 @ catch 'R' bit for push/pop
+ add r0, r0, r2, lsr #8
+ and r0, r0, #15 @ number of regs to transfer
+ ldr r7, [sp, #13 << 2]
+ tst r4, #1 << 11
+ addne r7, r7, r0, lsl #2 @ increment SP if PUSH
+ subeq r7, r7, r0, lsr #2 @ decrement SP if POP
+ str r7, [sp, #13 << 2]
+ b Ldata_simple
+
+.data_thumb_ldmstm:
+ mov r7, #0x11
+ and r0, r4, r7
+ and r2, r4, r7, lsl #1
+ add r0, r0, r2, lsr #1
+ and r2, r4, r7, lsl #2
+ add r0, r0, r2, lsr #2
+ and r2, r4, r7, lsl #3
+ add r0, r0, r2, lsr #3
+ add r0, r0, r0, lsr #4
+ and r0, r0, #15 @ number of regs to transfer
+ and r5, r4, #7 << 8
+ ldr r7, [sp, r5, lsr #6]
+ sub r7, r7, r0, lsr #2 @ always decrement
+ str r7, [sp, r5, lsr #6]
+ b Ldata_simple
+
/*
* Function: arm720_check_bugs (void)
* : arm720_proc_init (void)
.align
/*
- * See /include/asm-arm for a definition of this structure.
+ * See linux/include/asm-arm/procinfo.h for a definition of this structure.
*/
.section ".proc.info", #alloc, #execinstr
b __arm720_setup @ cpu_flush
.long cpu_arch_name @ arch_name
.long cpu_elf_name @ elf_name
- .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT @ elf_hwcap
+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_26BIT @ elf_hwcap
.long cpu_arm720_info @ info
.long arm720_processor_functions
.size __arm720_proc_info, . - __arm720_proc_info
# Generate the constants.h header file using the compiler. We get
# the compiler to spit out assembly code, and then mundge it into
-# what we want.
+# what we want. We do this in several stages so make picks up on
+# any errors that occur along the way.
$(TOPDIR)/include/asm-arm/constants.h: constants-hdr getconstants.c
- $(CC) $(CFLAGS) -S -o - getconstants.c | \
- sed 's/^\(#define .* \)[#$$]\(.*\)/\1\2/;/^#define/!d' | \
- cat constants-hdr - > $@.tmp
- cmp $@.tmp $@ >/dev/null 2>&1 || mv $@.tmp $@; $(RM) $@.tmp
+ $(CC) $(CFLAGS) -S -o - getconstants.c > $@.tmp.1
+ sed 's/^\(#define .* \)[#$$]\(.*\)/\1\2/;/^#define/!d' $@.tmp.1 > $@.tmp.2
+ cat constants-hdr $@.tmp.2 > $@.tmp
+ cmp $@.tmp $@ >/dev/null 2>&1 || mv $@.tmp $@
+ $(RM) $@.tmp*
# Build our dependencies, and then generate the constants and
# mach-types header files. If we do it now, mkdep will pick
#include <asm/pgtable.h>
#include <asm/uaccess.h>
-#ifndef __APCS_32__
-#error APCS-32 required
+/*
+ * Make sure that the compiler and target are compatible.
+ */
+#if defined(__APCS_32__) && defined(CONFIG_CPU_26)
+#error Your compiler targets APCS-32 but this kernel requires APCS-26
+#endif
+#if defined(__APCS_26__) && defined(CONFIG_CPU_32)
+#error Your compiler targets APCS-26 but this kernel requires APCS-32
#endif
#define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n)
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
-# Last update: Thu Aug 23 12:38:13 2001
+# Last update: Fri Oct 5 18:40:53 2001
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
jupiter SA1100_JUPITER JUPITER 59
psionw ARCH_PSIONW PSIONW 60
aln SA1100_ALN ALN 61
-camelot ARCH_CAMELOT CAMELOT 62
+epxa10db ARCH_CAMELOT CAMELOT 62
gds2200 SA1100_GDS2200 GDS2200 63
psion_series7 SA1100_PSION_SERIES7 PSION_SERIES7 64
xfile SA1100_XFILE XFILE 65
gator SA1100_GATOR GATOR 103
granite ARCH_GRANITE GRANITE 104
consus SA1100_CONSUS CONSUS 105
-aaec2000_aaed20 ARCH_AAEC2000_AAED2000 AAEC2000_AAED2000 106
+agilent_aaed2000 ARCH_AAEC2000_AAED2000 AAEC2000_AAED2000 106
cdb89712 ARCH_CDB89712 CDB89712 107
graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108
adsbitsy SA1100_ADSBITSY ADSBITSY 109
plce ARCH_PLCE PLCE 111
pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112
medalb ARCH_MEDALB MEDALB 113
+eagle ARCH_EAGLE EAGLE 114
+dsc21 ARCH_DSC21 DSC21 115
+dsc24 ARCH_DSC24 DSC24 116
+ti5472 ARCH_TI5472 TI5472 117
+autcpu12 ARCH_AUTCPU12 AUTCPU12 118
+uengine ARCH_UENGINE UENGINE 119
+bluestem SA1100_BLUESTEM BLUESTEM 120
+xingu8 ARCH_XINGU8 XINGU8 121
+bushstb ARCH_BUSHSTB BUSHSTB 122
#include <asm/processor.h>
#include <asm/msr.h>
+static int mce_disabled __initdata = 0;
+
/*
* Machine Check Handler For PII/PIII
*/
* Set up machine check reporting for Intel processors
*/
-void __init intel_mcheck_init(struct cpuinfo_x86 *c)
+static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
if(c->x86 == 5)
{
+ /* Default P5 to off as its often misconnected */
+ if(mce_disabled != -1)
+ return;
machine_check_vector = pentium_machine_check;
wmb();
/* Read registers before enabling */
rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
if(done==0)
printk(KERN_INFO "Intel old style machine check architecture supported.\n");
- /* Enable MCE */
- __asm__ __volatile__ (
- "movl %%cr4, %%eax\n\t"
- "orl $0x40, %%eax\n\t"
- "movl %%eax, %%cr4\n\t" : : : "eax");
+ /* Enable MCE */
+ set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
return;
}
lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
lo&= ~(1<<4); /* Enable MCE */
wrmsr(MSR_IDT_FCR1, lo, hi);
- __asm__ __volatile__ (
- "movl %%cr4, %%eax\n\t"
- "orl $0x40, %%eax\n\t"
- "movl %%eax, %%cr4\n\t" : : : "eax");
+ set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Winchip machine check reporting enabled on CPU#%d.\n", smp_processor_id());
}
*/
-static int mce_disabled = 0;
void __init mcheck_init(struct cpuinfo_x86 *c)
{
- if(mce_disabled)
+ if(mce_disabled==1)
return;
switch(c->x86_vendor)
case X86_VENDOR_CENTAUR:
winchip_mcheck_init(c);
break;
+ default:
+ break;
}
}
mce_disabled = 1;
return 0;
}
+
+static int __init mcheck_enable(char *str)
+{
+ mce_disabled = -1;
+ return 0;
+}
+
__setup("nomce", mcheck_disable);
+__setup("mce", mcheck_enable);
MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
MODULE_DESCRIPTION("x86 generic CPUID driver");
+MODULE_LICENSE("GPL");
#include <linux/keyboard.h>
#include <asm/keyboard.h>
+int is_sony_vaio_laptop;
+
struct dmi_header
{
u8 type;
* This one isn't a bug detect for those who asked, we simply want to
* activate Sony specific goodies like the camera and jogdial..
*/
-int is_sony_vaio_laptop;
-
static __init int sony_vaio_laptop(struct dmi_blacklist *d)
{
if (is_sony_vaio_laptop == 0)
EXPORT_SYMBOL(do_BUG);
#endif
-#if defined(CONFIG_SONYPI) || defined(CONFIG_SONYPI_MODULE)
extern int is_sony_vaio_laptop;
EXPORT_SYMBOL(is_sony_vaio_laptop);
-#endif
-
MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
+MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
#define MICRO_DEBUG 0
MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
MODULE_DESCRIPTION("x86 generic MSR driver");
+MODULE_LICENSE("GPL");
break;
case MTRR_IF_INTEL:
- /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
+ /* For Intel PPro stepping <= 7, must be 4 MiB aligned
+ and not touch 0x70000000->0x7003FFFF */
if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
boot_cpu_data.x86 == 6 &&
boot_cpu_data.x86_model == 1 &&
printk (KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
return -EINVAL;
}
+ if (!(base + size < 0x70000000 || base > 0x7003FFFF) &&
+ (type == MTRR_TYPE_WRCOMB || type == MTRR_TYPE_WRBACK))
+ {
+ printk (KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
+ return -EINVAL;
+ }
}
/* Fall through */
-# BK Id: SCCS/s.Makefile 1.21 08/19/01 20:06:47 paulus
+# BK Id: SCCS/s.Makefile 1.23 09/18/01 11:19:05 paulus
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
/*
- * BK Id: SCCS/s.config.c 1.7 05/21/01 00:48:24 cort
+ * BK Id: SCCS/s.config.c 1.12 09/18/01 11:19:06 paulus
*/
#define m68k_debug_device debug_device
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-MAKESILO = $(MAKE) -C arch/$(ARCH)/tools/silo
-
-MAKEDASDFMT = $(MAKE) -C arch/$(ARCH)/tools/dasdfmt
-
-silo:
- @$(MAKESILO) silo
-
-dasdfmt:
- @$(MAKEDASDFMT) dasdfmt
-
image: vmlinux
@$(MAKEBOOT) image
O_TARGET := kernel.o
export-objs := debug.o ebcdic.o irq.o s390_ext.o smp.o s390_ksyms.o
-obj-y := lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \
+obj-y := entry.o bitmap.o traps.o time.o process.o irq.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
struct file *file, const char *user_buf,
size_t user_buf_size, loff_t * offset);
+static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char *user_buf,
+ size_t user_buf_size, loff_t * offset);
static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
char *out_buf, const char *in_buf);
static int debug_raw_format_fn(debug_info_t * id,
NULL
};
+struct debug_view debug_flush_view = {
+ "flush",
+ NULL,
+ NULL,
+ NULL,
+ &debug_input_flush_fn,
+ NULL
+};
+
struct debug_view debug_sprintf_view = {
"sprintf",
NULL,
if(!rc)
goto out;
debug_register_view(rc, &debug_level_view);
+ debug_register_view(rc, &debug_flush_view);
printk(KERN_INFO
"debug: reserved %d areas of %d pages for debugging %s\n",
nr_areas, 1 << page_order, rc->name);
return rc; /* number of input characters */
}
+
+/*
+ * flushes debug areas
+ */
+
+void debug_flush(debug_info_t* id, int area)
+{
+ unsigned long flags;
+ int i;
+
+ if(!id)
+ return;
+ spin_lock_irqsave(&id->lock,flags);
+ if(area == DEBUG_FLUSH_ALL){
+ id->active_area = 0;
+ memset(id->active_entry, 0, id->nr_areas * sizeof(int));
+ for (i = 0; i < id->nr_areas; i++)
+ memset(id->areas[i], 0, PAGE_SIZE << id->page_order);
+ printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
+ } else if(area >= 0 && area < id->nr_areas) {
+ id->active_entry[area] = 0;
+ memset(id->areas[area], 0, PAGE_SIZE << id->page_order);
+ printk(KERN_INFO
+ "debug: %s: area %i has been flushed\n",
+ id->name, area);
+ } else {
+ printk(KERN_INFO
+ "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
+ id->name, area, 0, id->nr_areas-1);
+ }
+ spin_unlock_irqrestore(&id->lock,flags);
+}
+
+/*
+ * view function: flushes debug areas
+ */
+
+static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char *user_buf,
+ size_t in_buf_size, loff_t * offset)
+{
+ char input_buf[1];
+ int rc = in_buf_size;
+
+ if (*offset != 0)
+ goto out;
+ if (copy_from_user(input_buf, user_buf, 1)){
+ rc = -EFAULT;
+ goto out;
+ }
+ if(input_buf[0] == '-') {
+ debug_flush(id, DEBUG_FLUSH_ALL);
+ goto out;
+ }
+ if (isdigit(input_buf[0])) {
+ int area = ((int) input_buf[0] - (int) '0');
+ debug_flush(id, area);
+ goto out;
+ }
+
+ printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]);
+
+ out:
+ *offset += in_buf_size;
+ return rc; /* number of input characters */
+}
+
/*
* prints debug header in raw format
*/
* R15 - kernel stack pointer
*/
- .macro SAVE_ALL psworg # system entry macro
+ .macro SAVE_ALL psworg,sync # system entry macro
stm %r13,%r15,__LC_SAVE_AREA
- stam %a2,%a4,__LC_SAVE_AREA+12
basr %r13,0 # temp base pointer
l %r13,.Lentry_base-.(%r13) # load &entry_base to %r13
tm \psworg+1,0x01 # test problem state bit
- bz BASED(.+12) # skip stack setup save
- l %r15,__LC_KERNEL_STACK # problem state -> load ksp
- lam %a2,%a4,BASED(.Lc_ac) # set ac.reg. 2 to primary space
- # and access reg. 4 to home space
-0: s %r15,BASED(.Lc_spsize) # make room for registers & psw
+ stam %a2,%a4,__LC_SAVE_AREA+12
+ .if \sync
+ bz BASED(1f) # skip stack setup save
+ .else
+ bnz BASED(0f) # from user -> load kernel stack
+ l %r14,__LC_ASYNC_STACK # are we already on the async stack ?
+ slr %r14,%r15
+ sra %r14,13
+ be BASED(1f)
+ l %r15,__LC_ASYNC_STACK # load async. stack
+ b BASED(1f)
+ .endif
+0: l %r15,__LC_KERNEL_STACK # problem state -> load ksp
+ lam %a2,%a4,BASED(.Lc_ac) # set ac.reg. 2 to primary space
+ # and ac.reg. 4 to home space
+1: s %r15,BASED(.Lc_spsize) # make room for registers & psw
n %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
stm %r0,%r12,SP_R0(%r15) # store gprs 0-12 to kernel stack
st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
xc 0(4,%r15),0(%r15) # clear back chain
.endm
- .macro RESTORE_ALL # system exit macro
+ .macro RESTORE_ALL sync # system exit macro
mvc __LC_RETURN_PSW(8),SP_PSW(%r15) # move user PSW to lowcore
lam %a0,%a15,SP_AREGS(%r15) # load the access registers
lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user
.endm
.macro GET_CURRENT
- lr %r9,%r15 # load pointer to task_struct to %r9
- n %r9,BASED(.Lc0xffffe000)
+ l %r9,BASED(.Lc0xffffe000) # load pointer to task_struct to %r9
+ al %r9,__LC_KERNEL_STACK
.endm
lm %r6,%r15,24(%r15) # load resume registers of next task
br %r14
+/*
+ * do_softirq calling function. We want to run the softirq functions on the
+ * asynchronous interrupt stack.
+ */
+ .global do_call_softirq
+do_call_softirq:
+ stm %r12,%r15,24(%r15)
+ lr %r12,%r15
+ basr %r13,0
+do_call_base:
+ l %r0,__LC_ASYNC_STACK
+ slr %r0,%r15
+ sra %r0,13
+ be 0f-do_call_base(%r13)
+ l %r15,__LC_ASYNC_STACK
+0: sl %r15,.Lc_overhead-do_call_base(%r13)
+ st %r12,0(%r15) # store backchain
+ l %r1,.Ldo_softirq-do_call_base(%r13)
+ basr %r14,%r1
+ lm %r12,%r15,24(%r12)
+ br %r14
+
/*
* SVC interrupt handler routine. System calls are synchronous events and
* are executed with interrupts enabled.
.globl system_call
system_call:
- SAVE_ALL __LC_SVC_OLD_PSW
+ SAVE_ALL __LC_SVC_OLD_PSW,1
mvi SP_PGM_OLD_ILC(%r15),1 # mark PGM_OLD_ILC as invalid
pgm_system_call:
GET_CURRENT # load pointer to task_struct to R9
tm SP_PGM_OLD_ILC(%r15),0xff
bz BASED(pgm_svcret)
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
- RESTORE_ALL
+ RESTORE_ALL 1
#
# call do_signal before return
.long sys_madvise
.long sys_getdents64 /* 220 */
.long sys_fcntl64
- .rept 255-221
+ .long sys_ni_syscall /* 222 - reserved for posix_acl */
+ .long sys_ni_syscall /* 223 - reserved for posix_acl */
+ .long sys_ni_syscall /* 224 - reserved for posix_acl */
+ .rept 255-224
.long sys_ni_syscall
.endr
* for LPSW?).
*/
stm %r13,%r15,__LC_SAVE_AREA
- stam %a2,%a4,__LC_SAVE_AREA+12
basr %r13,0 # temp base pointer
l %r13,.Lentry_base-.(%r13)# load &entry_base to %r13
tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+ stam %a2,%a4,__LC_SAVE_AREA+12
bz BASED(pgm_sv) # skip if not
tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on
bnz BASED(pgm_sv) # skip if it is
.globl io_int_handler
io_int_handler:
- SAVE_ALL __LC_IO_OLD_PSW
+ SAVE_ALL __LC_IO_OLD_PSW,0
GET_CURRENT # load pointer to task_struct to R9
la %r2,SP_PTREGS(%r15) # address of register-save area
sr %r3,%r3
bnz BASED(io_signal_return)
io_leave:
stnsm 24(%r15),0xfc # disable I/O and ext. interrupts
- RESTORE_ALL
+ RESTORE_ALL 0
#
# call do_softirq
.globl ext_int_handler
ext_int_handler:
- SAVE_ALL __LC_EXT_OLD_PSW
+ SAVE_ALL __LC_EXT_OLD_PSW,0
GET_CURRENT # load pointer to task_struct to R9
la %r2,SP_PTREGS(%r15) # address of register-save area
lh %r3,__LC_EXT_INT_CODE # error code
.globl mcck_int_handler
mcck_int_handler:
- SAVE_ALL __LC_MCK_OLD_PSW
+ SAVE_ALL __LC_MCK_OLD_PSW,0
l %r1,BASED(.Ls390_mcck)
basr %r14,%r1 # call machine check handler
mcck_return:
- RESTORE_ALL
+ RESTORE_ALL 0
#ifdef CONFIG_SMP
/*
*/
.globl restart_int_handler
restart_int_handler:
- l %r15,__LC_KERNEL_STACK # load ksp
+ l %r15,__LC_SAVE_AREA+60 # load ksp
lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
lam %a0,%a15,__LC_AREGS_SAVE_AREA
stosm 0(%r15),0x04 # now we can turn dat on
.Lc0xffffe000: .long -8192 # to round stack pointer to &task_struct
.Lc8191: .long 8191
.Lc_spsize: .long SP_SIZE
+.Lc_overhead: .long STACK_FRAME_OVERHEAD
.Lc_ac: .long 0,0,1
.Lc_ENOSYS: .long -ENOSYS
.Lc4: .long 4
* $m0,10#2a +$00010203040506070809101112131415#42
*
*/
-
+#define TRUE 1
+#define FALSE 0
#include <asm/gdb-stub.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/pgtable.h>
#include <asm/system.h>
+#include <linux/stddef.h>
+#define S390_REGS_COMMON_SIZE offsetof(struct gdb_pt_regs,orig_gpr2)
/*
* external low-level support routines
*/
-extern int putDebugChar(char c); /* write a single character */
-extern char getDebugChar(void); /* read and return a single char */
+
extern void fltr_set_mem_err(void);
extern void trap_low(void);
while (count-- > 0) {
ch = *(mem++);
+#if 0
if (mem_err)
return 0;
+#endif
*buf++ = hexchars[ch >> 4];
*buf++ = hexchars[ch & 0xf];
}
ch = hex(*buf++) << 4;
ch |= hex(*buf++);
*(mem++) = ch;
+#if 0
if (mem_err)
return 0;
+#endif
}
/* set_mem_fault_trap(0); */
return (numChars);
}
-void gdb_stub_get_non_pt_regs(gdb_pt_regs *regs)
+void gdb_stub_get_non_pt_regs(struct gdb_pt_regs *regs)
{
s390_fp_regs *fpregs=®s->fp_regs;
int has_ieee=save_fp_regs1(fpregs);
}
}
-void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs)
+void gdb_stub_set_non_pt_regs(struct gdb_pt_regs *regs)
{
restore_fp_regs1(®s->fp_regs);
}
* returns 1 if you should skip the instruction at the trap address, 0
* otherwise.
*/
-void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval)
+void gdb_stub_handle_exception(struct gdb_pt_regs *regs,int sigval)
{
int trap; /* Trap type */
int addr;
/*
* reply to host that an exception has occurred
*/
+#if 0
send_signal(sigval);
-
+#endif
/*
* Wait for input from remote GDB
*/
- while (1) {
+ while (1)
+ {
output_buffer[0] = 0;
getpacket(input_buffer);
switch (input_buffer[0])
{
case '?':
+#if 0
send_signal(sigval);
+#endif
continue;
case 'd':
case 'g':
gdb_stub_get_non_pt_regs(regs);
ptr = output_buffer;
- ptr= mem2hex((char *)regs,ptr,sizeof(s390_regs_common),FALSE);
+ ptr= mem2hex((char *)regs,ptr,S390_REGS_COMMON_SIZE,FALSE);
ptr= mem2hex((char *)®s->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
- ptr = mem2hex((char *)®s->fp_regs, ptr,sizeof(s390_fp_regs));
+ ptr = mem2hex((char *)®s->fp_regs, ptr,sizeof(s390_fp_regs),FALSE);
break;
/*
*/
case 'G':
ptr=input_buffer;
- hex2mem (ptr, (char *)regs,sizeof(s390_regs_common), FALSE);
- ptr+=sizeof(s390_regs_common)*2;
+ hex2mem (ptr, (char *)regs,S390_REGS_COMMON_SIZE, FALSE);
+ ptr+=S390_REGS_COMMON_SIZE*2;
hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
ptr+=NUM_CRS*CR_SIZE*2;
- hex2mem (ptr, (char *)regs->fp_regs,sizeof(s390_fp_regs), FALSE);
+ hex2mem (ptr, (char *)®s->fp_regs,sizeof(s390_fp_regs), FALSE);
gdb_stub_set_non_pt_regs(regs);
strcpy(output_buffer,"OK");
break;
if (hexToInt(&ptr, &addr)
&& *ptr++ == ','
&& hexToInt(&ptr, &length)
- && *ptr++ == ':') {
+ && *ptr++ == ':')
+ {
if (hex2mem(ptr, (char *)addr, length, 1))
strcpy(output_buffer, "OK");
else
ptr = &input_buffer[1];
if (hexToInt(&ptr, &addr))
- regs->cp0_epc = addr;
-
+ regs->psw.addr = addr;
/*
* Need to flush the instruction cache here, as we may
* have deposited a breakpoint, and the icache probably
* There is no single step insn in the MIPS ISA, so we
* use breakpoints and continue, instead.
*/
+#if 0
single_step(regs);
+#endif
flush_cache_all();
return;
/* NOTREACHED */
+ break;
- }
- break;
-
- } /* switch */
-
- /*
- * reply to the request
- */
+ } /* switch */
+ /*
+ * reply to the request
+ */
+
putpacket(output_buffer);
-
+
} /* while */
}
{
if (!gdb_stub_initialised)
return;
- __asm__ __volatile__(
- ".globl breakinst\n"
- "breakinst:\t.word %0\n\t"
- :
- : "i" (S390_BREAKPOINT_U16)
- :
- );
+ asm volatile (".globl breakinst\n"
+ "breakinst:\t.word %0"
+ : : "i" (S390_BREAKPOINT_U16) );
}
.org 0x10000
startup:basr %r13,0 # get base
.LPG1: lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
- la %r12,parmarea-.LPG1(%r13) # pointer to parameter area
+ la %r12,_pstart-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore
mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
#
-# find out memory size.
+# find memory chunks.
#
mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
- lhi %r2,1
- sll %r2,17 # test in increments of 128KB
- lr %r1,%r2
- ahi %r1,-4 # test last word in the segment
-.Lloop:
- l %r0,0(%r1) # test 128KB segment
- st %r0,0(%r1)
- ar %r1,%r2 # add 128KB
- bnm .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop
-.Lchkmem:
- n %r1,.L4malign-.LPG1(%r13) # align to multiples of 4M
- l %r2,.Lmemsize-.LPG1(%r13) # address of variable memory_size
- st %r1,0(%r2) # store memory size
-
+ la %r1,1 # test in increments of 128KB
+ sll %r1,17
+ l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
+ slr %r4,%r4 # set start of chunk to zero
+ slr %r5,%r5 # set end of chunk to zero
+ slr %r6,%r6 # set access code to zero
+.Lloop:
+ tprot 0(%r5),0 # test protection of first byte
+ ipm %r7
+ srl %r7,28
+ clr %r6,%r7 # compare cc with last access code
+ be .Lsame-.LPG1(%r13)
+ clr %r4,%r5 # chunk size > 0?
+ be .Lsize0-.LPG1(%r13)
+ st %r4,0(%r3) # store start address of chunk
+ lr %r0,%r5
+ slr %r0,%r4
+ st %r0,4(%r3) # store size of chunk
+ st %r6,8(%r3) # store type of chunk
+ la %r3,12(%r3)
+ lr %r4,%r5 # set start to end
+.Lsize0:
+ lr %r6,%r7 # set access code to last cc
+.Lsame:
+ ar %r5,%r1 # add 128KB to end of chunk
+ bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop
+.Lchkmem: # > 2GB or tprot got a program check
+ clr %r4,%r5 # chunk size > 0?
+ be .Ldonemem-.LPG1(%r13)
+ st %r4,0(%r3) # store start address of chunk
+ lr %r0,%r5
+ slr %r0,%r4
+ st %r0,4(%r3) # store size of chunk
+ st %r6,8(%r3) # store type of chunk
+.Ldonemem:
+ l %r1,.Lmemsize-.LPG1(%r13) # address of variable memory_size
+ st %r5,0(%r1) # store last end to memory size
+
l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
#
# find out if we are running under VM
.Lentry:.long 0x00080000,0x80000000 + _stext
.Lctl: .long 0x04b50002 # cr0: various things
.long 0 # cr1: primary space segment table
- .long 0 # cr2: access register translation
+ .long .Lduct # cr2: dispatchable unit control table
.long 0 # cr3: instruction authorization
.long 0 # cr4: instruction authorization
.long 0 # cr5: various things
.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
-.L4malign:.long 0xffc00000
.Lmemsize:.long memory_size
+.Lmchunk:.long memory_chunk
.Lmflags:.long machine_flags
+ .org PARMAREA-64
+.Lduct: .long 0,0,0,0,0,0,0,0
+ .long 0,0,0,0,0,0,0,0
+
#
# params at 10400 (setup.h)
#
.org PARMAREA
-parmarea:
+ .global _pstart
+_pstart:
.long 0,0 # IPL_DEVICE
.long 0,RAMDISK_ORIGIN # INITRD_START
- .long 0,0x800000 # INITRD_SIZE
+ .long 0,RAMDISK_SIZE # INITRD_SIZE
.org COMMAND_LINE
.byte "root=/dev/ram0 ro"
.byte 0
+ .org 0x11000
+ .global _pend
+_pend:
-#
-# startup-code, running in virtual mode
-#
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000
-#else
- .org 0x10800
#endif
+
+#
+# startup-code, running in virtual mode
+#
.globl _stext
_stext: basr %r13,0 # get base
.LPG2:
#
-# Setup lowcore
+# Setup stack
#
- l %r1,__LC_IPLDEV # load ipl device number
- spx .Lprefix-.LPG2(%r13) # set prefix to linux lowcore
- st %r1,__LC_IPLDEV # store ipl device number
l %r15,.Linittu-.LPG2(%r13)
- ahi %r15,8192 # init_task_union + 8191
+ ahi %r15,8192 # init_task_union + 8192
st %r15,__LC_KERNEL_STACK # set end of kernel stack
ahi %r15,-96
xc 0(4,%r15),0(%r15) # set backchain to zero
- lhi %r0,-1
- st %r0,__LC_KERNEL_LEVEL # set interrupt count to -1
+
#
# clear bss memory
#
#
.align 8
.Ldw: .long 0x000a0000,0x00000000
-.Lprefix: .long init_S390_lowcore
.Linittu: .long init_task_union
.Lstart: .long start_kernel
.Lbss_bgn: .long __bss_start
+++ /dev/null
-/*
- * arch/s390/kernel/lowcore.S
- * S390 lowcore definition.
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Hartmut Penner (hp@de.ibm.com)
- * Martin Schwidefsky (schwidefsky@de.ibm.com),
- */
-
-#include <asm/lowcore.h>
- .align 4096
- .globl init_S390_lowcore
-init_S390_lowcore:
- .long _RESTART_PSW_MASK
- .long restart_int_handler + _ADDR_31
- .long 0,0
- .long 0,0
-EXT_OLD: .long 0,0
-SVC_OLD: .long 0,0
-PGM_OLD: .long 0,0
-MCCK_OLD:.long 0,0
-IO_OLD: .long 0,0
- .long 0,0,0,0,0,0
-#
-# new psws need all to be physical
-# because we start with dat off
-#
-EXT_PSW: .long _EXT_PSW_MASK
- .long ext_int_handler + _ADDR_31
-#
-SVC_PSW: .long _SVC_PSW_MASK
- .long system_call + _ADDR_31
-#
-PGM_PSW: .long _PGM_PSW_MASK
- .long pgm_check_handler + _ADDR_31
-#
-MCCK_PSW:.long _MCCK_PSW_MASK
- .long mcck_int_handler + _ADDR_31
-#
-IO_PSW: .long _IO_PSW_MASK
- .long io_int_handler + _ADDR_31
-#
-#
-#
-EXTERNAL_PARAMETER: .long 0
-CPU_ADDRESS: .word 0
-EXT_INTERRUPT_CODE: .word 0
-SVC_ILC: .word 0
-SVC_CODE: .word 0
-PGM_ILC: .word 0
-PGM_CODE: .word 0
-TRANS_EXC_ADDR: .long 0 # 090
- .fill 0xC00-0x094,1,0
-SAVE_AREA: .fill 0x40,1,0 # C00
-KERNEL_STACK: .long 0 # C40
-KERNEL_LEVEL: .long 0 # C44
-CPUID: .long 0,0 # C48
- .fill 0x1000-0xC50,1,0
-
#include <asm/processor.h>
#include <asm/irq.h>
-spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
-
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
/*
void show_regs(struct pt_regs *regs)
{
char buff[80];
- int line;
+ int i, line;
printk("CPU: %d\n",smp_processor_id());
printk("Process %s (pid: %d, stackpage=%08X)\n",
for (line = 0; sprintf_regs(line, buff, current, regs); line++)
printk(buff);
+
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ {
+ printk("User Code:\n");
+ memset(buff, 0, 20);
+ copy_from_user(buff,
+ (char *) (regs->psw.addr & PSW_ADDR_MASK), 20);
+ for (i = 0; i < 20; i++)
+ printk("%02x ", buff[i]);
+ printk("\n");
+ }
}
char *task_show_regs(struct task_struct *task, char *buffer)
asmlinkage int sys_fork(struct pt_regs regs)
{
- int ret;
-
- lock_kernel();
- ret = do_fork(SIGCHLD, regs.gprs[15], ®s, 0);
- unlock_kernel();
- return ret;
+ return do_fork(SIGCHLD, regs.gprs[15], ®s, 0);
}
asmlinkage int sys_clone(struct pt_regs regs)
{
unsigned long clone_flags;
unsigned long newsp;
- int ret;
- lock_kernel();
clone_flags = regs.gprs[3];
newsp = regs.orig_gpr2;
if (!newsp)
newsp = regs.gprs[15];
- ret = do_fork(clone_flags, newsp, ®s, 0);
- unlock_kernel();
- return ret;
+ return do_fork(clone_flags, newsp, ®s, 0);
}
/*
/*
* memory management
*/
-EXPORT_SYMBOL(_oi_bitmap);
-EXPORT_SYMBOL(_ni_bitmap);
-EXPORT_SYMBOL(_zb_findmap);
-EXPORT_SYMBOL(__copy_from_user_fixup);
-EXPORT_SYMBOL(__copy_to_user_fixup);
+EXPORT_SYMBOL_NOVERS(_oi_bitmap);
+EXPORT_SYMBOL_NOVERS(_ni_bitmap);
+EXPORT_SYMBOL_NOVERS(_zb_findmap);
+EXPORT_SYMBOL_NOVERS(__copy_from_user_fixup);
+EXPORT_SYMBOL_NOVERS(__copy_to_user_fixup);
/*
* semaphore ops
EXPORT_SYMBOL(csum_fold);
EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_device);
+EXPORT_SYMBOL_NOVERS(do_call_softirq);
-#if CONFIG_IP_MULTICAST
-/* Required for lcs gigabit ethernet multicast support */
-EXPORT_SYMBOL(arp_mc_map);
-#endif
unsigned int console_device = -1;
unsigned long memory_size = 0;
unsigned long machine_flags = 0;
+struct { unsigned long addr, size, type; } memory_chunk[16];
+#define CHUNK_READ_WRITE 0
+#define CHUNK_READ_ONLY 1
__u16 boot_cpu_addr;
int cpus_initialized = 0;
unsigned long cpu_initialized = 0;
* Setup function called from init/main.c just after the banner
* was printed.
*/
+extern char _pstart, _pend, _stext;
+
void __init setup_arch(char **cmdline_p)
{
unsigned long bootmap_size;
unsigned long start_pfn, end_pfn;
static unsigned int smptrap=0;
unsigned long delay = 0;
+ struct _lowcore *lowcore;
+ int i;
if (smptrap)
return;
smptrap=1;
- /*
- * Setup lowcore information for boot cpu
- */
- cpu_init();
- boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
- __cpu_logical_map[0] = boot_cpu_addr;
-
/*
* print what head.S has found out about the machine
*/
ROOT_DEV = to_kdev_t(0x0100);
memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/
- memory_end = memory_size;
+ memory_end = memory_size & ~0x400000UL; /* align memory end to 4MB */
/*
* We need some free virtual space to be able to do vmalloc.
* On a machine with 2GB memory we make sure that we have at
bootmap_size = init_bootmem(start_pfn, end_pfn);
/*
- * Register RAM pages with the bootmem allocator.
+ * Register RAM areas with the bootmem allocator.
*/
- free_bootmem(start_pfn << PAGE_SHIFT,
- (end_pfn - start_pfn) << PAGE_SHIFT);
+ for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) {
+ unsigned long start_chunk, end_chunk;
+
+ if (memory_chunk[i].type != CHUNK_READ_WRITE)
+ continue;
+ start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
+ start_chunk >>= PAGE_SHIFT;
+ end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
+ end_chunk >>= PAGE_SHIFT;
+ if (start_chunk < start_pfn)
+ start_chunk = start_pfn;
+ if (end_chunk > end_pfn)
+ end_chunk = end_pfn;
+ if (start_chunk < end_chunk)
+ free_bootmem(start_chunk << PAGE_SHIFT,
+ (end_chunk - start_chunk) << PAGE_SHIFT);
+ }
/*
* Reserve the bootmem bitmap itself as well. We do this in two
}
#endif
+ /*
+ * Setup lowcore for boot cpu
+ */
+ lowcore = (struct _lowcore *)
+ __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
+ memset(lowcore, 0, PAGE_SIZE);
+ lowcore->restart_psw.mask = _RESTART_PSW_MASK;
+ lowcore->restart_psw.addr = _ADDR_31 + (addr_t) &restart_int_handler;
+ lowcore->external_new_psw.mask = _EXT_PSW_MASK;
+ lowcore->external_new_psw.addr = _ADDR_31 + (addr_t) &ext_int_handler;
+ lowcore->svc_new_psw.mask = _SVC_PSW_MASK;
+ lowcore->svc_new_psw.addr = _ADDR_31 + (addr_t) &system_call;
+ lowcore->program_new_psw.mask = _PGM_PSW_MASK;
+ lowcore->program_new_psw.addr = _ADDR_31 + (addr_t) &pgm_check_handler;
+ lowcore->mcck_new_psw.mask = _MCCK_PSW_MASK;
+ lowcore->mcck_new_psw.addr = _ADDR_31 + (addr_t) &mcck_int_handler;
+ lowcore->io_new_psw.mask = _IO_PSW_MASK;
+ lowcore->io_new_psw.addr = _ADDR_31 + (addr_t) &io_int_handler;
+ lowcore->ipl_device = S390_lowcore.ipl_device;
+ lowcore->kernel_stack = ((__u32) &init_task_union) + 8192;
+ lowcore->async_stack = (__u32)
+ __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0) + 8192;
+ set_prefix((__u32) lowcore);
+ cpu_init();
+ boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+ __cpu_logical_map[0] = boot_cpu_addr;
+
+ /*
+ * Create kernel page tables and switch to virtual addressing.
+ */
paging_init();
res = alloc_bootmem_low(sizeof(struct resource));
}
/*
- * Get CPU information for use by the procfs.
+ * get_cpuinfo - Get information on one CPU for use by procfs.
+ *
+ * Prints info on the next CPU into buffer. Beware, doesn't check for
+ * buffer overflow. Current implementation of procfs assumes that the
+ * resulting data is <= 1K.
+ *
+ * Args:
+ * buffer -- you guessed it, the data buffer
+ * cpu_np -- Input: next cpu to get (start at 0). Output: Updated.
+ *
+ * Returns number of bytes written to buffer.
*/
-int get_cpuinfo(char * buffer)
+int get_cpuinfo(char *buffer, unsigned *cpu_np)
{
struct cpuinfo_S390 *cpuinfo;
char *p = buffer;
- int i;
-
- p += sprintf(p,"vendor_id : IBM/S390\n"
- "# processors : %i\n"
- "bogomips per cpu: %lu.%02lu\n",
- smp_num_cpus, loops_per_jiffy/(500000/HZ),
- (loops_per_jiffy/(5000/HZ))%100);
- for (i = 0; i < smp_num_cpus; i++) {
- cpuinfo = &safe_get_cpu_lowcore(i).cpu_data;
- p += sprintf(p,"processor %i: "
- "version = %02X, "
- "identification = %06X, "
- "machine = %04X\n",
- i, cpuinfo->cpu_id.version,
- cpuinfo->cpu_id.ident,
- cpuinfo->cpu_id.machine);
- }
+ unsigned n;
+
+ n = *cpu_np;
+ while (n < NR_CPUS && (cpu_online_map & (1 << n)) == 0)
+ n++;
+ if (n >= NR_CPUS) {
+ *cpu_np = NR_CPUS;
+ return (0);
+ }
+ *cpu_np = n + 1;
+
+ if (n == 0) {
+ p += sprintf(p,"vendor_id : IBM/S390\n"
+ "# processors : %i\n"
+ "bogomips per cpu: %lu.%02lu\n",
+ smp_num_cpus, loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ))%100);
+ }
+ cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
+ p += sprintf(p,"processor %i: "
+ "version = %02X, "
+ "identification = %06X, "
+ "machine = %04X\n",
+ n, cpuinfo->cpu_id.version,
+ cpuinfo->cpu_id.ident,
+ cpuinfo->cpu_id.machine);
return p - buffer;
}
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
+#include <linux/personality.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
-#define DEBUG_SIG 0
-
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-/* pretcode & sig are used to store the return addr on Intel
- & the signal no as the first parameter we do this differently
- using gpr14 & gpr2. */
-
-#define SIGFRAME_COMMON \
-__u8 callee_used_stack[__SIGNAL_FRAMESIZE]; \
-struct sigcontext sc; \
-_sigregs sregs; \
-__u8 retcode[S390_SYSCALL_SIZE];
typedef struct
{
- SIGFRAME_COMMON
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
+ struct sigcontext sc;
+ _sigregs sregs;
+ __u8 retcode[S390_SYSCALL_SIZE];
} sigframe;
typedef struct
{
- SIGFRAME_COMMON
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
+ __u8 retcode[S390_SYSCALL_SIZE];
struct siginfo info;
struct ucontext uc;
} rt_sigframe;
err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
if(!err)
{
- regs->orig_gpr2 = -1; /* disable syscall checks */
+ regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
return(err);
}
-static int
-restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
- _sigregs *sregs,sigset_t *set)
-{
- unsigned int err;
-
- err=restore_sigregs(regs,sregs);
- if(!err)
- err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE);
- return(err);
-}
-
-int sigreturn_common(struct pt_regs *regs,int framesize)
+asmlinkage long sys_sigreturn(struct pt_regs *regs)
{
sigframe *frame = (sigframe *)regs->gprs[15];
sigset_t set;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- return -1;
- if (restore_sigcontext(&frame->sc,regs,&frame->sregs,&set))
- return -1;
+ goto badframe;
+ if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
+ goto badframe;
+
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(¤t->sigmask_lock);
current->blocked = set;
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
- return 0;
-}
-
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
-{
- if (sigreturn_common(regs,sizeof(sigframe)))
+ if (restore_sigregs(regs, &frame->sregs))
goto badframe;
+
return regs->gprs[2];
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
{
rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
+ sigset_t set;
- if (sigreturn_common(regs,sizeof(rt_sigframe)))
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
+ if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ if (restore_sigregs(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
/*
* Set up a signal frame.
return (void *)((sp - frame_size) & -8ul);
}
-static void *setup_frame_common(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs,
- int frame_size,u16 retcode)
+static inline int map_signal(int sig)
{
- sigframe *frame;
- int err;
+ if (current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32)
+ return current->exec_domain->signal_invmap[sig];
+ else
+ return sig;
+}
- frame = get_sigframe(ka, regs,frame_size);
- if (!access_ok(VERIFY_WRITE, frame,frame_size))
- return 0;
- err = save_sigregs(regs,&frame->sregs);
- if(!err)
- err=__put_user(&frame->sregs,&frame->sc.sregs);
- if(!err)
+static void setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs * regs)
+{
+ sigframe *frame = get_sigframe(ka, regs, sizeof(sigframe));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
+ goto give_sigsegv;
+
+ if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
+ goto give_sigsegv;
+
+ if (save_sigregs(regs, &frame->sregs))
+ goto give_sigsegv;
+ if (__put_user(&frame->sregs, &frame->sc.sregs))
+ goto give_sigsegv;
- err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE);
- if(!err)
- {
- regs->gprs[2]=(current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig);
- /* Set up registers for signal handler */
- regs->gprs[15] = (addr_t)frame;
- regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
- regs->psw.mask = _USER_PSW_MASK;
- }
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
- err |= __put_user(retcode, (u16 *)(frame->retcode));
+ if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
+ (u16 *)(frame->retcode)))
+ goto give_sigsegv;
}
- return(err ? 0:frame);
-}
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs)
-{
- sigframe *frame;
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK;
- if((frame=setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
- (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
- goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
- /* Martin wants this for pthreads */
+ regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->sc;
/* We forgot to include these in the sigcontext.
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
- rt_sigframe *frame;
- addr_t orig_sp=regs->gprs[15];
- int err;
+ int err = 0;
+ rt_sigframe *frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
+ goto give_sigsegv;
- if((frame=setup_frame_common(sig,ka,set,regs,sizeof(rt_sigframe),
- (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
+ if (copy_siginfo_to_user(&frame->info, info))
goto give_sigsegv;
-
- err = copy_siginfo_to_user(&frame->info, info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(orig_sp),
+ err |= __put_user(sas_ss_flags(regs->gprs[15]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= __put_user(&frame->sc,&frame->uc.sc);
- regs->gprs[3] = (addr_t)&frame->info;
- regs->gprs[4] = (addr_t)&frame->uc;
-
+ err |= save_sigregs(regs, &frame->uc.uc_mcontext);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+ } else {
+ regs->gprs[14] = FIX_PSW(frame->retcode);
+ err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
+ (u16 *)(frame->retcode));
+ }
+
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK;
+
+ regs->gprs[2] = map_signal(sig);
+ regs->gprs[3] = (addr_t)&frame->info;
+ regs->gprs[4] = (addr_t)&frame->uc;
return;
give_sigsegv:
continue;
/* FALLTHRU */
- case SIGSTOP:
+ case SIGSTOP: {
+ struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+ sig = current->p_pptr->sig;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
+ }
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+unsigned long cpu_online_map;
+
/*
* Setup routine for controlling SMP activation
*
extern void reipl(unsigned long devno);
+static sigp_ccode smp_ext_bitcall(int, ec_bit_sig);
+static void smp_ext_bitcall_others(ec_bit_sig);
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
+ */
+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
+
+struct call_data_struct {
+ void (*func) (void *info);
+ void *info;
+ atomic_t started;
+ atomic_t finished;
+ int wait;
+};
+
+static struct call_data_struct * call_data;
+
+/*
+ * 'Call function' interrupt callback
+ */
+static void do_call_function(void)
+{
+ void (*func) (void *info) = call_data->func;
+ void *info = call_data->info;
+ int wait = call_data->wait;
+
+ atomic_inc(&call_data->started);
+ (*func)(info);
+ if (wait)
+ atomic_inc(&call_data->finished);
+}
+
+/*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ */
+
+int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+ int wait)
+/*
+ * [SUMMARY] Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <nonatomic> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+{
+ struct call_data_struct data;
+ int cpus = smp_num_cpus-1;
+
+ if (!cpus || !atomic_read(&smp_commenced))
+ return 0;
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.started, 0);
+ data.wait = wait;
+ if (wait)
+ atomic_set(&data.finished, 0);
+
+ spin_lock_bh(&call_lock);
+ call_data = &data;
+ /* Send a message to all other CPUs and wait for them to respond */
+ smp_ext_bitcall_others(ec_call_function);
+
+ /* Wait for response */
+ while (atomic_read(&data.started) != cpus)
+ barrier();
+
+ if (wait)
+ while (atomic_read(&data.finished) != cpus)
+ barrier();
+ spin_unlock_bh(&call_lock);
+
+ return 0;
+}
+
+
+/*
+ * Various special callbacks
+ */
+
void do_machine_restart(void)
{
smp_send_stop();
void do_ext_call_interrupt(struct pt_regs *regs, __u16 code)
{
- ec_ext_call *ec, *next;
int bits;
/*
do_machine_halt();
if (test_bit(ec_power_off, &bits))
do_machine_power_off();
- if (test_bit(ec_ptlb, &bits))
- local_flush_tlb();
-
- /*
- * Handle external call commands with a parameter area
- */
- do {
- ec = (ec_ext_call *) atomic_read(&S390_lowcore.ext_call_queue);
- } while (atomic_compare_and_swap((int) ec, 0,
- &S390_lowcore.ext_call_queue));
- if (ec == NULL)
- return; /* no command signals */
-
- /* Make a fifo out of the lifo */
- next = ec->next;
- ec->next = NULL;
- while (next != NULL) {
- ec_ext_call *tmp = next->next;
- next->next = ec;
- ec = next;
- next = tmp;
- }
-
- /* Execute every sigp command on the queue */
- while (ec != NULL) {
- switch (ec->cmd) {
- case ec_callback_async: {
- void (*func)(void *info);
- void *info;
-
- func = ec->func;
- info = ec->info;
- atomic_set(&ec->status,ec_executing);
- (func)(info);
- return;
- }
- case ec_callback_sync:
- atomic_set(&ec->status,ec_executing);
- (ec->func)(ec->info);
- atomic_set(&ec->status,ec_done);
- return;
- default:
- }
- ec = ec->next;
- }
-}
-
-/*
- * Send a callback sigp to another cpu.
- */
-sigp_ccode
-smp_ext_call(int cpu, void (*func)(void *info), void *info, int wait)
-{
- struct _lowcore *lowcore = &get_cpu_lowcore(cpu);
- sigp_ccode ccode;
- ec_ext_call ec;
-
- ec.cmd = wait ? ec_callback_sync : ec_callback_async;
- atomic_set(&ec.status, ec_pending);
- ec.func = func;
- ec.info = info;
- do {
- ec.next = (ec_ext_call*) atomic_read(&lowcore->ext_call_queue);
- } while (atomic_compare_and_swap((int) ec.next, (int)(&ec),
- &lowcore->ext_call_queue));
- /*
- * We try once to deliver the signal. There are four possible
- * return codes:
- * 0) Order code accepted - can't show up on an external call
- * 1) Status stored - fine, wait for completion.
- * 2) Busy - there is another signal pending. Thats fine too, because
- * do_ext_call from the pending signal will execute all signals on
- * the queue. We wait for completion.
- * 3) Not operational - something very bad has happened to the cpu.
- * do not wait for completion.
- */
- ccode = signal_processor(cpu, sigp_external_call);
-
- if (ccode != sigp_not_operational)
- /* wait for completion, FIXME: possible seed of a deadlock */
- while (atomic_read(&ec.status) != (wait?ec_done:ec_executing));
-
- return ccode;
-}
-
-/*
- * Send a callback sigp to every other cpu in the system.
- */
-void smp_ext_call_others(void (*func)(void *info), void *info, int wait)
-{
- struct _lowcore *lowcore;
- ec_ext_call ec[NR_CPUS];
- sigp_ccode ccode;
- int i;
-
- for (i = 0; i < smp_num_cpus; i++) {
- if (smp_processor_id() == i)
- continue;
- lowcore = &get_cpu_lowcore(i);
- ec[i].cmd = wait ? ec_callback_sync : ec_callback_async;
- atomic_set(&ec[i].status, ec_pending);
- ec[i].func = func;
- ec[i].info = info;
- do {
- ec[i].next = (ec_ext_call *)
- atomic_read(&lowcore->ext_call_queue);
- } while (atomic_compare_and_swap((int) ec[i].next, (int)(ec+i),
- &lowcore->ext_call_queue));
- ccode = signal_processor(i, sigp_external_call);
- }
-
- /* wait for completion, FIXME: possible seed of a deadlock */
- for (i = 0; i < smp_num_cpus; i++) {
- if (smp_processor_id() == i)
- continue;
- while (atomic_read(&ec[i].status) !=
- (wait ? ec_done:ec_executing));
- }
+ if (test_bit(ec_call_function, &bits))
+ do_call_function();
}
/*
* Send an external call sigp to another cpu and return without waiting
* for its completion.
*/
-sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
+static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
{
struct _lowcore *lowcore = &get_cpu_lowcore(cpu);
sigp_ccode ccode;
* Send an external call sigp to every other cpu in the system and
* return without waiting for its completion.
*/
-void smp_ext_bitcall_others(ec_bit_sig sig)
+static void smp_ext_bitcall_others(ec_bit_sig sig)
{
struct _lowcore *lowcore;
sigp_ccode ccode;
}
}
-/*
- * cycles through all the cpus,
- * returns early if info is not NULL & the processor has something
- * of intrest to report in the info structure.
- * it returns the next cpu to check if it returns early.
- * i.e. it should be used as follows if you wish to receive info.
- * next_cpu=0;
- * do
- * {
- * info->cpu=next_cpu;
- * next_cpu=smp_signal_others(order_code,parameter,1,info);
- * ... check info here
- * } while(next_cpu<=smp_num_cpus)
- *
- * if you are lazy just use it like
- * smp_signal_others(order_code,parameter,0,1,NULL);
- */
-int smp_signal_others(sigp_order_code order_code, u32 parameter,
- int spin, sigp_info *info)
-{
- sigp_ccode ccode;
- u32 dummy;
- u16 i;
-
- if (info)
- info->intresting = 0;
- for (i = (info ? info->cpu : 0); i < smp_num_cpus; i++) {
- if (smp_processor_id() != i) {
- do {
- ccode = signal_processor_ps(
- (info ? &info->status : &dummy),
- parameter, i, order_code);
- } while(spin && ccode == sigp_busy);
- if (info && ccode != sigp_order_code_accepted) {
- info->intresting = 1;
- info->cpu = i;
- info->ccode = ccode;
- i++;
- break;
- }
- }
- }
- return i;
-}
-
/*
* this function sends a 'stop' sigp to all other CPUs in the system.
* it goes straight through.
/* stop all processors */
- smp_signal_others(sigp_stop, 0, 1, NULL);
+ for (i = 0; i < smp_num_cpus; i++) {
+ if (smp_processor_id() != i) {
+ int ccode;
+ do {
+ ccode = signal_processor_ps(
+ &dummy,
+ 0,
+ i,
+ sigp_stop);
+ } while(ccode == sigp_busy);
+ }
+ }
/* store status of all processors in their lowcores (real 0) */
void smp_ptlb_all(void)
{
- smp_ext_call_others(smp_ptlb_callback, NULL, 1);
+ smp_call_function(smp_ptlb_callback, NULL, 0, 1);
local_flush_tlb();
}
parms.end_ctl = cr;
parms.orvals[cr] = 1 << bit;
parms.andvals[cr] = 0xFFFFFFFF;
- smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
+ smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
}
__ctl_set_bit(cr, bit);
}
parms.end_ctl = cr;
parms.orvals[cr] = 0x00000000;
parms.andvals[cr] = ~(1 << bit);
- smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
+ smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
}
__ctl_clear_bit(cr, bit);
}
-/*
- * Call a function on all other processors
- */
-
-int
-smp_call_function(void (*func)(void *info), void *info, int retry, int wait)
-/*
- * [SUMMARY] Run a function on all other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <retry> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler, you may call it from a bottom half handler.
- */
-{
- if (atomic_read(&smp_commenced) != 0)
- smp_ext_call_others(func, info, wait);
- return 0;
-}
-
/*
* Lets check how many CPUs we have.
*/
current->processor = 0;
smp_num_cpus = 1;
+ cpu_online_map = 1;
for (curr_cpu = 0;
curr_cpu <= 65535 && smp_num_cpus < max_cpus; curr_cpu++) {
if ((__u16) curr_cpu == boot_cpu_addr)
* Activate a secondary processor.
*/
extern void init_100hz_timer(void);
+extern int pfault_init(void);
extern int pfault_token(void);
int __init start_secondary(void *cpuvoid)
init_tasks[cpu] = idle;
cpu_lowcore=&get_cpu_lowcore(cpu);
- cpu_lowcore->kernel_stack=idle->thread.ksp;
- __asm__ __volatile__("stctl 0,15,%0\n\t"
- "stam 0,15,%1"
+ cpu_lowcore->save_area[15] = idle->thread.ksp;
+ cpu_lowcore->kernel_stack = (idle->thread.ksp | 8191) + 1;
+ __asm__ __volatile__("la 1,%0\n\t"
+ "stctl 0,15,0(1)\n\t"
+ "la 1,%1\n\t"
+ "stam 0,15,0(1)"
: "=m" (cpu_lowcore->cregs_save_area[0]),
"=m" (cpu_lowcore->access_regs_save_area[0])
- : : "memory");
+ : : "1", "memory");
eieio();
signal_processor(cpu,sigp_restart);
+ /* Mark this cpu as online */
+ set_bit(cpu, &cpu_online_map);
}
/*
}
/*
- * Cycle through the processors sending APIC IPIs to boot each.
+ * Cycle through the processors sending sigp_restart to boot each.
*/
void __init smp_boot_cpus(void)
{
- struct _lowcore *curr_lowcore;
+ unsigned long async_stack;
sigp_ccode ccode;
int i;
for(i = 0; i < smp_num_cpus; i++)
{
- curr_lowcore = (struct _lowcore *)
- __get_free_page(GFP_KERNEL|GFP_DMA);
- if (curr_lowcore == NULL) {
- printk("smp_boot_cpus failed to allocate prefix memory\n");
- break;
- }
- lowcore_ptr[i] = curr_lowcore;
- memcpy(curr_lowcore, &S390_lowcore, sizeof(struct _lowcore));
+ lowcore_ptr[i] = (struct _lowcore *)
+ __get_free_page(GFP_KERNEL|GFP_DMA);
+ if (lowcore_ptr[i] == NULL)
+ panic("smp_boot_cpus failed to "
+ "allocate prefix memory\n");
+ async_stack = __get_free_pages(GFP_KERNEL,1);
+ if (async_stack == 0)
+ panic("smp_boot_cpus failed to allocate "
+ "asyncronous interrupt stack\n");
+
+ memcpy(lowcore_ptr[i], &S390_lowcore, sizeof(struct _lowcore));
+ lowcore_ptr[i]->async_stack = async_stack + (2 * PAGE_SIZE);
/*
* Most of the parameters are set up when the cpu is
* started up.
*/
- if (smp_processor_id() == i)
- set_prefix((u32) curr_lowcore);
- else {
- ccode = signal_processor_p((u32)(curr_lowcore),
- i, sigp_set_prefix);
- if(ccode) {
- /* if this gets troublesome I'll have to do
- * something about it. */
- printk("ccode %d for cpu %d returned when "
- "setting prefix in smp_boot_cpus not good.\n",
- (int) ccode, (int) i);
- }
- else
- do_boot_cpu(i);
- }
- }
+ if (smp_processor_id() == i)
+ set_prefix((u32) lowcore_ptr[i]);
+ else {
+ ccode = signal_processor_p((u32)(lowcore_ptr[i]),
+ i, sigp_set_prefix);
+ if (ccode)
+ /* if this gets troublesome I'll have to do
+ * something about it. */
+ printk("ccode %d for cpu %d returned when "
+ "setting prefix in smp_boot_cpus not good.\n",
+ (int) ccode, (int) i);
+ else
+ do_boot_cpu(i);
+ }
+ }
}
/*
s390_do_profile(regs->psw.addr);
if (!--prof_counter[cpu]) {
- int system = 1-user;
- struct task_struct * p = current;
/*
* The multiplier may have changed since the last time we got
* WrongThing (tm) to do.
*/
- irq_enter(cpu, 0);
update_process_times(user);
- irq_exit(cpu, 0);
}
}
void do_timer_interrupt(struct pt_regs *regs, __u16 error_code)
{
- unsigned long flags;
+ int cpu = smp_processor_id();
+
+ irq_enter(cpu, 0);
/*
* reset timer to 10ms minus time already elapsed
* since timer-interrupt pending
*/
-
- save_flags(flags);
- cli();
#ifdef CONFIG_SMP
if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) {
write_lock(&xtime_lock);
write_unlock(&xtime_lock);
#endif
}
- restore_flags(flags);
+ irq_exit(cpu, 0);
}
/*
init_timer_cc -= 0x8126d60e46000000LL -
(0x3c26700LL*1000000*4096);
tod_to_timeval(init_timer_cc, &xtime);
+
+ /* Set do_get_fast_time function pointer. */
+ do_get_fast_time = do_gettimeofday;
}
extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code);
#endif
-spinlock_t die_lock;
+spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
void die(const char * str, struct pt_regs * regs, long err)
{
console_verbose();
spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
printk("%s: %04lx\n", str, err & 0xffff);
show_regs(regs);
+ bust_spinlocks(0);
spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
#if CONFIG_REMOTE_DEBUG
if(gdb_stub_initialised)
{
- gdb_stub_handle_exception((gdb_pt_regs *)regs,signal);
+ gdb_stub_handle_exception((struct gdb_pt_regs *)regs,signal);
return 0;
}
#endif
specification_exception(struct pt_regs * regs, long interruption_code)
{
__u8 opcode[6];
- __u16 *location;
+ __u16 *location = NULL;
int signal = 0;
if (regs->psw.mask & PSW_PROBLEM_STATE) {
}
/* Test data class long double */
-static int emu_tcxb (int rx, double *val) {
- display_emulation_not_implemented("tcxb");
+static int emu_tcxb (int rx, long val) {
+ FP_DECL_Q(QA);
+ mathemu_ldcv cvt;
+ int bit;
+
+ cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
+ cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
+ FP_UNPACK_RAW_QP(QA, &cvt.ld);
+ switch (QA_e) {
+ default:
+ bit = 8; /* normalized number */
+ break;
+ case 0:
+ if (_FP_FRAC_ZEROP_4(QA))
+ bit = 10; /* zero */
+ else
+ bit = 6; /* denormalized number */
+ break;
+ case _FP_EXPMAX_Q:
+ if (_FP_FRAC_ZEROP_4(QA))
+ bit = 4; /* infinity */
+ else if (_FP_FRAC_HIGH_RAW_Q(QA) & _FP_QNANBIT_Q)
+ bit = 2; /* quiet NAN */
+ else
+ bit = 0; /* signaling NAN */
+ break;
+ }
+ if (!QA_s)
+ bit++;
+ emu_set_CC(((__u32) val >> bit) & 1);
return 0;
}
/* Test data class double */
-static int emu_tcdb (int rx, double *val) {
- display_emulation_not_implemented("tcdb");
+static int emu_tcdb (int rx, long val) {
+ FP_DECL_D(DA);
+ int bit;
+
+ FP_UNPACK_RAW_DP(DA, ¤t->thread.fp_regs.fprs[rx].d);
+ switch (DA_e) {
+ default:
+ bit = 8; /* normalized number */
+ break;
+ case 0:
+ if (_FP_FRAC_ZEROP_2(DA))
+ bit = 10; /* zero */
+ else
+ bit = 6; /* denormalized number */
+ break;
+ case _FP_EXPMAX_D:
+ if (_FP_FRAC_ZEROP_2(DA))
+ bit = 4; /* infinity */
+ else if (_FP_FRAC_HIGH_RAW_D(DA) & _FP_QNANBIT_D)
+ bit = 2; /* quiet NAN */
+ else
+ bit = 0; /* signaling NAN */
+ break;
+ }
+ if (!DA_s)
+ bit++;
+ emu_set_CC(((__u32) val >> bit) & 1);
return 0;
}
/* Test data class float */
-static int emu_tceb (int rx, __u32 val) {
- display_emulation_not_implemented("tceb");
+static int emu_tceb (int rx, long val) {
+ FP_DECL_S(SA);
+ int bit;
+
+ FP_UNPACK_RAW_SP(SA, ¤t->thread.fp_regs.fprs[rx].f);
+ switch (SA_e) {
+ default:
+ bit = 8; /* normalized number */
+ break;
+ case 0:
+ if (_FP_FRAC_ZEROP_1(SA))
+ bit = 10; /* zero */
+ else
+ bit = 6; /* denormalized number */
+ break;
+ case _FP_EXPMAX_S:
+ if (_FP_FRAC_ZEROP_1(SA))
+ bit = 4; /* infinity */
+ else if (_FP_FRAC_HIGH_RAW_S(SA) & _FP_QNANBIT_S)
+ bit = 2; /* quiet NAN */
+ else
+ bit = 0; /* signaling NAN */
+ break;
+ }
+ if (!SA_s)
+ bit++;
+ emu_set_CC(((__u32) val >> bit) & 1);
return 0;
}
int _fex = 0;
static const __u8 format_table[256] = {
- [0x04] = 0x08,[0x05] = 0x07,[0x06] = 0x09,[0x07] = 0x07,
- [0x08] = 0x03,[0x09] = 0x03,[0x0a] = 0x03,[0x0b] = 0x03,
- [0x0c] = 0x08,[0x0d] = 0x03,[0x0e] = 0x06,[0x0f] = 0x06,
- [0x10] = 0x03,[0x11] = 0x02,[0x12] = 0x01,[0x14] = 0x03,
- [0x15] = 0x02,[0x17] = 0x03,[0x18] = 0x02,[0x19] = 0x02,
- [0x1a] = 0x02,[0x1b] = 0x02,[0x1c] = 0x02,[0x1d] = 0x02,
- [0x1e] = 0x05,[0x1f] = 0x05,
+ [0x04] = 0x06,[0x05] = 0x05,[0x06] = 0x07,[0x07] = 0x05,
+ [0x08] = 0x02,[0x09] = 0x02,[0x0a] = 0x02,[0x0b] = 0x02,
+ [0x0c] = 0x06,[0x0d] = 0x02,[0x0e] = 0x04,[0x0f] = 0x04,
+ [0x10] = 0x08,[0x11] = 0x09,[0x12] = 0x0a,[0x14] = 0x02,
+ [0x15] = 0x01,[0x17] = 0x02,[0x18] = 0x01,[0x19] = 0x01,
+ [0x1a] = 0x01,[0x1b] = 0x01,[0x1c] = 0x01,[0x1d] = 0x01,
+ [0x1e] = 0x03,[0x1f] = 0x03,
};
static const void *jump_table[]= {
[0x04] = emu_ldeb,[0x05] = emu_lxdb,[0x06] = emu_lxeb,
};
switch (format_table[opcode[5]]) {
- case 1: /* RXE format, long double constant */ {
- __u64 *dxb, temp[2];
- __u32 opc;
-
- if ((opcode[1] >> 4) & 2)
- return SIGILL;
- emu_store_regd((opcode[1] >> 4) & 15);
- emu_store_regd(((opcode[1] >> 4) & 15) + 2);
- opc = *((__u32 *) opcode);
- dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
- mathemu_copy_from_user(&temp, dxb, 16);
- /* call the emulation function */
- _fex = ((int (*)(int, long double *)) jump_table[opcode[5]])
- (opcode[1] >> 4, (long double *) &temp);
- emu_load_regd((opcode[1] >> 4) & 15);
- emu_load_regd(((opcode[1] >> 4) & 15) + 2);
- break;
- }
- case 2: /* RXE format, double constant */ {
+ case 1: /* RXE format, double constant */ {
__u64 *dxb, temp;
__u32 opc;
emu_load_regd((opcode[1] >> 4) & 15);
break;
}
- case 3: /* RXE format, float constant */ {
+ case 2: /* RXE format, float constant */ {
__u32 *dxb, temp;
__u32 opc;
emu_load_rege((opcode[1] >> 4) & 15);
break;
}
- case 4: /* RXF format, long double constant */ {
- __u64 *dxb, temp[2];
- __u32 opc;
-
- if (((opcode[1] >> 4) & 0x20) || ((opcode[4] >> 4) & 0x20))
- return SIGILL;
- emu_store_regd((opcode[1] >> 4) & 15);
- emu_store_regd(((opcode[1] >> 4) & 15) + 2);
- emu_store_regd((opcode[4] >> 4) & 15);
- emu_store_regd(((opcode[4] >> 4) & 15) + 2);
- opc = *((__u32 *) opcode);
- dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
- mathemu_copy_from_user(&temp, dxb, 16);
- /* call the emulation function */
- _fex = ((int (*)(int,long double *,int)) jump_table[opcode[5]])
- (opcode[1] >> 4, (double *) &temp, opcode[4] >> 4);
- emu_load_regd((opcode[1] >> 4) & 15);
- emu_load_regd(((opcode[1] >> 4) & 15) + 2);
- break;
- }
- case 5: /* RXF format, double constant */ {
+ case 3: /* RXF format, double constant */ {
__u64 *dxb, temp;
__u32 opc;
emu_load_regd((opcode[1] >> 4) & 15);
break;
}
- case 6: /* RXF format, float constant */ {
+ case 4: /* RXF format, float constant */ {
__u32 *dxb, temp;
__u32 opc;
emu_load_rege((opcode[4] >> 4) & 15);
break;
}
- case 7: /* RXE format, double constant */
+ case 5: /* RXE format, double constant */
/* store double and load long double */
{
__u64 *dxb, temp;
emu_load_regd(((opcode[1] >> 4) & 15) + 2);
break;
}
- case 8: /* RXE format, float constant */
+ case 6: /* RXE format, float constant */
/* store float and load double */
{
__u32 *dxb, temp;
emu_load_regd((opcode[1] >> 4) & 15);
break;
}
- case 9: /* RXE format, float constant */
+ case 7: /* RXE format, float constant */
/* store float and load long double */
{
__u32 *dxb, temp;
emu_load_regd(((opcode[1] >> 4) & 15) + 2);
break;
}
+ case 8: /* RXE format, RX address used as int value */ {
+ __u64 dxb;
+ __u32 opc;
+
+ emu_store_rege((opcode[1] >> 4) & 15);
+ opc = *((__u32 *) opcode);
+ dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc);
+ /* call the emulation function */
+ _fex = ((int (*)(int, long)) jump_table[opcode[5]])
+ (opcode[1] >> 4, dxb);
+ break;
+ }
+ case 9: /* RXE format, RX address used as int value */ {
+ __u64 dxb;
+ __u32 opc;
+
+ emu_store_regd((opcode[1] >> 4) & 15);
+ opc = *((__u32 *) opcode);
+ dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc);
+ /* call the emulation function */
+ _fex = ((int (*)(int, long)) jump_table[opcode[5]])
+ (opcode[1] >> 4, dxb);
+ break;
+ }
+ case 10: /* RXE format, RX address used as int value */ {
+ __u64 dxb;
+ __u32 opc;
+
+ if ((opcode[1] >> 4) & 2)
+ return SIGILL;
+ emu_store_regd((opcode[1] >> 4) & 15);
+ emu_store_regd(((opcode[1] >> 4) & 15) + 2);
+ opc = *((__u32 *) opcode);
+ dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc);
+ /* call the emulation function */
+ _fex = ((int (*)(int, long)) jump_table[opcode[5]])
+ (opcode[1] >> 4, dxb);
+ break;
+ }
default: /* invalid operation */
return SIGILL;
}
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/spinlock.h>
#include <asm/uaccess.h>
extern const struct exception_table_entry __start___ex_table[];
return 0;
}
+extern spinlock_t modlist_lock;
+
unsigned long
search_exception_table(unsigned long addr)
{
- unsigned long ret;
+ unsigned long ret = 0;
+ unsigned long flags;
#ifndef CONFIG_MODULES
addr &= 0x7fffffff; /* remove amode bit from address */
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
- if (ret) return FIX_PSW(ret);
+ if (ret) ret = FIX_PSW(ret);
+ return ret;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
addr &= 0x7fffffff; /* remove amode bit from address */
+
+ spin_lock_irqsave(&modlist_lock, flags);
for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->ex_table_start == NULL)
+ if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return FIX_PSW(ret);
+ if (ret) {
+ ret = FIX_PSW(ret);
+ break;
+ }
}
+ spin_unlock_irqrestore(&modlist_lock, flags);
+ return ret;
#endif
-
- return 0;
}
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Hartmut Penner (hp@de.ibm.com)
+ * Ulrich Weigand (uweigand@de.ibm.com)
*
* Derived from "arch/i386/mm/fault.c"
* Copyright (C) 1995 Linus Torvalds
#include <linux/smp_lock.h>
#include <linux/compatmac.h>
#include <linux/init.h>
+#include <linux/console.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#endif
extern void die(const char *,struct pt_regs *,long);
+static void force_sigsegv(struct task_struct *tsk, int code, void *address);
+
+extern spinlock_t timerlist_lock;
+
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out (timerlist_lock is acquired through the
+ * console unblank code)
+ */
+void bust_spinlocks(int yes)
+{
+ spin_lock_init(&timerlist_lock);
+ if (yes) {
+ oops_in_progress = 1;
+ } else {
+ int loglevel_save = console_loglevel;
+ oops_in_progress = 0;
+ console_unblank();
+ /*
+ * OK, the message is on the console. Now we call printk()
+ * without oops_in_progress set so that printk will give klogd
+ * a poke. Hold onto your hats...
+ */
+ console_loglevel = 15;
+ printk(" ");
+ console_loglevel = loglevel_save;
+ }
+}
/*
* This routine handles page faults. It determines the address,
int si_code = SEGV_MAPERR;
int kernel_address = 0;
+ tsk = current;
+ mm = tsk->mm;
+
+ /*
+ * Check for low-address protection. This needs to be treated
+ * as a special case because the translation exception code
+ * field is not guaranteed to contain valid data in this case.
+ */
+ if ((error_code & 0xff) == 4 && !(S390_lowcore.trans_exc_code & 4)) {
+
+ /* Low-address protection hit in kernel mode means
+ NULL pointer write access in kernel mode. */
+ if (!(regs->psw.mask & PSW_PROBLEM_STATE)) {
+ address = 0;
+ kernel_address = 1;
+ goto no_context;
+ }
+
+ /* Low-address protection hit in user mode 'cannot happen'. */
+ die ("Low-address protection", regs, error_code);
+ do_exit(SIGKILL);
+ }
+
/*
* get the failing address
* more specific the segment and page table portion of
* the address
*/
- address = S390_lowcore.trans_exc_code&0x7ffff000;
- tsk = current;
- mm = tsk->mm;
-
- if (in_interrupt() || !mm)
- goto no_context;
+ address = S390_lowcore.trans_exc_code&0x7ffff000;
/*
}
}
die("page fault via unknown access register", regs, error_code);
+ do_exit(SIGKILL);
break;
case 2: /* Secondary Segment Table Descriptor */
break;
}
+ /*
+ * Check whether we have a user MM in the first place.
+ */
+ if (in_interrupt() || !mm)
+ goto no_context;
/*
* When we get here, the fault happened in the current
goto bad_area;
}
+ survive:
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
/* User mode accesses just cause a SIGSEGV */
if (regs->psw.mask & PSW_PROBLEM_STATE) {
- struct siginfo si;
tsk->thread.prot_addr = address;
tsk->thread.trap_no = error_code;
#ifndef CONFIG_SYSCTL
show_regs(regs);
}
#endif
- si.si_signo = SIGSEGV;
- si.si_code = si_code;
- si.si_addr = (void*) address;
- force_sig_info(SIGSEGV, &si, tsk);
+
+ force_sigsegv(tsk, si_code, (void *)address);
return;
}
else
printk(KERN_ALERT "Unable to handle kernel paging request"
" at virtual user address %08lx\n", address);
-/*
- * need to define, which information is useful here
- */
die("Oops", regs, error_code);
do_exit(SIGKILL);
*/
out_of_memory:
up_read(&mm->mmap_sem);
+ if (tsk->pid == 1) {
+ tsk->policy |= SCHED_YIELD;
+ schedule();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
printk("VM: killing process %s\n", tsk->comm);
if (regs->psw.mask & PSW_PROBLEM_STATE)
do_exit(SIGKILL);
goto no_context;
}
+/*
+ * Send SIGSEGV to task. This is an external routine
+ * to keep the stack usage of do_page_fault small.
+ */
+static void force_sigsegv(struct task_struct *tsk, int code, void *address)
+{
+ struct siginfo si;
+ si.si_signo = SIGSEGV;
+ si.si_code = code;
+ si.si_addr = address;
+ force_sig_info(SIGSEGV, &si, tsk);
+}
typedef struct _pseudo_wait_t {
struct _pseudo_wait_t *next;
asmlinkage void
pfault_interrupt(struct pt_regs *regs, __u16 error_code)
{
- DECLARE_WAITQUEUE(wait, current);
struct task_struct *tsk;
wait_queue_head_t queue;
wait_queue_head_t *qp;
* external interrupt.
*/
subcode = S390_lowcore.cpu_addr;
- if ((subcode & 0xff00) != 0x06)
+ if ((subcode & 0xff00) != 0x0600)
return;
/*
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
-static int test_access(unsigned long loc)
-{
- static const int ssm_mask = 0x07000000L;
- int rc, i;
-
- rc = 0;
- for (i=0; i<4; i++) {
- __asm__ __volatile__(
- " slr %0,%0\n"
- " ssm %1\n"
- " tprot 0(%2),0\n"
- "0: jne 1f\n"
- " lhi %0,1\n"
- "1: ssm %3\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous"
- : "+&d" (rc) : "i" (0), "a" (loc), "m" (ssm_mask)
- : "cc");
- if (rc == 0)
- break;
- loc += 0x100000;
- }
- return rc;
-}
-
int do_check_pgt_cache(int low, int high)
{
int freed = 0;
if(pgtable_cache_size > high) {
do {
- if(pgd_quicklist)
- free_pgd_slow(get_pgd_fast()), freed += 2;
- if(pmd_quicklist)
- pmd_free_slow(pmd_alloc_one_fast(NULL, 0)), freed++;
- if(pte_quicklist)
- pte_free_slow(pte_alloc_one_fast(NULL, 0)), freed++;
+ if(pgd_quicklist) {
+ free_pgd_slow(get_pgd_fast());
+ freed += 2;
+ }
+ if(pmd_quicklist) {
+ pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
+ freed++;
+ }
+ if(pte_quicklist) {
+ pte_free_slow(pte_alloc_one_fast(NULL, 0));
+ freed++;
+ }
} while(pgtable_cache_size > low);
}
return freed;
void __init mem_init(void)
{
int codesize, reservedpages, datasize, initsize;
- int tmp;
max_mapnr = num_physpages = max_low_pfn;
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem();
- /* mark usable pages in the mem_map[] and count reserved pages */
reservedpages = 0;
- tmp = 0;
- do {
- if (tmp && (tmp & 0x3ff) == 0 &&
- test_access(tmp * PAGE_SIZE) == 0) {
- printk("4M Segment %lX not available\n",tmp*PAGE_SIZE);
- do {
- set_bit(PG_reserved, &mem_map[tmp].flags);
- reservedpages++;
- tmp++;
- } while (tmp < max_low_pfn && (tmp & 0x3ff));
- } else {
- if (PageReserved(mem_map+tmp))
- reservedpages++;
- tmp++;
- }
- } while (tmp < max_low_pfn);
codesize = (unsigned long) &_etext - (unsigned long) &_text;
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-MAKESILO = $(MAKE) -C arch/$(ARCH)/tools/silo
-
-MAKEDASDFMT = $(MAKE) -C arch/$(ARCH)/tools/dasdfmt
-
-silo:
- @$(MAKE) -C arch/$(ARCH)/tools/silo
-
-dasdfmt:
- @$(MAKE) -C arch/$(ARCH)/tools/dasdfmt
-
image: vmlinux
@$(MAKEBOOT) image
define_bool CONFIG_MCA n
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+define_bool CONFIG_GENERIC_BUST_SPINLOCK n
mainmenu_name "Linux Kernel Configuration"
define_bool CONFIG_ARCH_S390 y
# CONFIG_MCA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_BUST_SPINLOCK=n
CONFIG_ARCH_S390=y
CONFIG_ARCH_S390X=y
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID5=m
+# CONFIG_MD_MULTIPATH is not set
CONFIG_BLK_DEV_LVM=m
#
CONFIG_IBM_PARTITION=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
all: kernel.o head.o init_task.o
-O_TARGET := kernel.o
+O_TARGET := kernel.o
-export-objs := debug.o ebcdic.o irq.o s390_ext.o smp.o s390_ksyms.o
-obj-y := lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \
- setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
- semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
+export-objs := debug.o ebcdic.o irq.o s390_ext.o smp.o s390_ksyms.o \
+ exec32.o
+
+obj-y := entry.o bitmap.o traps.o time.o process.o irq.o \
+ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
+ semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
obj-$(CONFIG_MODULES) += s390_ksyms.o
obj-$(CONFIG_SMP) += smp.o
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
*/
-#include <linux/stddef.h>
-#include <linux/kernel.h>
#include <linux/string.h>
-#include <asm/ebcdic.h>
+#include <linux/spinlock.h>
#include <asm/cpcmd.h>
+#include <asm/ebcdic.h>
+#include <asm/system.h>
+
+static spinlock_t cpcmd_lock = SPIN_LOCK_UNLOCKED;
+static char cpcmd_buf[128];
void cpcmd(char *cmd, char *response, int rlen)
{
const int mask = 0x40000000L;
- char obuffer[128];
- int olen;
+ unsigned long flags;
+ int cmdlen;
- olen = strlen(cmd);
- strcpy(obuffer, cmd);
- ASCEBC(obuffer,olen);
+ spin_lock_irqsave(&cpcmd_lock, flags);
+ cmdlen = strlen(cmd);
+ strcpy(cpcmd_buf, cmd);
+ ASCEBC(cpcmd_buf, cmdlen);
if (response != NULL && rlen > 0) {
asm volatile (" lrag 2,0(%0)\n"
" .long 0x83240008 # Diagnose 83\n"
" sam64"
: /* no output */
- : "a" (obuffer), "d" (olen),
+ : "a" (cpcmd_buf), "d" (cmdlen),
"a" (response), "d" (rlen), "m" (mask)
: "2", "3", "4", "5" );
EBCASC(response, rlen);
" .long 0x83230008 # Diagnose 83\n"
" sam64"
: /* no output */
- : "a" (obuffer), "d" (olen)
+ : "a" (cpcmd_buf), "d" (cmdlen)
: "2", "3" );
}
+ spin_unlock_irqrestore(&cpcmd_lock, flags);
}
static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
struct file *file, const char *user_buf,
size_t user_buf_size, loff_t * offset);
+static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char *user_buf,
+ size_t user_buf_size, loff_t * offset);
static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
char *out_buf, const char *in_buf);
static int debug_raw_format_fn(debug_info_t * id,
NULL
};
+struct debug_view debug_flush_view = {
+ "flush",
+ NULL,
+ NULL,
+ NULL,
+ &debug_input_flush_fn,
+ NULL
+};
+
struct debug_view debug_sprintf_view = {
"sprintf",
NULL,
if(!rc)
goto out;
debug_register_view(rc, &debug_level_view);
+ debug_register_view(rc, &debug_flush_view);
printk(KERN_INFO
"debug: reserved %d areas of %d pages for debugging %s\n",
nr_areas, 1 << page_order, rc->name);
return rc; /* number of input characters */
}
+
+/*
+ * flushes debug areas
+ */
+
+void debug_flush(debug_info_t* id, int area)
+{
+ unsigned long flags;
+ int i;
+
+ if(!id)
+ return;
+ spin_lock_irqsave(&id->lock,flags);
+ if(area == DEBUG_FLUSH_ALL){
+ id->active_area = 0;
+ memset(id->active_entry, 0, id->nr_areas * sizeof(int));
+ for (i = 0; i < id->nr_areas; i++)
+ memset(id->areas[i], 0, PAGE_SIZE << id->page_order);
+ printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
+ } else if(area >= 0 && area < id->nr_areas) {
+ id->active_entry[area] = 0;
+ memset(id->areas[area], 0, PAGE_SIZE << id->page_order);
+ printk(KERN_INFO
+ "debug: %s: area %i has been flushed\n",
+ id->name, area);
+ } else {
+ printk(KERN_INFO
+ "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
+ id->name, area, 0, id->nr_areas-1);
+ }
+ spin_unlock_irqrestore(&id->lock,flags);
+}
+
+/*
+ * view function: flushes debug areas
+ */
+
+static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char *user_buf,
+ size_t in_buf_size, loff_t * offset)
+{
+ char input_buf[1];
+ int rc = in_buf_size;
+
+ if (*offset != 0)
+ goto out;
+ if (copy_from_user(input_buf, user_buf, 1)){
+ rc = -EFAULT;
+ goto out;
+ }
+ if(input_buf[0] == '-') {
+ debug_flush(id, DEBUG_FLUSH_ALL);
+ goto out;
+ }
+ if (isdigit(input_buf[0])) {
+ int area = ((int) input_buf[0] - (int) '0');
+ debug_flush(id, area);
+ goto out;
+ }
+
+ printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]);
+
+ out:
+ *offset += in_buf_size;
+ return rc; /* number of input characters */
+}
+
/*
* prints debug header in raw format
*/
* R15 - kernel stack pointer
*/
- .macro SAVE_ALL psworg # system entry macro
+ .macro SAVE_ALL psworg,sync # system entry macro
stmg %r14,%r15,__LC_SAVE_AREA
- stam %a2,%a4,__LC_SAVE_AREA+16
tm \psworg+1,0x01 # test problem state bit
- jz 0f # skip stack setup save
- lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
- slr %r14,%r14
- sar %a2,%r14 # set ac.reg. 2 to primary space
- lhi %r14,1
- sar %a4,%r14 # set access reg. 4 to home space
-0: aghi %r15,-SP_SIZE # make room for registers & psw
+ stam %a2,%a4,__LC_SAVE_AREA+16
+ .if \sync
+ jz 1f # skip stack setup save
+ .else
+ jnz 0f # from user -> load kernel stack
+ lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ?
+ slgr %r14,%r15
+ srag %r14,%r14,14
+ jz 1f
+ lg %r15,__LC_ASYNC_STACK # load async. stack
+ j 1f
+ .endif
+0: lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
+ larl %r14,.Lc_ac
+ lam %a2,%a4,0(%r14)
+1: aghi %r15,-SP_SIZE # make room for registers & psw
nill %r15,0xfff8 # align stack pointer to 8
stmg %r0,%r14,SP_R0(%r15) # store gprs 0-14 to kernel stack
stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
xc 0(8,%r15),0(%r15) # clear back chain
.endm
- .macro RESTORE_ALL # system exit macro
+ .macro RESTORE_ALL sync # system exit macro
mvc __LC_RETURN_PSW(16),SP_PSW(%r15) # move user PSW to lowcore
lam %a0,%a15,SP_AREGS(%r15) # load the access registers
lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user
.endm
.macro GET_CURRENT
- lghi %r9,-16384 # load pointer to task_struct to %r9
- ngr %r9,15
+ lg %r9,__LC_KERNEL_STACK # load pointer to task_struct to %r9
+ aghi %r9,-16384
.endm
lmg %r6,%r15,48(%r15) # load resume registers of next task
br %r14
+/*
+ * do_softirq calling function. We want to run the softirq functions on the
+ * asynchronous interrupt stack.
+ */
+ .global do_call_softirq
+do_call_softirq:
+ stmg %r12,%r15,48(%r15)
+ lgr %r12,%r15
+ lg %r0,__LC_ASYNC_STACK
+ slgr %r0,%r15
+ srag %r0,%r0,14
+ je 0f
+ lg %r15,__LC_ASYNC_STACK
+0: aghi %r15,-STACK_FRAME_OVERHEAD
+ stg %r12,0(%r15) # store back chain
+ brasl %r14,do_softirq
+ lmg %r12,%r15,48(%r12)
+ br %r14
+
/*
* SVC interrupt handler routine. System calls are synchronous events and
* are executed with interrupts enabled.
.globl system_call
system_call:
- SAVE_ALL __LC_SVC_OLD_PSW
+ SAVE_ALL __LC_SVC_OLD_PSW,1
mvi SP_PGM_OLD_ILC(%r15),1 # mark PGM_OLD_ILC as invalid
pgm_system_call:
GET_CURRENT # load pointer to task_struct to R9
tm SP_PGM_OLD_ILC(%r15),0xff
jz pgm_svcret
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
- RESTORE_ALL
+ RESTORE_ALL 1
#
# call do_signal before return
.long SYSCALL(sys_mmap2,sys32_mmap2_wrapper)
.long SYSCALL(sys_ni_syscall,sys32_truncate64_wrapper)
.long SYSCALL(sys_ni_syscall,sys32_ftruncate64_wrapper)
- .long SYSCALL(sys_ni_syscall,sys32_stat64) /* 195 */
- .long SYSCALL(sys_ni_syscall,sys32_lstat64)
- .long SYSCALL(sys_ni_syscall,sys32_fstat64)
+ .long SYSCALL(sys_ni_syscall,sys32_stat64_wrapper) /* 195 */
+ .long SYSCALL(sys_ni_syscall,sys32_lstat64_wrapper)
+ .long SYSCALL(sys_ni_syscall,sys32_fstat64_wrapper)
.long SYSCALL(sys_lchown,sys32_lchown_wrapper)
.long SYSCALL(sys_getuid,sys_getuid)
.long SYSCALL(sys_getgid,sys_getgid) /* 200 */
.long SYSCALL(sys_madvise,sys32_madvise_wrapper)
.long SYSCALL(sys_getdents64,sys32_getdents64_wrapper)/* 220 */
.long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
- .rept 255-221
+ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 222 - reserved for posix_acl */
+ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 223 - reserved for posix_acl */
+ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for posix_acl */
+ .rept 255-224
.long SYSCALL(sys_ni_syscall,sys_ni_syscall)
.endr
lpswe __LC_PGM_OLD_PSW
# it was a single stepped SVC that is causing all the trouble
pgm_svcper:
- SAVE_ALL __LC_SVC_OLD_PSW
+ SAVE_ALL __LC_SVC_OLD_PSW,1
mvc SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information
j pgm_system_call # now do the svc
pgm_svcret:
mvi SP_PGM_OLD_ILC(%r15),1 # mark PGM_OLD_ILC as invalid
j pgm_no_sv
pgm_sv:
- SAVE_ALL __LC_PGM_OLD_PSW
+ SAVE_ALL __LC_PGM_OLD_PSW,1
mvi SP_PGM_OLD_ILC(%r15),1 # mark PGM_OLD_ILC as invalid
llgh %r7,__LC_PGM_ILC # load instruction length
GET_CURRENT
*/
.globl io_int_handler
io_int_handler:
- SAVE_ALL __LC_IO_OLD_PSW
+ SAVE_ALL __LC_IO_OLD_PSW,0
GET_CURRENT # load pointer to task_struct to R9
la %r2,SP_PTREGS(%r15) # address of register-save area
llgh %r3,__LC_SUBCHANNEL_NR # load subchannel number
jnz io_signal_return
io_leave:
stnsm 48(%r15),0xfc # disable I/O and ext. interrupts
- RESTORE_ALL
+ RESTORE_ALL 0
#
# call do_softirq and return from syscall, if interrupt-level
*/
.globl ext_int_handler
ext_int_handler:
- SAVE_ALL __LC_EXT_OLD_PSW
+ SAVE_ALL __LC_EXT_OLD_PSW,0
GET_CURRENT # load pointer to task_struct to R9
la %r2,SP_PTREGS(%r15) # address of register-save area
llgh %r3,__LC_EXT_INT_CODE # error code
*/
.globl mcck_int_handler
mcck_int_handler:
- SAVE_ALL __LC_MCK_OLD_PSW
+ SAVE_ALL __LC_MCK_OLD_PSW,0
brasl %r14,s390_do_machine_check
mcck_return:
- RESTORE_ALL
+ RESTORE_ALL 0
#ifdef CONFIG_SMP
/*
*/
.globl restart_int_handler
restart_int_handler:
- lg %r15,__LC_KERNEL_STACK # load ksp
- lhi %r10,__LC_CREGS_SAVE_AREA
+ lg %r15,__LC_SAVE_AREA+120 # load ksp
+ lghi %r10,__LC_CREGS_SAVE_AREA
lctlg %c0,%c15,0(%r10) # get new ctl regs
- lhi %r10,__LC_AREGS_SAVE_AREA
+ lghi %r10,__LC_AREGS_SAVE_AREA
lam %a0,%a15,0(%r10)
stosm 0(%r15),0x04 # now we can turn dat on
lmg %r6,%r15,48(%r15) # load registers from clone
restart_go:
#endif
+/*
+ * Integer constants
+ */
+ .align 4
+.Lc_ac: .long 0,0,1
l %r1,0xb8 # load ipl subchannel number
la %r2,IPL_BS # load start address
bas %r14,.Lloader # load rest of ipl image
- larl %r12,parmarea # pointer to parameter area
+ larl %r12,_pstart # pointer to parameter area
st %r1,IPL_DEVICE+4-PARMAREA(%r12) # store ipl device number
#
sigp %r1,%r0,0x12 # switch to esame mode
sam64 # switch to 64 bit mode
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
- larl %r12,parmarea # pointer to parameter area
+ larl %r12,_pstart # pointer to parameter area
# move IPL device to lowcore
mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
# set program check new psw mask
#
-# find out memory size.
+# find memory chunks.
#
- la %r1,1f-.LPG1(%r13) # set program check address
+ larl %r1,.Lchkmem # set program check address
stg %r1,__LC_PGM_NEW_PSW+8
- lghi %r2,1
- sllg %r2,%r2,17 # test in increments of 128KB
- lgr %r1,%r2
- aghi %r1,-8 # test last word in the segment
-0: lg %r0,0(%r1) # test 128KB segment
- stg %r0,0(%r1)
- algr %r1,%r2 # add 128KB
- bc 12,0b-.LPG1(%r13) # r1 < 2^64 -> loop
-1: ng %r1,.L4malign-.LPG1(%r13) # align to multiples of 4M
- larl %r3,memory_size-.
- stg %r1,0(%r3) # store memory size
-#
-# find out memory size part 2. Running native the HSA is located at
-# 2GB and we will get an addressing exception trying to access it.
-# We have to restart the scan at 2GB to find out if the machine has
-# more than 2GB of storage.
-#
- la %r1,1f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- lg %r1,.Lscan2g-.LPG1(%r13) # restart scanning @ 2GB + 128K - 8
-0: lg %r0,0(%r1) # test 128KB segment
- stg %r0,0(%r1)
- algr %r1,%r2 # add 128 KB
- bc 12,0b-.LPG1(%r13) # r1 < 2^64 -> loop
-1: clg %r1,.Lscan2g-.LPG1(%r13) # program check @ 2GB + 128K - 8 ?
- be 2f-.LPG1(%r13)
- ng %r1,.L4malign-.LPG1(%r13) # align to multiples of 4M
- larl %r3,memory_size-.
- stg %r1,0(%r3) # store memory size
-2:
-
- larl %r12,machine_flags-.
+ la %r1,1 # test in increments of 128KB
+ sllg %r1,%r1,17
+ larl %r3,memory_chunk
+ slgr %r4,%r4 # set start of chunk to zero
+ slgr %r5,%r5 # set end of chunk to zero
+ slr %r6,%r6 # set access code to zero
+.Lloop:
+ tprot 0(%r5),0 # test protection of first byte
+ ipm %r7
+ srl %r7,28
+ clr %r6,%r7 # compare cc with last access code
+ je .Lsame
+ clgr %r4,%r5 # chunk size > 0?
+ je .Lsize0
+ stg %r4,0(%r3) # store start address of chunk
+ lgr %r0,%r5
+ slgr %r0,%r4
+ stg %r0,8(%r3) # store size of chunk
+ st %r6,20(%r3) # store type of chunk
+ la %r3,24(%r3)
+ lgr %r4,%r5 # set start to end
+ larl %r8,memory_size
+ stg %r5,0(%r8) # store memory size
+.Lsize0:
+ lr %r6,%r7 # set access code to last cc
+.Lsame:
+ algr %r5,%r1 # add 128KB to end of chunk
+ brc 12,.Lloop
+.Lchkmem: # > 16EB or tprot got a program check
+ clgr %r4,%r5 # chunk size > 0?
+ je .Ldonemem
+ stg %r4,0(%r3) # store start address of chunk
+ lgr %r0,%r5
+ slgr %r0,%r4
+ stg %r0,8(%r3) # store size of chunk
+ st %r6,20(%r3) # store type of chunk
+ la %r3,24(%r3)
+ lgr %r4,%r5
+ larl %r8,memory_size
+ stg %r5,0(%r8) # store memory size
+#
+# Running native the HSA is located at 2GB and we will get an
+# addressing exception trying to access it. We have to restart
+# the scan at 2GB to find out if the machine has more than 2GB.
+#
+ lghi %r4,1
+ sllg %r4,%r4,31
+ clgr %r5,%r4
+ jhe .Ldonemem
+ lgr %r5,%r4
+ j .Lloop
+.Ldonemem:
+
+ larl %r12,machine_flags
#
# find out if we are running under VM
#
.Lentry:.quad 0x0000000180000000,_stext
.Lctl: .quad 0x04b50002 # cr0: various things
.quad 0 # cr1: primary space segment table
- .quad 0 # cr2: access register translation
+ .quad .Lduct # cr2: dispatchable unit control table
.quad 0 # cr3: instruction authorization
.quad 0 # cr4: instruction authorization
.quad 0 # cr5: various things
.L4malign:.quad 0xffffffffffc00000
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
+ .org PARMAREA-64
+.Lduct: .long 0,0,0,0,0,0,0,0
+ .long 0,0,0,0,0,0,0,0
+
#
# params at 10400 (setup.h)
#
.org PARMAREA
-parmarea:
+ .global _pstart
+_pstart:
.quad 0 # IPL_DEVICE
.quad RAMDISK_ORIGIN # INITRD_START
.quad RAMDISK_SIZE # INITRD_SIZE
.org COMMAND_LINE
.byte "root=/dev/ram0 ro"
.byte 0
+ .org 0x11000
+ .global _pend
+_pend:
-#
-# startup-code, running in virtual mode
-#
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000
-#else
- .org 0x10800
#endif
+
+#
+# startup-code, running in virtual mode
+#
.globl _stext
_stext: basr %r13,0 # get base
.LPG2:
#
-# Setup lowcore
+# Setup stack
#
- l %r1,__LC_IPLDEV # load ipl device number
- spx .Lprefix-.LPG2(%r13) # set prefix to linux lowcore
- st %r1,__LC_IPLDEV # store ipl device number
larl %r15,init_task_union
aghi %r15,16384 # init_task_union + 16384
stg %r15,__LC_KERNEL_STACK # set end of kernel stack
aghi %r15,-160
xc 0(8,%r15),0(%r15) # set backchain to zero
- lghi %r0,-1
- stg %r0,__LC_KERNEL_LEVEL # set interrupt count to -1
#
# clear bss memory
#
#
.align 8
.Ldw: .quad 0x0002000180000000,0x0000000000000000
-.Lprefix: .long init_S390_lowcore
.Laregs: .long 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/dasd.h>
+#include <asm/sockios.h>
#include "linux32.h"
IOCTL32_DEFAULT(VT_LOCKSWITCH),
IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
+ IOCTL32_DEFAULT(SIOCGSTAMP),
+
IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
err = copy_from_user(kaddr + offset, (char *)A(str),
bytes_to_copy);
flush_page_to_ram(page);
- kunmap((unsigned long)kaddr);
+ kunmap(page);
if (err)
return -EFAULT;
}
struct stat64_emu31 {
- unsigned short st_dev;
- unsigned char __pad0[6];
-
- long long st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
-
- __u32 st_uid;
- __u32 st_gid;
-
- unsigned short st_rdev;
- unsigned char __pad3[10];
-
- long long st_size;
- __u32 st_blksize;
-
- __u32 st_blocks; /* Number 512-byte blocks allocated. */
- __u32 __pad4; /* future possible st_blocks high bits */
-
- __u32 st_atime;
- __u32 __pad5;
-
- __u32 st_mtime;
- __u32 __pad6;
-
- __u32 st_ctime;
- __u32 __pad7; /* will be high 32 bits of ctime someday */
-
- __u32 __unused1;
- __u32 __unused2;
-};
+ unsigned char __pad0[6];
+ unsigned short st_dev;
+ unsigned int __pad1;
+#define STAT64_HAS_BROKEN_ST_INO 1
+ u32 __st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ u32 st_uid;
+ u32 st_gid;
+ unsigned char __pad2[6];
+ unsigned short st_rdev;
+ unsigned int __pad3;
+ long st_size;
+ u32 st_blksize;
+ unsigned char __pad4[4];
+ u32 __pad5; /* future possible st_blocks high bits */
+ u32 st_blocks; /* Number 512-byte blocks allocated. */
+ u32 st_atime;
+ u32 __pad6;
+ u32 st_mtime;
+ u32 __pad7;
+ u32 st_ctime;
+ u32 __pad8; /* will be high 32 bits of ctime someday */
+ unsigned long st_ino;
+};
static inline int
putstat64 (struct stat64_emu31 *ubuf, struct stat *kbuf)
{
- int err;
-
- err = put_user (kbuf->st_dev, &ubuf->st_dev);
- err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
- err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
- err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
- err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
- err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
- err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
- err |= __put_user (kbuf->st_size, &ubuf->st_size);
- err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
- err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
- err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
- err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
- err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
- return err;
+ struct stat64_emu31 tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ tmp.st_dev = (unsigned short)kbuf->st_dev;
+ tmp.st_ino = kbuf->st_ino;
+ tmp.__st_ino = (u32)kbuf->st_ino;
+ tmp.st_mode = kbuf->st_mode;
+ tmp.st_nlink = (unsigned int)kbuf->st_nlink;
+ tmp.st_uid = kbuf->st_uid;
+ tmp.st_gid = kbuf->st_gid;
+ tmp.st_rdev = (unsigned short)kbuf->st_rdev;
+ tmp.st_size = kbuf->st_size;
+ tmp.st_blksize = (u32)kbuf->st_blksize;
+ tmp.st_blocks = (u32)kbuf->st_blocks;
+ tmp.st_atime = (u32)kbuf->st_atime;
+ tmp.st_mtime = (u32)kbuf->st_mtime;
+ tmp.st_ctime = (u32)kbuf->st_ctime;
+
+ return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
return err;
set_fs (KERNEL_DS);
- ret = sys_newstat(tmp, &s);
+ ret = sys_newlstat(tmp, &s);
set_fs (old_fs);
putname(tmp);
if (putstat64 (statbuf, &s))
__u32 uc_flags;
__u32 uc_link; /* pointer */
stack_t32 uc_stack;
+ _sigregs32 uc_mcontext;
sigset_t32 uc_sigmask; /* mask last for extensibility */
- __u32 sc; /* pointer */
};
#endif /* !CONFIG_S390_SUPPORT */
+++ /dev/null
-/*
- * arch/s390/kernel/lowcore.S
- * S390 lowcore definition.
- *
- * S390 64 bit Version
- * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Hartmut Penner (hpenner@de.ibm.com)
- * Martin Schwidefsky (schwidefsky@de.ibm.com),
- */
-#include <asm/lowcore.h>
-
- .align 8192
- .globl init_S390_lowcore
-init_S390_lowcore:
- .fill 0x1a0-0x000,1,0
- .quad _RESTART_PSW_MASK
- .quad restart_int_handler
- .quad _EXT_PSW_MASK
- .quad ext_int_handler
- .quad _SVC_PSW_MASK
- .quad system_call
- .quad _PGM_PSW_MASK
- .quad pgm_check_handler
- .quad _MCCK_PSW_MASK
- .quad mcck_int_handler
-EXT_PSW: .quad _IO_PSW_MASK
- .quad io_int_handler
- .fill 0x2000-0x200,1,0
+++ /dev/null
-/*
- * arch/s390/kernel/mathemu.c
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *
- * 'mathemu.c' handles IEEE instructions on a S390 processor
- * that does not have the IEEE fpu
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-
-#include <asm/uaccess.h>
-#include <asm/mathemu.h>
-
-#ifdef CONFIG_SYSCTL
-int sysctl_ieee_emulation_warnings=1;
-#endif
-
-static void display_emulation_not_implemented(char *instr)
-{
- struct pt_regs *regs;
- __u16 *location;
-
-#if CONFIG_SYSCTL
- if(sysctl_ieee_emulation_warnings)
-#endif
- {
- regs=current->thread.regs;
- location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
- printk("%s ieee fpu instruction not emulated process name: %s pid: %d \n",
- instr,
- current->comm, current->pid);
- printk("%s's PSW: %08lx %08lx\n",instr,
- (unsigned long) regs->psw.mask,
- (unsigned long) location);
- }
-}
-
-
-static void set_CC_df(__u64 val1,__u64 val2) {
- int rc;
- rc = __cmpdf2(val1,val2);
- current->thread.regs->psw.mask &= 0xFFFFCFFFFFFFFFFFL;
- switch (rc) {
- case -1:
- current->thread.regs->psw.mask |= 0x0000100000000000L;
- break;
- case 1:
- current->thread.regs->psw.mask |= 0x0000200000000000L;
- break;
- }
-}
-
-static void set_CC_sf(__u32 val1,__u32 val2) {
- int rc;
- rc = __cmpsf2(val1,val2);
- current->thread.regs->psw.mask &= 0xFFFFCFFFFFFFFFFF;
- switch (rc) {
- case -1:
- current->thread.regs->psw.mask |= 0x0000100000000000L;
- break;
- case 1:
- current->thread.regs->psw.mask |= 0x0000200000000000L;
- break;
- }
-}
-
-
-static void emu_adb (int rx, __u64 val) {
- current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,val);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_adbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,
- current->thread.fp_regs.fprs[ry].d);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_aeb (int rx, __u32 val) {
- current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,val);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_aebr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,
- current->thread.fp_regs.fprs[ry].f);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_axbr (int rx, int ry) {
- display_emulation_not_implemented("axbr");
-}
-
-static void emu_cdb (int rx, __u64 val) {
- set_CC_df(current->thread.fp_regs.fprs[rx].d,val);
-}
-
-static void emu_cdbr (int rx, int ry) {
- set_CC_df(current->thread.fp_regs.fprs[rx].d,current->thread.fp_regs.fprs[ry].d);
-}
-
-static void emu_cdfbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d =
- __floatsidf(current->thread.regs->gprs[ry]);
-}
-
-static void emu_ceb (int rx, __u32 val) {
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,val);
-}
-
-static void emu_cebr (int rx, int ry) {
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,current->thread.fp_regs.fprs[ry].f);
-}
-
-static void emu_cefbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f =
- __floatsisf(current->thread.regs->gprs[ry]);
-}
-
-static void emu_cfdbr (int rx, int ry, int mask) {
- current->thread.regs->gprs[rx] =
- __fixdfsi(current->thread.fp_regs.fprs[ry].d);
-}
-
-static void emu_cfebr (int rx, int ry, int mask) {
- current->thread.regs->gprs[rx] =
- __fixsfsi(current->thread.fp_regs.fprs[ry].f);
-}
-
-static void emu_cfxbr (int rx, int ry, int mask) {
- display_emulation_not_implemented("cfxbr");
-}
-
-static void emu_cxbr (int rx, int ry) {
- display_emulation_not_implemented("cxbr");
-}
-
-static void emu_cxfbr (int rx, int ry) {
- display_emulation_not_implemented("cxfbr");
-}
-
-static void emu_ddb (int rx, __u64 val) {
- current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,val);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_ddbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,
- current->thread.fp_regs.fprs[ry].d);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_deb (int rx, __u32 val) {
- current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,val);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_debr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,
- current->thread.fp_regs.fprs[ry].f);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_didbr (int rx, int ry, int mask) {
- display_emulation_not_implemented("didbr");
-}
-
-static void emu_diebr (int rx, int ry, int mask) {
- display_emulation_not_implemented("diebr");
-}
-
-static void emu_dxbr (int rx, int ry) {
- display_emulation_not_implemented("dxbr");
-}
-
-static void emu_efpc (int rx, int ry) {
- display_emulation_not_implemented("efpc");
-}
-
-static void emu_fidbr (int rx, int ry, int mask) {
- display_emulation_not_implemented("fidbr");
-}
-
-static void emu_fiebr (int rx, int ry, int mask) {
- display_emulation_not_implemented("fiebr");
-}
-
-static void emu_fixbr (int rx, int ry, int mask) {
- display_emulation_not_implemented("fixbr");
-}
-
-static void emu_kdb (int rx, __u64 val) {
- display_emulation_not_implemented("kdb");
-}
-
-static void emu_kdbr (int rx, int ry) {
- display_emulation_not_implemented("kdbr");
-}
-
-static void emu_keb (int rx, __u32 val) {
- display_emulation_not_implemented("keb");
-}
-
-static void emu_kebr (int rx, int ry) {
- display_emulation_not_implemented("kebr");
-}
-
-static void emu_kxbr (int rx, int ry) {
- display_emulation_not_implemented("kxbr");
-}
-
-static void emu_lcdbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d =
- __negdf2(current->thread.fp_regs.fprs[ry].d);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_lcebr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f =
- __negsf2(current->thread.fp_regs.fprs[ry].f);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_lcxbr (int rx, int ry) {
- display_emulation_not_implemented("lcxbr");
-}
-
-static void emu_ldeb (int rx, __u32 val) {
- current->thread.fp_regs.fprs[rx].d = __extendsfdf2(val);
-}
-
-static void emu_ldebr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d =
- __extendsfdf2(current->thread.fp_regs.fprs[ry].f);
-}
-
-static void emu_ldxbr (int rx, int ry) {
- display_emulation_not_implemented("ldxbr");
-}
-
-static void emu_ledbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f = __truncdfsf2(current->thread.fp_regs.fprs[ry].d);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_lexbr (int rx, int ry) {
- display_emulation_not_implemented("lexbr");
-}
-
-static void emu_lndbr (int rx, int ry) {
- display_emulation_not_implemented("lndbr");
-}
-
-static void emu_lnebr (int rx, int ry) {
- display_emulation_not_implemented("lnebr");
-}
-
-static void emu_lnxbr (int rx, int ry) {
- display_emulation_not_implemented("lnxbr");
-}
-
-static void emu_lpdbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d = __absdf2(current->thread.fp_regs.fprs[ry].d);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0);
-}
-
-static void emu_lpebr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f = __abssf2(current->thread.fp_regs.fprs[ry].f);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_lpxbr (int rx, int ry) {
- display_emulation_not_implemented("lpxbr");
-}
-
-static void emu_ltdbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d = current->thread.fp_regs.fprs[ry].d;
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_ltebr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f = current->thread.fp_regs.fprs[ry].f;
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_ltxbr (int rx, int ry) {
- display_emulation_not_implemented("ltxbr");
-}
-
-static void emu_lxdb (int rx, __u64 val) {
- display_emulation_not_implemented("lxdb");
-}
-
-static void emu_lxdbr (int rx, int ry) {
- display_emulation_not_implemented("lxdbr");
-}
-
-static void emu_lxeb (int rx, __u32 val) {
- display_emulation_not_implemented("lxeb");
-}
-
-static void emu_lxebr (int rx, int ry) {
- display_emulation_not_implemented("lxebr");
-}
-
-static void emu_madb (int rx, __u64 val, int mask) {
- display_emulation_not_implemented("madb");
-}
-
-static void emu_madbr (int rx, int ry, int mask) {
- display_emulation_not_implemented("madbr");
-}
-
-static void emu_maeb (int rx, __u32 val, int mask) {
- display_emulation_not_implemented("maeb");
-}
-
-static void emu_maebr (int rx, int ry, int mask) {
- display_emulation_not_implemented("maebr");
-}
-
-static void emu_mdb (int rx, __u64 val) {
- current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,val);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_mdbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,
- current->thread.fp_regs.fprs[ry].d);
- set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_mdeb (int rx, __u32 val) {
- display_emulation_not_implemented("mdeb");
-}
-
-static void emu_mdebr (int rx, int ry) {
- display_emulation_not_implemented("mdebr");
-}
-
-static void emu_meeb (int rx, __u32 val) {
- current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f,
- val);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_meebr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f,
- current->thread.fp_regs.fprs[ry].f);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_msdb (int rx, __u64 val, int mask) {
- display_emulation_not_implemented("msdb");
-}
-
-static void emu_msdbr (int rx, int ry, int mask) {
- display_emulation_not_implemented("msdbr");
-}
-
-static void emu_mseb (int rx, __u32 val, int mask) {
- display_emulation_not_implemented("mseb");
-}
-
-static void emu_msebr (int rx, int ry, int mask) {
- display_emulation_not_implemented("msebr");
-}
-
-static void emu_mxbr (int rx, int ry) {
- display_emulation_not_implemented("mxbr");
-}
-
-static void emu_mxdb (int rx, __u64 val) {
- display_emulation_not_implemented("mxdb");
-}
-
-static void emu_mxdbr (int rx, int ry) {
- display_emulation_not_implemented("mxdbr");
-}
-
-static void emu_sdb (int rx, __u64 val) {
- current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d,
- val);
- set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_sdbr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d,
- current->thread.fp_regs.fprs[ry].d);
- set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL);
-}
-
-static void emu_seb (int rx, __u32 val) {
- current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f,
- val);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_sebr (int rx, int ry) {
- current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f,
- current->thread.fp_regs.fprs[ry].f);
- set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
-}
-
-static void emu_sfpc (int rx, int ry) {
- display_emulation_not_implemented("sfpc");
-}
-
-static void emu_sqdb (int rx, __u64 val) {
- display_emulation_not_implemented("sqdb");
-}
-
-static void emu_sqdbr (int rx, int ry) {
- display_emulation_not_implemented("sqdbr");
-}
-
-static void emu_sqeb (int rx, __u32 val) {
- display_emulation_not_implemented("sqeb");
-}
-
-static void emu_sqebr (int rx, int ry) {
- display_emulation_not_implemented("sqebr");
-}
-
-static void emu_sqxbr (int rx, int ry) {
- display_emulation_not_implemented("sqxbr");
-}
-
-static void emu_sxbr (int rx, int ry) {
- display_emulation_not_implemented("sxbr");
-}
-
-static void emu_tcdb (int rx, __u64 val) {
- display_emulation_not_implemented("tcdb");
-}
-
-static void emu_tceb (int rx, __u32 val) {
- display_emulation_not_implemented("tceb");
-}
-
-static void emu_tcxb (int rx, __u64 val) {
- display_emulation_not_implemented("tcxb");
-}
-
-
-static inline void emu_load_regd(int reg) {
- if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */
- __asm__ __volatile ( /* load reg from fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " ld 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].d)
- : "1" );
- }
-}
-
-static inline void emu_load_rege(int reg) {
- if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */
- __asm__ __volatile ( /* load reg from fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " le 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].f)
- : "1" );
- }
-}
-
-static inline void emu_store_regd(int reg) {
- if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */
- __asm__ __volatile ( /* store reg to fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " std 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].d)
- : "1" );
- }
-}
-
-
-static inline void emu_store_rege(int reg) {
- if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */
- __asm__ __volatile ( /* store reg to fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " ste 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].f)
- : "1" );
- }
-}
-
-int math_emu_b3(__u8 *opcode, struct pt_regs * regs) {
- static const __u8 format_table[] = {
- 2, 2, 2, 2, 9, 1, 2, 1, 2, 2, 2, 2, 9, 2, 4, 4,
- 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 3,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1,10, 1, 1, 3, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 3,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 0, 0, 0, 5, 6, 6, 0, 7, 8, 8, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- static const void *jump_table[]= {
- emu_lpebr, emu_lnebr, emu_ltebr, emu_lcebr,
- emu_ldebr, emu_lxdbr, emu_lxebr, emu_mxdbr,
- emu_kebr, emu_cebr, emu_aebr, emu_sebr,
- emu_mdebr, emu_debr, emu_maebr, emu_msebr,
- emu_lpdbr, emu_lndbr, emu_ltdbr, emu_lcdbr,
- emu_sqebr, emu_sqdbr, emu_sqxbr, emu_meebr,
- emu_kdbr, emu_cdbr, emu_adbr, emu_sdbr,
- emu_mdbr, emu_ddbr, emu_madbr, emu_msdbr,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- emu_lpxbr, emu_lnxbr, emu_ltxbr, emu_lcxbr,
- emu_ledbr, emu_ldxbr, emu_lexbr, emu_fixbr,
- emu_kxbr, emu_cxbr, emu_axbr, emu_sxbr,
- emu_mxbr, emu_dxbr, NULL, NULL,
- NULL, NULL, NULL, emu_diebr,
- NULL, NULL, NULL, emu_fiebr,
- NULL, NULL, NULL, emu_didbr,
- NULL, NULL, NULL, emu_fidbr,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- emu_sfpc, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- emu_efpc, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- emu_cefbr, emu_cdfbr, emu_cxfbr, NULL,
- emu_cfebr, emu_cfdbr, emu_cfxbr
- };
-
- switch (format_table[opcode[1]]) {
- case 1: /* RRE format, double operation */
- emu_store_regd((opcode[3]>>4)&15);
- emu_store_regd(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15);
- emu_load_regd((opcode[3]>>4)&15);
- emu_load_regd(opcode[3]&15);
- return 0;
- case 2: /* RRE format, float operation */
- emu_store_rege((opcode[3]>>4)&15);
- emu_store_rege(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15);
- emu_load_rege((opcode[3]>>4)&15);
- emu_load_rege(opcode[3]&15);
- return 0;
- case 3: /* RRF format, double operation */
- emu_store_regd((opcode[3]>>4)&15);
- emu_store_regd(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
- emu_load_regd((opcode[3]>>4)&15);
- emu_load_regd(opcode[3]&15);
- return 0;
- case 4: /* RRF format, float operation */
- emu_store_rege((opcode[3]>>4)&15);
- emu_store_rege(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
- emu_load_rege((opcode[3]>>4)&15);
- emu_load_rege(opcode[3]&15);
- return 0;
- case 5: /* RRE format, cefbr instruction */
- emu_store_rege((opcode[3]>>4)&15);
- /* call the emulation function */
- ((void (*)(int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15);
- emu_load_rege((opcode[3]>>4)&15);
- return 0;
- case 6: /* RRE format, cdfbr & cxfbr instruction */
- emu_store_regd((opcode[3]>>4)&15);
- /* call the emulation function */
- ((void (*)(int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15);
- emu_load_regd((opcode[3]>>4)&15);
- return 0;
- /* FIXME !! */
- return 0;
- case 7: /* RRF format, cfebr instruction */
- emu_store_rege(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
- return 0;
- case 8: /* RRF format, cfdbr & cfxbr instruction */
- emu_store_regd(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
- return 0;
- case 9: /* RRE format, ldebr & mdebr instruction */
- /* float store but double load */
- emu_store_rege((opcode[3]>>4)&15);
- emu_store_rege(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15);
- emu_load_regd((opcode[3]>>4)&15);
- return 0;
- case 10: /* RRE format, ledbr instruction */
- /* double store but float load */
- emu_store_regd((opcode[3]>>4)&15);
- emu_store_regd(opcode[3]&15);
- /* call the emulation function */
- ((void (*)(int, int))jump_table[opcode[1]])
- (opcode[3]>>4,opcode[3]&15);
- emu_load_rege((opcode[3]>>4)&15);
- return 0;
- default:
- return 1;
- }
-}
-
-static void* calc_addr(struct pt_regs *regs,int rx,int rb,int disp)
-{
- rx &= 0xf;
- rb &= 0xf;
- disp &= 0xfff;
- return (void*) ((rx != 0 ? regs->gprs[rx] : 0) + /* index */
- (rb != 0 ? regs->gprs[rb] : 0) + /* base */
- disp);
-}
-
-int math_emu_ed(__u8 *opcode, struct pt_regs * regs) {
- static const __u8 format_table[] = {
- 0, 0, 0, 0, 5, 1, 2, 1, 2, 2, 2, 2, 5, 2, 4, 4,
- 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 1, 1, 1, 1, 3, 3,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- static const void *jump_table[]= {
- NULL, NULL, NULL, NULL,
- emu_ldeb, emu_lxdb, emu_lxeb, emu_mxdb,
- emu_keb, emu_ceb, emu_aeb, emu_seb,
- emu_mdeb, emu_deb, emu_maeb, emu_mseb,
- emu_tceb, emu_tcdb, emu_tcxb, NULL,
- emu_sqeb, emu_sqdb, NULL, emu_meeb,
- emu_kdb, emu_cdb, emu_adb, emu_sdb,
- emu_mdb, emu_ddb, emu_madb, emu_msdb
- };
-
- switch (format_table[opcode[5]]) {
- case 1: /* RXE format, __u64 constant */ {
- __u64 *dxb, temp;
- __u32 opc;
-
- emu_store_regd((opcode[1]>>4)&15);
- opc = *((__u32 *) opcode);
- dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if copy_from_user fails ? */
- copy_from_user(&temp, dxb, 8);
- /* call the emulation function */
- ((void (*)(int, __u64))jump_table[opcode[5]])
- (opcode[1]>>4,temp);
- emu_load_regd((opcode[1]>>4)&15);
- return 0;
- }
- case 2: /* RXE format, __u32 constant */ {
- __u32 *dxb, temp;
- __u32 opc;
-
- emu_store_rege((opcode[1]>>4)&15);
- opc = *((__u32 *) opcode);
- dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if get_user fails ? */
- get_user(temp, dxb);
- /* call the emulation function */
- ((void (*)(int, __u32))jump_table[opcode[5]])
- (opcode[1]>>4,temp);
- emu_load_rege((opcode[1]>>4)&15);
- return 0;
- }
- case 3: /* RXF format, __u64 constant */ {
- __u32 *dxb, temp;
- __u32 opc;
-
- emu_store_regd((opcode[1]>>4)&15);
- opc = *((__u32 *) opcode);
- dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if copy_from_user fails ? */
- copy_from_user(&temp, dxb, 8);
- /* call the emulation function */
- ((void (*)(int, __u32, int))jump_table[opcode[5]])
- (opcode[1]>>4,temp,opcode[4]>>4);
- emu_load_regd((opcode[1]>>4)&15);
- return 0;
- }
- case 4: /* RXF format, __u32 constant */ {
- __u32 *dxb, temp;
- __u32 opc;
-
- emu_store_rege((opcode[1]>>4)&15);
- opc = *((__u32 *) opcode);
- dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if get_user fails ? */
- get_user(temp, dxb);
- /* call the emulation function */
- ((void (*)(int, __u32, int))jump_table[opcode[5]])
- (opcode[1]>>4,temp,opcode[4]>>4);
- emu_load_rege((opcode[1]>>4)&15);
- return 0;
- }
- case 5: /* RXE format, __u32 constant */
- /* store_rege and load_regd */
- {
- __u32 *dxb, temp;
- __u32 opc;
- emu_store_rege((opcode[1]>>4)&15);
- opc = *((__u32 *) opcode);
- dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if get_user fails ? */
- get_user(temp, dxb);
- /* call the emulation function */
- ((void (*)(int, __u32))jump_table[opcode[5]])
- (opcode[1]>>4,temp);
- emu_load_regd((opcode[1]>>4)&15);
- return 0;
- }
- default:
- return 1;
- }
-}
-
-/*
- * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
- */
-void math_emu_ldr(__u8 *opcode) {
- __u16 opc = *((__u16 *) opcode);
-
- if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */
- /* we got an exception therfore ry can't be in {0,2,4,6} */
- __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */
- " bras 1,0f\n"
- " ld 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (opc&0x00f0),
- "a" (¤t->thread.fp_regs.fprs[opc&0x000f].d)
- : "1" );
- } else if ((opc & 0x0009) == 0) { /* test if ry in {0,2,4,6} */
- __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */
- " bras 1,0f\n"
- " std 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" ((opc&0x000f)<<4),
- "a" (¤t->thread.fp_regs.fprs[(opc&0x00f0)>>4].d)
- : "1" );
- } else { /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
- current->thread.fp_regs.fprs[(opc&0x00f0)>>4] =
- current->thread.fp_regs.fprs[opc&0x000f];
- }
-}
-
-/*
- * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
- */
-void math_emu_ler(__u8 *opcode) {
- __u16 opc = *((__u16 *) opcode);
-
- if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */
- /* we got an exception therfore ry can't be in {0,2,4,6} */
- __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */
- " bras 1,0f\n"
- " le 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (opc&0x00f0),
- "a" (¤t->thread.fp_regs.fprs[opc&0x000f].f)
- : "1" );
- } else if ((opc & 0x0009) == 0) { /* test if ry in {0,2,4,6} */
- __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */
- " bras 1,0f\n"
- " ste 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" ((opc&0x000f)<<4),
- "a" (¤t->thread.fp_regs.fprs[(opc&0x00f0)>>4].f)
- : "1" );
- } else { /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
- current->thread.fp_regs.fprs[(opc&0x00f0)>>4] =
- current->thread.fp_regs.fprs[opc&0x000f];
- }
-}
-
-/*
- * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6}
- */
-void math_emu_ld(__u8 *opcode, struct pt_regs * regs) {
- __u32 opc = *((__u32 *) opcode);
- __u64 *dxb;
-
- dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if copy_from_user fails ? */
- copy_from_user(¤t->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8);
-}
-
-/*
- * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6}
- */
-void math_emu_le(__u8 *opcode, struct pt_regs * regs) {
- __u32 opc = *((__u32 *) opcode);
- __u32 *mem, *dxb;
-
- dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if get_user fails ? */
- mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f);
- get_user(mem[0], dxb);
-}
-
-/*
- * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6}
- */
-void math_emu_std(__u8 *opcode, struct pt_regs * regs) {
- __u32 opc = *((__u32 *) opcode);
- __u64 *dxb;
- dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if copy_to_user fails ? */
- copy_to_user(dxb, ¤t->thread.fp_regs.fprs[(opc>>20)&15].d, 8);
-}
-
-/*
- * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6}
- */
-void math_emu_ste(__u8 *opcode, struct pt_regs * regs) {
- __u32 opc = *((__u32 *) opcode);
- __u32 *mem, *dxb;
- dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
- /* FIXME: how to react if put_user fails ? */
- mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f);
- put_user(mem[0], dxb);
-}
-
-/*
- * Emulate LFPC D(B)
- */
-int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) {
- /* FIXME: how to do that ?!? */
- return 0;
-}
-
-/*
- * Emulate STFPC D(B)
- */
-int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) {
- /* FIXME: how to do that ?!? */
- return 0;
-}
-
-/*
- * Emulate SRNM D(B)
- */
-int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) {
- /* FIXME: how to do that ?!? */
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <asm/processor.h>
#include <asm/irq.h>
-spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
-
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
/*
void show_regs(struct pt_regs *regs)
{
char buff[80];
- int line;
+ int i, line;
printk("CPU: %d\n",smp_processor_id());
printk("Process %s (pid: %d, stackpage=%016lX)\n",
for (line = 0; sprintf_regs(line, buff, current, regs); line++)
printk(buff);
+
+ if (regs->psw.mask & PSW_PROBLEM_STATE)
+ {
+ printk("User Code:\n");
+ memset(buff, 0, 20);
+ copy_from_user(buff,
+ (char *) (regs->psw.addr & PSW_ADDR_MASK), 20);
+ for (i = 0; i < 20; i++)
+ printk("%02x ", buff[i]);
+ printk("\n");
+ }
}
char *task_show_regs(struct task_struct *task, char *buffer)
asmlinkage int sys_fork(struct pt_regs regs)
{
- int ret;
-
- lock_kernel();
- ret = do_fork(SIGCHLD, regs.gprs[15], ®s, 0);
- unlock_kernel();
- return ret;
+ return do_fork(SIGCHLD, regs.gprs[15], ®s, 0);
}
asmlinkage int sys_clone(struct pt_regs regs)
{
unsigned long clone_flags;
unsigned long newsp;
- int ret;
- lock_kernel();
clone_flags = regs.gprs[3];
newsp = regs.orig_gpr2;
if (!newsp)
newsp = regs.gprs[15];
- ret = do_fork(clone_flags, newsp, ®s, 0);
- unlock_kernel();
- return ret;
+ return do_fork(clone_flags, newsp, ®s, 0);
}
/*
/*
* memory management
*/
-EXPORT_SYMBOL(_oi_bitmap);
-EXPORT_SYMBOL(_ni_bitmap);
-EXPORT_SYMBOL(_zb_findmap);
-EXPORT_SYMBOL(__copy_from_user_fixup);
-EXPORT_SYMBOL(__copy_to_user_fixup);
+EXPORT_SYMBOL_NOVERS(_oi_bitmap);
+EXPORT_SYMBOL_NOVERS(_ni_bitmap);
+EXPORT_SYMBOL_NOVERS(_zb_findmap);
+EXPORT_SYMBOL_NOVERS(__copy_from_user_fixup);
+EXPORT_SYMBOL_NOVERS(__copy_to_user_fixup);
/*
* semaphore ops
EXPORT_SYMBOL_NOVERS(strlen);
EXPORT_SYMBOL_NOVERS(strchr);
EXPORT_SYMBOL_NOVERS(strcmp);
-EXPORT_SYMBOL_NOVERS(strcat);
EXPORT_SYMBOL_NOVERS(strncat);
EXPORT_SYMBOL_NOVERS(strncmp);
EXPORT_SYMBOL_NOVERS(strncpy);
EXPORT_SYMBOL_NOVERS(strnlen);
EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL_NOVERS(strstr);
EXPORT_SYMBOL_NOVERS(strtok);
EXPORT_SYMBOL_NOVERS(strpbrk);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_device);
+EXPORT_SYMBOL_NOVERS(do_call_softirq);
-#if CONFIG_IP_MULTICAST
-/* Required for lcs gigibit ethernet multicast support */
-EXPORT_SYMBOL(arp_mc_map);
-#endif
unsigned int console_device = -1;
unsigned long memory_size = 0;
unsigned long machine_flags = 0;
+struct { unsigned long addr, size, type; } memory_chunk[16];
+#define CHUNK_READ_WRITE 0
+#define CHUNK_READ_ONLY 1
__u16 boot_cpu_addr;
int cpus_initialized = 0;
unsigned long cpu_initialized = 0;
* Setup function called from init/main.c just after the banner
* was printed.
*/
+extern char _pstart, _pend, _stext;
+
void __init setup_arch(char **cmdline_p)
{
unsigned long bootmap_size;
unsigned long start_pfn, end_pfn;
static unsigned int smptrap=0;
unsigned long delay = 0;
+ struct _lowcore *lowcore;
+ int i;
if (smptrap)
return;
smptrap=1;
- /*
- * Setup lowcore information for boot cpu
- */
- cpu_init();
- boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
- __cpu_logical_map[0] = boot_cpu_addr;
-
/*
* print what head.S has found out about the machine
*/
ROOT_DEV = to_kdev_t(0x0100);
memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/
- memory_end = memory_size; /* detected in head.s */
+ memory_end = memory_size & ~0x200000UL; /* detected in head.s */
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
bootmap_size = init_bootmem(start_pfn, end_pfn);
/*
- * Register RAM pages with the bootmem allocator.
+ * Register RAM areas with the bootmem allocator.
*/
- free_bootmem(start_pfn << PAGE_SHIFT,
- (end_pfn - start_pfn) << PAGE_SHIFT);
-
+ for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) {
+ unsigned long start_chunk, end_chunk;
+
+ if (memory_chunk[i].type != CHUNK_READ_WRITE)
+ continue;
+ start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
+ start_chunk >>= PAGE_SHIFT;
+ end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
+ end_chunk >>= PAGE_SHIFT;
+ if (start_chunk < start_pfn)
+ start_chunk = start_pfn;
+ if (end_chunk > end_pfn)
+ end_chunk = end_pfn;
+ if (start_chunk < end_chunk)
+ free_bootmem(start_chunk << PAGE_SHIFT,
+ (end_chunk - start_chunk) << PAGE_SHIFT);
+ }
+
/*
* Reserve the bootmem bitmap itself as well. We do this in two
* steps (first step was init_bootmem()) because this catches
}
#endif
+ /*
+ * Setup lowcore for boot cpu
+ */
+ lowcore = (struct _lowcore *)
+ __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0);
+ memset(lowcore, 0, 2*PAGE_SIZE);
+ lowcore->restart_psw.mask = _RESTART_PSW_MASK;
+ lowcore->restart_psw.addr = (addr_t) &restart_int_handler;
+ lowcore->external_new_psw.mask = _EXT_PSW_MASK;
+ lowcore->external_new_psw.addr = (addr_t) &ext_int_handler;
+ lowcore->svc_new_psw.mask = _SVC_PSW_MASK;
+ lowcore->svc_new_psw.addr = (addr_t) &system_call;
+ lowcore->program_new_psw.mask = _PGM_PSW_MASK;
+ lowcore->program_new_psw.addr = (addr_t) &pgm_check_handler;
+ lowcore->mcck_new_psw.mask = _MCCK_PSW_MASK;
+ lowcore->mcck_new_psw.addr = (addr_t) &mcck_int_handler;
+ lowcore->io_new_psw.mask = _IO_PSW_MASK;
+ lowcore->io_new_psw.addr = (addr_t) &io_int_handler;
+ lowcore->ipl_device = S390_lowcore.ipl_device;
+ lowcore->kernel_stack = ((__u32) &init_task_union) + 16384;
+ lowcore->async_stack = (__u64)
+ __alloc_bootmem(4*PAGE_SIZE, 4*PAGE_SIZE, 0) + 16384;
+ set_prefix((__u32)(__u64) lowcore);
+ cpu_init();
+ boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+ __cpu_logical_map[0] = boot_cpu_addr;
+
+ /*
+ * Create kernel page tables and switch to virtual addressing.
+ */
paging_init();
res = alloc_bootmem_low(sizeof(struct resource));
}
/*
- * Get CPU information for use by the procfs.
+ * get_cpuinfo - Get information on one CPU for use by procfs.
+ *
+ * Prints info on the next CPU into buffer. Beware, doesn't check for
+ * buffer overflow. Current implementation of procfs assumes that the
+ * resulting data is <= 1K.
+ *
+ * Args:
+ * buffer -- you guessed it, the data buffer
+ * cpu_np -- Input: next cpu to get (start at 0). Output: Updated.
+ *
+ * Returns number of bytes written to buffer.
*/
-int get_cpuinfo(char * buffer)
+int get_cpuinfo(char *buffer, unsigned *cpu_np)
{
struct cpuinfo_S390 *cpuinfo;
char *p = buffer;
- int i;
-
- p += sprintf(p,"vendor_id : IBM/S390\n"
- "# processors : %i\n"
- "bogomips per cpu: %lu.%02lu\n",
- smp_num_cpus, loops_per_jiffy/(500000/HZ),
- (loops_per_jiffy/(5000/HZ))%100);
- for (i = 0; i < smp_num_cpus; i++) {
- cpuinfo = &safe_get_cpu_lowcore(i).cpu_data;
- p += sprintf(p,"processor %i: "
- "version = %02X, "
- "identification = %06X, "
- "machine = %04X\n",
- i, cpuinfo->cpu_id.version,
- cpuinfo->cpu_id.ident,
- cpuinfo->cpu_id.machine);
- }
+ unsigned n;
+
+ n = *cpu_np;
+ while (n < NR_CPUS && (cpu_online_map & (1 << n)) == 0)
+ n++;
+ if (n >= NR_CPUS) {
+ *cpu_np = NR_CPUS;
+ return (0);
+ }
+ *cpu_np = n + 1;
+
+ if (n == 0) {
+ p += sprintf(p, "vendor_id : IBM/S390\n"
+ "# processors : %i\n"
+ "bogomips per cpu: %lu.%02lu\n",
+ smp_num_cpus, loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ))%100);
+ }
+ cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
+ p += sprintf(p, "processor %i: "
+ "version = %02X, "
+ "identification = %06X, "
+ "machine = %04X\n",
+ n, cpuinfo->cpu_id.version,
+ cpuinfo->cpu_id.ident,
+ cpuinfo->cpu_id.machine);
return p - buffer;
}
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
+#include <linux/personality.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
-#define DEBUG_SIG 0
-
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-/* pretcode & sig are used to store the return addr on Intel
- & the signal no as the first parameter we do this differently
- using gpr14 & gpr2. */
-
-#define SIGFRAME_COMMON \
-__u8 callee_used_stack[__SIGNAL_FRAMESIZE]; \
-struct sigcontext sc; \
-_sigregs sregs; \
-__u8 retcode[S390_SYSCALL_SIZE];
typedef struct
{
- SIGFRAME_COMMON
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
+ struct sigcontext sc;
+ _sigregs sregs;
+ __u8 retcode[S390_SYSCALL_SIZE];
} sigframe;
typedef struct
{
- SIGFRAME_COMMON
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
+ __u8 retcode[S390_SYSCALL_SIZE];
struct siginfo info;
struct ucontext uc;
} rt_sigframe;
err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
if(!err)
{
- regs->orig_gpr2 = -1; /* disable syscall checks */
+ regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
return(err);
}
-static int
-restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
- _sigregs *sregs,sigset_t *set)
-{
- unsigned int err;
-
- err=restore_sigregs(regs,sregs);
- if(!err)
- err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE);
- return(err);
-}
-
-int sigreturn_common(struct pt_regs *regs,int framesize)
+asmlinkage long sys_sigreturn(struct pt_regs *regs)
{
sigframe *frame = (sigframe *)regs->gprs[15];
sigset_t set;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- return -1;
- if (restore_sigcontext(&frame->sc,regs,&frame->sregs,&set))
- return -1;
+ goto badframe;
+ if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
+ goto badframe;
+
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(¤t->sigmask_lock);
current->blocked = set;
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
- return 0;
-}
-asmlinkage long sys_sigreturn(struct pt_regs *regs)
-{
-
- if (sigreturn_common(regs,sizeof(sigframe)))
+ if (restore_sigregs(regs, &frame->sregs))
goto badframe;
+
return regs->gprs[2];
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
{
rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
+ sigset_t set;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
- if (sigreturn_common(regs,sizeof(rt_sigframe)))
+ if (restore_sigregs(regs, &frame->uc.uc_mcontext))
goto badframe;
+
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
/*
* Set up a signal frame.
return (void *)((sp - frame_size) & -8ul);
}
-static void *setup_frame_common(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs,
- int frame_size,u16 retcode)
+static inline int map_signal(int sig)
{
- sigframe *frame;
- int err;
+ if (current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32)
+ return current->exec_domain->signal_invmap[sig];
+ else
+ return sig;
+}
- frame = get_sigframe(ka, regs,frame_size);
- if (!access_ok(VERIFY_WRITE, frame,frame_size))
- return 0;
- err = save_sigregs(regs,&frame->sregs);
- if(!err)
- err=__put_user(&frame->sregs,&frame->sc.sregs);
- if(!err)
+static void setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs * regs)
+{
+ sigframe *frame = get_sigframe(ka, regs, sizeof(sigframe));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
+ goto give_sigsegv;
+
+ if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
+ goto give_sigsegv;
+
+ if (save_sigregs(regs, &frame->sregs))
+ goto give_sigsegv;
+ if (__put_user(&frame->sregs, &frame->sc.sregs))
+ goto give_sigsegv;
- err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE);
- if(!err)
- {
- regs->gprs[2]=(current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig);
- /* Set up registers for signal handler */
- regs->gprs[15] = (addr_t)frame;
- regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
- regs->psw.mask = _USER_PSW_MASK;
- }
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
- err |= __put_user(retcode, (u16 *)(frame->retcode));
+ if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
+ (u16 *)(frame->retcode)))
+ goto give_sigsegv;
}
- return(err ? 0:frame);
-}
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs)
-{
- sigframe *frame;
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK;
- if((frame=setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
- (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
- goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
- /* Martin wants this for pthreads */
+ regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->sc;
/* We forgot to include these in the sigcontext.
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
- rt_sigframe *frame;
- addr_t orig_sp=regs->gprs[15];
- int err;
+ int err = 0;
+ rt_sigframe *frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
+ goto give_sigsegv;
- if((frame=setup_frame_common(sig,ka,set,regs,sizeof(rt_sigframe),
- (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
+ if (copy_siginfo_to_user(&frame->info, info))
goto give_sigsegv;
-
- err = copy_siginfo_to_user(&frame->info, info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(orig_sp),
+ err |= __put_user(sas_ss_flags(regs->gprs[15]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= __put_user(&frame->sc,&frame->uc.sc);
- regs->gprs[3] = (addr_t)&frame->info;
- regs->gprs[4] = (addr_t)&frame->uc;
-
+ err |= save_sigregs(regs, &frame->uc.uc_mcontext);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+ } else {
+ regs->gprs[14] = FIX_PSW(frame->retcode);
+ err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
+ (u16 *)(frame->retcode));
+ }
+
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK;
+
+ regs->gprs[2] = map_signal(sig);
+ regs->gprs[3] = (addr_t)&frame->info;
+ regs->gprs[4] = (addr_t)&frame->uc;
return;
give_sigsegv:
continue;
/* FALLTHRU */
- case SIGSTOP:
+ case SIGSTOP: {
+ struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+ sig = current->p_pptr->sig;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
+ }
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
+#include <linux/personality.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include "linux32.h"
-#define DEBUG_SIG 0
-
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-/* pretcode & sig are used to store the return addr on Intel
- & the signal no as the first parameter we do this differently
- using gpr14 & gpr2. */
-
-#define SIGFRAME_COMMON32 \
-__u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; \
-struct sigcontext32 sc; \
-_sigregs32 sregs; \
-__u8 retcode[S390_SYSCALL_SIZE];
+#define _USER_PSW_MASK32 0x0701C00080000000
typedef struct
{
- SIGFRAME_COMMON32
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
+ struct sigcontext32 sc;
+ _sigregs32 sregs;
+ __u8 retcode[S390_SYSCALL_SIZE];
} sigframe32;
typedef struct
{
- SIGFRAME_COMMON32
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
+ __u8 retcode[S390_SYSCALL_SIZE];
struct siginfo32 info;
struct ucontext32 uc;
} rt_sigframe32;
if(!err)
{
- regs->orig_gpr2 = -1; /* disable syscall checks */
+ regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
return(err);
}
-static int
-restore_sigcontext32(struct sigcontext32 *sc, struct pt_regs *regs,
- _sigregs32 *sregs,sigset_t *set)
-{
- unsigned int err;
-
- err=restore_sigregs32(regs,sregs);
- if(!err)
- err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE32);
- return(err);
-}
-
-int sigreturn_common32(struct pt_regs *regs)
+asmlinkage long sys32_sigreturn(struct pt_regs *regs)
{
sigframe32 *frame = (sigframe32 *)regs->gprs[15];
sigset_t set;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- return -1;
- if (restore_sigcontext32(&frame->sc,regs,&frame->sregs,&set))
- return -1;
+ goto badframe;
+ if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
+ goto badframe;
+
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(¤t->sigmask_lock);
current->blocked = set;
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
- return 0;
-}
-asmlinkage long sys32_sigreturn(struct pt_regs *regs)
-{
-
- if (sigreturn_common32(regs))
+ if (restore_sigregs32(regs, &frame->sregs))
goto badframe;
+
return regs->gprs[2];
badframe:
asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
{
rt_sigframe32 *frame = (rt_sigframe32 *)regs->gprs[15];
+ sigset_t set;
stack_t st;
int err;
mm_segment_t old_fs = get_fs();
- if (sigreturn_common32(regs))
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
goto badframe;
err = __get_user(st.ss_sp, &frame->uc.uc_stack.ss_sp);
err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
if (err)
goto badframe;
- set_fs (KERNEL_DS);
+
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
+ set_fs (KERNEL_DS);
do_sigaltstack(&st, NULL, regs->gprs[15]);
set_fs (old_fs);
return regs->gprs[2];
badframe:
- force_sig(SIGSEGV, current);
- return 0;
+ force_sig(SIGSEGV, current);
+ return 0;
}
/*
return (void *)((sp - frame_size) & -8ul);
}
-static void *setup_frame_common32(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs,
- int frame_size,u16 retcode)
+static inline int map_signal(int sig)
{
- sigframe32 *frame;
- int err;
+ if (current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32)
+ return current->exec_domain->signal_invmap[sig];
+ else
+ return sig;
+}
- frame = get_sigframe(ka, regs,frame_size);
- if (!access_ok(VERIFY_WRITE, frame,frame_size))
- return 0;
- err = save_sigregs32(regs,&frame->sregs);
- if(!err)
- err=__put_user(&frame->sregs,&frame->sc.sregs);
- if(!err)
+static void setup_frame32(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs * regs)
+{
+ sigframe32 *frame = get_sigframe(ka, regs, sizeof(sigframe32));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
+ goto give_sigsegv;
+
+ if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
+ goto give_sigsegv;
+
+ if (save_sigregs32(regs, &frame->sregs))
+ goto give_sigsegv;
+ if (__put_user(&frame->sregs, &frame->sc.sregs))
+ goto give_sigsegv;
- err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE32);
- if(!err)
- {
- regs->gprs[2]=(current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig);
- /* Set up registers for signal handler */
- regs->gprs[15] = (addr_t)frame;
- regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
- }
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+ regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
} else {
- regs->gprs[14] = FIX_PSW(frame->retcode);
- err |= __put_user(retcode, (u16 *)(frame->retcode));
- }
- return(err ? 0:frame);
-}
+ regs->gprs[14] = FIX_PSW(frame->retcode);
+ if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
+ (u16 *)(frame->retcode)))
+ goto give_sigsegv;
+ }
-static void setup_frame32(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs)
-{
- sigframe32 *frame;
-
- if((frame=setup_frame_common32(sig,ka,set,regs,sizeof(sigframe32),
- (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
- goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
- /* Martin wants this for pthreads */
- regs->gprs[3] = (addr_t)&frame->sc;
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK32;
+
+ regs->gprs[2] = map_signal(sig);
+ regs->gprs[3] = (addr_t)&frame->sc;
+
+ /* We forgot to include these in the sigcontext.
+ To avoid breaking binary compatibility, they are passed as args. */
+ regs->gprs[4] = current->thread.trap_no;
+ regs->gprs[5] = current->thread.prot_addr;
return;
give_sigsegv:
static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
- rt_sigframe32 *frame;
- addr_t orig_sp=regs->gprs[15];
- int err;
+ int err = 0;
+ rt_sigframe32 *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
+ goto give_sigsegv;
- if((frame=setup_frame_common32(sig,ka,set,regs,sizeof(rt_sigframe32),
- (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
+ if (copy_siginfo_to_user32(&frame->info, info))
goto give_sigsegv;
-
- err = copy_siginfo_to_user32(&frame->info, info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(orig_sp),
- &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(sas_ss_flags(regs->gprs[15]),
+ &frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- regs->gprs[3] = (addr_t)&frame->info;
- regs->gprs[4] = (addr_t)&frame->uc;
-
+ err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+ } else {
+ regs->gprs[14] = FIX_PSW(frame->retcode);
+ err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
+ (u16 *)(frame->retcode));
+ }
+
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK32;
+
+ regs->gprs[2] = map_signal(sig);
+ regs->gprs[3] = (addr_t)&frame->info;
+ regs->gprs[4] = (addr_t)&frame->uc;
return;
give_sigsegv:
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
/* Are we from a system call? */
- if (regs->orig_gpr2 >= 0) {
+ if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */
switch (regs->gprs[2]) {
case -ERESTARTNOHAND:
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
- lock_kernel();
sigaddset(¤t->pending.signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
}
/* Did we come from a system call? */
- if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
+ if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
/* Restart the system call - no handlers present */
if (regs->gprs[2] == -ERESTARTNOHAND ||
regs->gprs[2] == -ERESTARTSYS ||
spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+unsigned long cpu_online_map;
+
/*
* Setup routine for controlling SMP activation
*
extern void reipl(unsigned long devno);
+static sigp_ccode smp_ext_bitcall(int, ec_bit_sig);
+static void smp_ext_bitcall_others(ec_bit_sig);
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
+ */
+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
+
+struct call_data_struct {
+ void (*func) (void *info);
+ void *info;
+ atomic_t started;
+ atomic_t finished;
+ int wait;
+};
+
+static struct call_data_struct * call_data;
+
+/*
+ * 'Call function' interrupt callback
+ */
+static void do_call_function(void)
+{
+ void (*func) (void *info) = call_data->func;
+ void *info = call_data->info;
+ int wait = call_data->wait;
+
+ atomic_inc(&call_data->started);
+ (*func)(info);
+ if (wait)
+ atomic_inc(&call_data->finished);
+}
+
+/*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ */
+
+int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+ int wait)
+/*
+ * [SUMMARY] Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <nonatomic> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+{
+ struct call_data_struct data;
+ int cpus = smp_num_cpus-1;
+
+ if (!cpus || !atomic_read(&smp_commenced))
+ return 0;
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.started, 0);
+ data.wait = wait;
+ if (wait)
+ atomic_set(&data.finished, 0);
+
+ spin_lock_bh(&call_lock);
+ call_data = &data;
+ /* Send a message to all other CPUs and wait for them to respond */
+ smp_ext_bitcall_others(ec_call_function);
+
+ /* Wait for response */
+ while (atomic_read(&data.started) != cpus)
+ barrier();
+
+ if (wait)
+ while (atomic_read(&data.finished) != cpus)
+ barrier();
+ spin_unlock_bh(&call_lock);
+
+ return 0;
+}
+
+
+/*
+ * Various special callbacks
+ */
+
void do_machine_restart(void)
{
smp_send_stop();
void do_ext_call_interrupt(struct pt_regs *regs, __u16 code)
{
- ec_ext_call *ec, *next;
unsigned long bits;
/*
do_machine_halt();
if (test_bit(ec_power_off, &bits))
do_machine_power_off();
-
- /*
- * Handle external call commands with a parameter area
- */
- ec = (ec_ext_call *) xchg(&S390_lowcore.ext_call_queue, 0);
- if (ec == NULL)
- return; /* no command signals */
-
- /* Make a fifo out of the lifo */
- next = ec->next;
- ec->next = NULL;
- while (next != NULL) {
- ec_ext_call *tmp = next->next;
- next->next = ec;
- ec = next;
- next = tmp;
- }
-
- /* Execute every sigp command on the queue */
- while (ec != NULL) {
- switch (ec->cmd) {
- case ec_callback_async: {
- void (*func)(void *info);
- void *info;
-
- func = ec->func;
- info = ec->info;
- atomic_set(&ec->status,ec_executing);
- (func)(info);
- return;
- }
- case ec_callback_sync:
- atomic_set(&ec->status,ec_executing);
- (ec->func)(ec->info);
- atomic_set(&ec->status,ec_done);
- return;
- default:
- }
- ec = ec->next;
- }
-}
-
-/*
- * Swap in a new request to external call queue
- */
-static inline void smp_add_ext_call(ec_ext_call *ec, struct _lowcore *lowcore)
-{
- int success;
-
- while (1) {
- ec->next = (ec_ext_call*) lowcore->ext_call_queue;
- __asm__ __volatile__ (
- " lgr 0,%2\n"
- " csg 0,%3,%1\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (success), "+m" (lowcore->ext_call_queue)
- : "d" (ec->next), "d" (ec)
- : "cc", "0" );
- if (success == 0) break;
- }
-}
-
-/*
- * Send an external call sigp to another cpu and wait for its completion.
- */
-sigp_ccode
-smp_ext_call(int cpu, void (*func)(void *info), void *info, int wait)
-{
- sigp_ccode ccode;
- ec_ext_call ec;
-
- ec.cmd = wait ? ec_callback_sync:ec_callback_async;
- atomic_set(&ec.status, ec_pending);
- ec.func = func;
- ec.info = info;
- /* swap in new request to external call queue */
- smp_add_ext_call(&ec, &get_cpu_lowcore(cpu));
- /*
- * We try once to deliver the signal. There are four possible
- * return codes:
- * 0) Order code accepted - can't show up on an external call
- * 1) Status stored - fine, wait for completion.
- * 2) Busy - there is another signal pending. Thats fine too, because
- * do_ext_call from the pending signal will execute all signals on
- * the queue. We wait for completion.
- * 3) Not operational - something very bad has happened to the cpu.
- * do not wait for completion.
- */
- ccode = signal_processor(cpu, sigp_external_call);
-
- if (ccode != sigp_not_operational)
- /* wait for completion, FIXME: possible seed of a deadlock */
- while (atomic_read(&ec.status) != (wait?ec_done:ec_executing));
-
- return ccode;
-}
-
-/*
- * Send a callback sigp to every other cpu in the system.
- */
-void smp_ext_call_others(void (*func)(void *info), void *info, int wait)
-{
- ec_ext_call ec[NR_CPUS];
- sigp_ccode ccode;
- int i;
-
- for (i = 0; i < smp_num_cpus; i++) {
- if (smp_processor_id() == i)
- continue;
- ec[i].cmd = wait ? ec_callback_sync : ec_callback_async;
- atomic_set(&ec[i].status, ec_pending);
- ec[i].func = func;
- ec[i].info = info;
- smp_add_ext_call(ec+i, &get_cpu_lowcore(i));
- ccode = signal_processor(i, sigp_external_call);
- }
-
- /* wait for completion, FIXME: possible seed of a deadlock */
- for (i = 0; i < smp_num_cpus; i++) {
- if (smp_processor_id() == i)
- continue;
- while (atomic_read(&ec[i].status) !=
- (wait ? ec_done:ec_executing));
- }
+ if (test_bit(ec_call_function, &bits))
+ do_call_function();
}
/*
* Send an external call sigp to another cpu and return without waiting
* for its completion.
*/
-sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
+static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
{
sigp_ccode ccode;
* Send an external call sigp to every other cpu in the system and
* return without waiting for its completion.
*/
-void smp_ext_bitcall_others(ec_bit_sig sig)
+static void smp_ext_bitcall_others(ec_bit_sig sig)
{
sigp_ccode ccode;
int i;
}
}
-/*
- * cycles through all the cpus,
- * returns early if info is not NULL & the processor has something
- * of intrest to report in the info structure.
- * it returns the next cpu to check if it returns early.
- * i.e. it should be used as follows if you wish to receive info.
- * next_cpu=0;
- * do
- * {
- * info->cpu=next_cpu;
- * next_cpu=smp_signal_others(order_code,parameter,1,info);
- * ... check info here
- * } while(next_cpu<=smp_num_cpus)
- *
- * if you are lazy just use it like
- * smp_signal_others(order_code,parameter,0,1,NULL);
- */
-int smp_signal_others(sigp_order_code order_code, u32 parameter,
- int spin, sigp_info *info)
-{
- sigp_ccode ccode;
- u32 dummy;
- u16 i;
-
- if (info)
- info->intresting = 0;
- for (i = (info ? info->cpu : 0); i < smp_num_cpus; i++) {
- if (smp_processor_id() != i) {
- do {
- ccode = signal_processor_ps(
- (info ? &info->status : &dummy),
- parameter, i, order_code);
- } while(spin && ccode == sigp_busy);
- if (info && ccode != sigp_order_code_accepted) {
- info->intresting = 1;
- info->cpu = i;
- info->ccode = ccode;
- i++;
- break;
- }
- }
- }
- return i;
-}
-
/*
* this function sends a 'stop' sigp to all other CPUs in the system.
* it goes straight through.
/* stop all processors */
- smp_signal_others(sigp_stop, 0, 1, NULL);
+ for (i = 0; i < smp_num_cpus; i++) {
+ if (smp_processor_id() != i) {
+ int ccode;
+ do {
+ ccode = signal_processor_ps(
+ &dummy,
+ 0,
+ i,
+ sigp_stop);
+ } while(ccode == sigp_busy);
+ }
+ }
/* store status of all processors in their lowcores (real 0) */
parms.end_ctl = cr;
parms.orvals[cr] = 1 << bit;
parms.andvals[cr] = -1L;
- smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
+ smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
}
__ctl_set_bit(cr, bit);
}
parms.end_ctl = cr;
parms.orvals[cr] = 0;
parms.andvals[cr] = ~(1L << bit);
- smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
+ smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
}
__ctl_clear_bit(cr, bit);
}
-/*
- * Call a function on all other processors
- */
-
-int
-smp_call_function(void (*func)(void *info), void *info, int retry, int wait)
-/*
- * [SUMMARY] Run a function on all other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <retry> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler, you may call it from a bottom half handler.
- */
-{
- if (atomic_read(&smp_commenced) != 0)
- smp_ext_call_others(func, info, wait);
- return 0;
-}
/*
* Lets check how many CPUs we have.
init_tasks[cpu] = idle;
cpu_lowcore=&get_cpu_lowcore(cpu);
- cpu_lowcore->kernel_stack=idle->thread.ksp;
- __asm__ __volatile__("stctg 0,15,%0\n\t"
- "stam 0,15,%1"
+ cpu_lowcore->save_area[15] = idle->thread.ksp;
+ cpu_lowcore->kernel_stack = (idle->thread.ksp | 16383) + 1;
+ __asm__ __volatile__("la 1,%0\n\t"
+ "stctg 0,15,0(1)\n\t"
+ "la 1,%1\n\t"
+ "stam 0,15,0(1)"
: "=m" (cpu_lowcore->cregs_save_area[0]),
"=m" (cpu_lowcore->access_regs_save_area[0])
- : : "memory");
+ : : "1", "memory");
eieio();
signal_processor(cpu,sigp_restart);
+ /* Mark this cpu as online. */
+ set_bit(cpu, &cpu_online_map);
}
/*
void __init smp_boot_cpus(void)
{
struct _lowcore *curr_lowcore;
+ unsigned long async_stack;
sigp_ccode ccode;
int i;
printk("smp_boot_cpus failed to allocate prefix memory\n");
break;
}
+ async_stack = __get_free_pages(GFP_KERNEL,2);
+ if (async_stack == 0) {
+ printk("smp_boot_cpus failed to allocate asyncronous"
+ " interrupt stack\n");
+ free_page((unsigned long) curr_lowcore);
+ break;
+ }
lowcore_ptr[i] = curr_lowcore;
memcpy(curr_lowcore, &S390_lowcore, sizeof(struct _lowcore));
+ curr_lowcore->async_stack = async_stack + (4 * PAGE_SIZE);
/*
* Most of the parameters are set up when the cpu is
* started up.
s390_do_profile(regs->psw.addr);
if (!--prof_counter[cpu]) {
- int system = 1-user;
- struct task_struct * p = current;
/*
* The multiplier may have changed since the last time we got
* WrongThing (tm) to do.
*/
- irq_enter(cpu, 0);
update_process_times(user);
- irq_exit(cpu, 0);
}
}
extern __u16 boot_cpu_addr;
#endif
-void do_timer_interrupt(struct pt_regs *regs,int error_code)
+void do_timer_interrupt(struct pt_regs *regs, __u16 error_code)
{
- unsigned long flags;
+ int cpu = smp_processor_id();
+
+ irq_enter(cpu, 0);
/*
* reset timer to 10ms minus time already elapsed
* since timer-interrupt pending
*/
-
- save_flags(flags);
- cli();
#ifdef CONFIG_SMP
if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) {
write_lock(&xtime_lock);
write_unlock(&xtime_lock);
#endif
}
- restore_flags(flags);
+ irq_exit(cpu, 0);
}
/*
init_timer_cc -= 0x8126d60e46000000LL -
(0x3c26700LL*1000000*4096);
tod_to_timeval(init_timer_cc, &xtime);
+
+ /* Set do_get_fast_time function pointer. */
+ do_get_fast_time = do_gettimeofday;
}
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/atomic.h>
-#include <asm/mathemu.h>
#if CONFIG_REMOTE_DEBUG
#include <asm/gdb-stub.h>
#endif
extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code);
#endif
-spinlock_t die_lock;
+spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
void die(const char * str, struct pt_regs * regs, long err)
{
console_verbose();
spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
printk("%s: %04lx\n", str, err & 0xffff);
show_regs(regs);
+ bust_spinlocks(0);
spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
llgfr %r4,%r4 # unsigned long
jg sys32_fcntl64 # branch to system call
+ .globl sys32_stat64_wrapper
+sys32_stat64_wrapper:
+ llgtr %r2,%r2 # char *
+ llgtr %r3,%r3 # struct stat64 *
+ llgfr %r4,%r4 # long
+ jg sys32_stat64 # branch to system call
+
+ .globl sys32_lstat64_wrapper
+sys32_lstat64_wrapper:
+ llgtr %r2,%r2 # char *
+ llgtr %r3,%r3 # struct stat64 *
+ llgfr %r4,%r4 # long
+ jg sys32_lstat64 # branch to system call
+
+ .globl sys32_fstat64_wrapper
+sys32_fstat64_wrapper:
+ llgfr %r2,%r2 # unsigned long
+ llgtr %r3,%r3 # struct stat64 *
+ llgfr %r4,%r4 # long
+ jg sys32_fstat64 # branch to system call
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/spinlock.h>
#include <asm/uaccess.h>
extern const struct exception_table_entry __start___ex_table[];
return 0;
}
+extern spinlock_t modlist_lock;
+
unsigned long
search_exception_table(unsigned long addr)
{
- unsigned long ret;
+ unsigned long ret = 0;
+ unsigned long flags;
#ifndef CONFIG_MODULES
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
- if (ret) return FIX_PSW(ret);
+ return ret;
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
+
+ spin_lock_irqsave(&modlist_lock, flags);
for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->ex_table_start == NULL)
+ if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
continue;
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
- if (ret) return FIX_PSW(ret);
+ if (ret)
+ break;
}
+ spin_unlock_irqrestore(&modlist_lock, flags);
+ return ret;
#endif
-
- return 0;
}
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Hartmut Penner (hp@de.ibm.com)
+ * Ulrich Weigand (uweigand@de.ibm.com)
*
* Derived from "arch/i386/mm/fault.c"
* Copyright (C) 1995 Linus Torvalds
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/console.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#endif
extern void die(const char *,struct pt_regs *,long);
+static void force_sigsegv(struct task_struct *tsk, int code, void *address);
extern spinlock_t timerlist_lock;
/*
* Unlock any spinlocks which will prevent us from getting the
- * message out
+ * message out (timerlist_lock is acquired through the
+ * console unblank code)
*/
void bust_spinlocks(int yes)
{
- spin_lock_init(&timerlist_lock);
- if (yes) {
- oops_in_progress = 1;
-#ifdef CONFIG_SMP
- atomic_set(&global_irq_lock,0);
-#endif
- } else {
- int loglevel_save = console_loglevel;
- oops_in_progress = 0;
- /*
- * OK, the message is on the console. Now we call printk()
- * without oops_in_progress set so that printk will give klogd
- * a poke. Hold onto your hats...
- */
- console_loglevel = 15; /* NMI oopser may have shut the console up */
- printk(" ");
- console_loglevel = loglevel_save;
- }
+ spin_lock_init(&timerlist_lock);
+ if (yes) {
+ oops_in_progress = 1;
+ } else {
+ int loglevel_save = console_loglevel;
+ oops_in_progress = 0;
+ console_unblank();
+ /*
+ * OK, the message is on the console. Now we call printk()
+ * without oops_in_progress set so that printk will give klogd
+ * a poke. Hold onto your hats...
+ */
+ console_loglevel = 15;
+ printk(" ");
+ console_loglevel = loglevel_save;
+ }
}
/*
int si_code = SEGV_MAPERR;
int kernel_address = 0;
+ tsk = current;
+ mm = tsk->mm;
+
+ /*
+ * Check for low-address protection. This needs to be treated
+ * as a special case because the translation exception code
+ * field is not guaranteed to contain valid data in this case.
+ */
+ if ((error_code & 0xff) == 4 && !(S390_lowcore.trans_exc_code & 4)) {
+
+ /* Low-address protection hit in kernel mode means
+ NULL pointer write access in kernel mode. */
+ if (!(regs->psw.mask & PSW_PROBLEM_STATE)) {
+ address = 0;
+ kernel_address = 1;
+ goto no_context;
+ }
+
+ /* Low-address protection hit in user mode 'cannot happen'. */
+ die ("Low-address protection", regs, error_code);
+ do_exit(SIGKILL);
+ }
+
/*
* get the failing address
* more specific the segment and page table portion of
address = S390_lowcore.trans_exc_code&-4096L;
- tsk = current;
- mm = tsk->mm;
-
- if (in_interrupt() || !mm)
- goto no_context;
/*
* Check which address space the address belongs to
}
}
die("page fault via unknown access register", regs, error_code);
+ do_exit(SIGKILL);
break;
case 2: /* Secondary Segment Table Descriptor */
break;
}
+ /*
+ * Check whether we have a user MM in the first place.
+ */
+ if (in_interrupt() || !mm)
+ goto no_context;
/*
* When we get here, the fault happened in the current
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
- if (!vma) {
- printk("no vma for address %lX\n",address);
+ if (!vma)
goto bad_area;
- }
if (vma->vm_start <= address)
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
}
+ survive:
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
/* User mode accesses just cause a SIGSEGV */
if (regs->psw.mask & PSW_PROBLEM_STATE) {
- struct siginfo si;
tsk->thread.prot_addr = address;
tsk->thread.trap_no = error_code;
#ifndef CONFIG_SYSCTL
show_regs(regs);
}
#endif
- si.si_signo = SIGSEGV;
- si.si_code = si_code;
- si.si_addr = (void*) address;
- force_sig_info(SIGSEGV, &si, tsk);
+
+ force_sigsegv(tsk, si_code, (void *)address);
return;
}
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*/
+
if (kernel_address)
printk(KERN_ALERT "Unable to handle kernel pointer dereference"
" at virtual kernel address %016lx\n", address);
printk(KERN_ALERT "Unable to handle kernel paging request"
" at virtual user address %016lx\n", address);
-/*
- * need to define, which information is useful here
- */
-
die("Oops", regs, error_code);
do_exit(SIGKILL);
*/
out_of_memory:
up_read(&mm->mmap_sem);
+ if (tsk->pid == 1) {
+ tsk->policy |= SCHED_YIELD;
+ schedule();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
printk("VM: killing process %s\n", tsk->comm);
if (regs->psw.mask & PSW_PROBLEM_STATE)
do_exit(SIGKILL);
goto no_context;
}
+/*
+ * Send SIGSEGV to task. This is an external routine
+ * to keep the stack usage of do_page_fault small.
+ */
+static void force_sigsegv(struct task_struct *tsk, int code, void *address)
+{
+ struct siginfo si;
+ si.si_signo = SIGSEGV;
+ si.si_code = code;
+ si.si_addr = address;
+ force_sig_info(SIGSEGV, &si, tsk);
+}
+
+
#ifdef CONFIG_PFAULT
/*
* 'pfault' pseudo page faults routines.
int resolved;
} pseudo_wait_t;
-static pseudo_wait_t *pseudo_lock_queue = NULL;
-static spinlock_t pseudo_wait_spinlock; /* spinlock to protect lock queue */
-
int pfault_init(void)
{
pfault_refbk_t refbk =
- { 0x258, 0, 5, 2, __LC_KERNEL_STACK, 1ULL << 48, 1ULL << 48, 0ULL };
+ { 0x258, 0, 5, 2, __LC_KERNEL_STACK, 1ULL << 48, 1ULL << 48,
+ 0x8000000000000000ULL };
int rc;
if (pfault_disable)
asmlinkage void
pfault_interrupt(struct pt_regs *regs, __u16 error_code)
{
- DECLARE_WAITQUEUE(wait, current);
struct task_struct *tsk;
wait_queue_head_t queue;
wait_queue_head_t *qp;
* external interrupt.
*/
subcode = S390_lowcore.cpu_addr;
- if ((subcode & 0xff00) != 0x06)
+ if ((subcode & 0xff00) != 0x0600)
return;
/*
#include <asm/dma.h>
#include <asm/lowcore.h>
#include <asm/tlb.h>
-
+
mmu_gather_t mmu_gathers[NR_CPUS];
static unsigned long totalram_pages;
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
-static int test_access(unsigned long loc)
-{
- static const int ssm_mask = 0x07000000L;
- int rc, i;
-
- rc = 0;
- for (i=0; i<2; i++) {
- __asm__ __volatile__(
- " slgr %0,%0\n"
- " ssm %1\n"
- " tprot 0(%2),0\n"
- "0: jne 1f\n"
- " lghi %0,1\n"
- "1: ssm %3\n"
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous"
- : "+&d" (rc) : "i" (0), "a" (loc), "m" (ssm_mask)
- : "cc");
- if (rc == 0)
- break;
- loc += 0x100000;
- }
- return rc;
-}
-
int do_check_pgt_cache(int low, int high)
{
int freed = 0;
if(pgtable_cache_size > high) {
do {
- if(pgd_quicklist)
- free_pgd_slow(get_pgd_fast()), freed += 4;
- if(pmd_quicklist)
- pmd_free_slow(pmd_alloc_one_fast(NULL, 0)), freed += 4;
- if(pte_quicklist)
- pte_free_slow(pte_alloc_one_fast(NULL, 0)), freed++;
+ if(pgd_quicklist) {
+ free_pgd_slow(get_pgd_fast());
+ freed += 4;
+ }
+ if(pmd_quicklist) {
+ pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
+ freed += 4;
+ }
+ if(pte_quicklist) {
+ pte_free_slow(pte_alloc_one_fast(NULL, 0));
+ freed += 4;
+ }
} while(pgtable_cache_size > low);
}
return freed;
int i,j,k;
unsigned long address=0;
unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) |
- _REGION_TABLE;
+ _KERN_REGION_TABLE;
unsigned long end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE);
static const int ssm_mask = 0x04000000L;
void __init mem_init(void)
{
unsigned long codesize, reservedpages, datasize, initsize;
- unsigned long tmp;
max_mapnr = num_physpages = max_low_pfn;
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem();
- /* mark usable pages in the mem_map[] and count reserved pages */
reservedpages = 0;
- tmp = 0;
- do {
- if (tmp && (tmp & 0x1ff) == 0 &&
- test_access(tmp * PAGE_SIZE) == 0) {
- printk("2M Segment 0x%016lX not available\n",
- tmp * PAGE_SIZE);
- do {
- set_bit(PG_reserved, &mem_map[tmp].flags);
- reservedpages++;
- tmp++;
- } while (tmp < max_low_pfn && (tmp & 0x1ff));
- } else {
- if (PageReserved(mem_map+tmp))
- reservedpages++;
- tmp++;
- }
- } while (tmp < max_low_pfn);
codesize = (unsigned long) &_etext - (unsigned long) &_text;
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
module_init(mouse_rpc_init);
module_exit(mouse_rpc_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("RiscPC mouse driver");
+MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
module_init(acornscsi_init);
module_exit(acornscsi_exit);
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("AcornSCSI driver");
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
module_init(init_arxe_scsi_driver);
module_exit(exit_arxe_scsi_driver);
+MODULE_AUTHOR("Stefan Hanske");
+MODULE_DESCRIPTION("ARXESCSI driver for Acorn machines");
MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
static struct expansion_card *ecs[MAX_ECARDS];
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("Cumana SCSI II driver");
-MODULE_PARM(term, "1-8i");
-MODULE_PARM_DESC(term, "SCSI bus termination");
-MODULE_LICENSE("GPL");
-
/*
* Use term=0,1,0,0,0 to turn terminators on/off
*/
module_init(cumanascsi2_init);
module_exit(cumanascsi2_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Cumana SCSI-2 driver for Acorn machines");
+MODULE_PARM(term, "1-8i");
+MODULE_PARM_DESC(term, "SCSI bus termination");
+MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
module_init(ecoscsi_init);
module_exit(ecoscsi_exit);
-EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines");
MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
static struct expansion_card *ecs[MAX_ECARDS];
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("EESOX SCSI driver");
-MODULE_PARM(term, "1-8i");
-MODULE_PARM_DESC(term, "SCSI bus termination");
-
/*
* Use term=0,1,0,0,0 to turn terminators on/off
*/
module_init(eesox_init);
module_exit(eesox_exit);
-EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("EESOX 'Fast' SCSI driver for Acorn machines");
+MODULE_PARM(term, "1-8i");
+MODULE_PARM_DESC(term, "SCSI bus termination");
MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
#include "../../scsi/hosts.h"
#include "fas216.h"
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver");
-
#define VER_MAJOR 0
#define VER_MINOR 0
#define VER_PATCH 5
EXPORT_SYMBOL(fas216_print_stats);
EXPORT_SYMBOL(fas216_print_device);
-#ifdef MODULE
-int __init init_module(void)
-{
- return 0;
-}
-
-void __exit cleanup_module(void)
-{
-}
-#endif
-
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core");
MODULE_LICENSE("GPL");
#include "msgqueue.h"
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("SCSI message queue handling");
-MODULE_LICENSE("GPL");
-
/*
* Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
* Purpose : Allocate a message queue entry
EXPORT_SYMBOL(msgqueue_addmsg);
EXPORT_SYMBOL(msgqueue_flush);
-#ifdef MODULE
-int __init init_module(void)
-{
- return 0;
-}
-
-void __exit cleanup_module(void)
-{
-}
-#endif
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SCSI message queue handling");
+MODULE_LICENSE("GPL");
module_init(oakscsi_init);
module_exit(oakscsi_exit);
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Oak SCSI driver");
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
#define VER_MINOR 0
#define VER_PATCH 5
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("Powertec SCSI driver");
-MODULE_PARM(term, "1-8i");
-MODULE_PARM_DESC(term, "SCSI bus termination");
-MODULE_LICENSE("GPL");
-
static struct expansion_card *ecs[MAX_ECARDS];
/*
module_init(powertecscsi_init);
module_exit(powertecscsi_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Powertec SCSI driver");
+MODULE_PARM(term, "1-8i");
+MODULE_PARM_DESC(term, "SCSI bus termination");
+MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
#include "../../scsi/scsi.h"
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("SCSI command queueing");
-MODULE_LICENSE("GPL");
-
#define DEBUG
typedef struct queue_entry {
EXPORT_SYMBOL(queue_remove_cmd);
EXPORT_SYMBOL(queue_probetgtlun);
-#ifdef MODULE
-int __init init_module (void)
-{
- return 0;
-}
-
-void __exit cleanup_module (void)
-{
-}
-#endif
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SCSI command queueing");
+MODULE_LICENSE("GPL");
tz_osl_add_device(
TZ_CONTEXT *thermal_zone)
{
- struct proc_dir_entry *proc_entry = NULL;
+ struct proc_dir_entry *proc_entry = NULL, *proc;
if (!thermal_zone) {
return(AE_BAD_PARAMETER);
printk("Thermal Zone: found\n");
proc_entry = proc_mkdir(thermal_zone->uid, tz_proc_root);
- if (!proc_entry) {
+ if (!proc_entry)
return(AE_ERROR);
- }
- create_proc_read_entry(TZ_PROC_STATUS, S_IFREG | S_IRUGO,
+ proc = create_proc_read_entry(TZ_PROC_STATUS, S_IFREG | S_IRUGO,
proc_entry, tz_osl_proc_read_status, (void*)thermal_zone);
+ if (!proc)
+ return(AE_ERROR);
- create_proc_read_entry(TZ_PROC_INFO, S_IFREG | S_IRUGO,
+ proc = create_proc_read_entry(TZ_PROC_INFO, S_IFREG | S_IRUGO,
proc_entry, tz_osl_proc_read_info, (void*)thermal_zone);
+ if (!proc)
+ return(AE_ERROR);
return(AE_OK);
}
module_exit(nbd_cleanup);
MODULE_DESCRIPTION("Network Block Device");
+MODULE_LICENSE("GPL");
+
#endif
/* end of aten.c */
+MODULE_LICENSE("GPL");
#endif
/* end of bpck.c */
+MODULE_LICENSE("GPL");
#endif
/* end of comm.c */
+MODULE_LICENSE("GPL");
#endif
/* end of dstr.c */
+MODULE_LICENSE("GPL");
#endif
/* end of epat.c */
+MODULE_LICENSE("GPL");
/* end of epia.c */
+MODULE_LICENSE("GPL");
#endif
/* end of fit2.c */
+MODULE_LICENSE("GPL");
#endif
/* end of fit3.c */
+MODULE_LICENSE("GPL");
#endif
/* end of friq.c */
+MODULE_LICENSE("GPL");
#endif
/* end of frpw.c */
+MODULE_LICENSE("GPL");
#endif
/* end of kbic.c */
+MODULE_LICENSE("GPL");
#endif
/* end of ktti.c */
+MODULE_LICENSE("GPL");
#endif
/* end of on20.c */
+MODULE_LICENSE("GPL");
/* end of on26.c */
+MODULE_LICENSE("GPL");
#endif
/* end of paride.c */
+MODULE_LICENSE("GPL");
/* end of pcd.c */
+MODULE_LICENSE("GPL");
}
void cleanup_module(void)
-
-{ struct gendisk **gdp;
+{
int unit;
devfs_unregister_blkdev(MAJOR_NR,name);
/* end of pd.c */
+MODULE_LICENSE("GPL");
/* end of pf.c */
+MODULE_LICENSE("GPL");
/* end of pg.c */
+MODULE_LICENSE("GPL");
//***************************************************************************
+MODULE_LICENSE("GPL");
/* end of pt.c */
+MODULE_LICENSE("GPL");
tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
tristate ' Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT
+ tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
tristate ' W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT
tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD
tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
tristate 'Siemens R3964 line discipline' CONFIG_R3964
tristate 'Applicom intelligent fieldbus card support' CONFIG_APPLICOM
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_X86" = "y" ]; then
dep_tristate 'Sony Vaio Programmable I/O Control Device support' CONFIG_SONYPI $CONFIG_PCI
fi
obj-$(CONFIG_PCWATCHDOG) += pcwd.o
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
+obj-$(CONFIG_IB700_WDT) += ib700wdt.o
obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
obj-$(CONFIG_WDT) += wdt.o
module_init(adb_mouse_init);
module_exit(adb_mouse_cleanup);
-MODULE_LICENSE("GPL"):
+MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jeff Garzik, Philipp Rumpf, Matt Sottek");
MODULE_DESCRIPTION("Intel i8xx chipset Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL");
/*
--- /dev/null
+/*
+ * IB700 Single Board Computer WDT driver for Linux 2.4.x
+ *
+ * (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ * Based on advantechwdt.c which is based on acquirewdt.c which
+ * is based on wdt.c.
+ *
+ * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ * Based on acquirewdt.c which is based on wdt.c.
+ * Original copyright messages:
+ *
+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ * http://www.redhat.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
+ *
+ * (c) Copyright 1995 Alan Cox <alan@redhat.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+
+static int ibwdt_is_open;
+static spinlock_t ibwdt_lock;
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system
+ * automatically and is defined at I/O port 0443H. To enable the
+ * watchdog timer and allow the system to reset, write I/O port 0443H.
+ * To disable the timer, write I/O port 0441H for the system to stop the
+ * watchdog function. The timer has a tolerance of 20% for its
+ * intervals.
+ *
+ * The following describes how the timer should be programmed.
+ *
+ * Enabling Watchdog:
+ * MOV AX,000FH (Choose the values from 0 to F)
+ * MOV DX,0443H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,000FH (Any value is fine.)
+ * MOV DX,0441H
+ * OUT DX,AX
+ *
+ * Watchdog timer control table:
+ * Level Value Time/sec | Level Value Time/sec
+ * 1 F 0 | 9 7 16
+ * 2 E 2 | 10 6 18
+ * 3 D 4 | 11 5 20
+ * 4 C 6 | 12 4 22
+ * 5 B 8 | 13 3 24
+ * 6 A 10 | 14 2 26
+ * 7 9 12 | 15 1 28
+ * 8 8 14 | 16 0 30
+ *
+ */
+
+#define WDT_STOP 0x441
+#define WDT_START 0x443
+
+#define WD_TIMO 0 /* 30 seconds +/- 20%, from table */
+
+/*
+ * Kernel methods.
+ */
+
+static void
+ibwdt_ping(void)
+{
+ /* Write a watchdog value */
+ outb_p(WD_TIMO, WDT_START);
+}
+
+static ssize_t
+ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+ if (count) {
+ ibwdt_ping();
+ return 1;
+ }
+ return 0;
+}
+
+static ssize_t
+ibwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+static int
+ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ static struct watchdog_info ident = {
+ WDIOF_KEEPALIVEPING, 1, "IB700 WDT"
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ if (copy_to_user((int *)arg, &ibwdt_is_open, sizeof(int)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_KEEPALIVE:
+ ibwdt_ping();
+ break;
+
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int
+ibwdt_open(struct inode *inode, struct file *file)
+{
+ switch (MINOR(inode->i_rdev)) {
+ case WATCHDOG_MINOR:
+ spin_lock(&ibwdt_lock);
+ if (ibwdt_is_open) {
+ spin_unlock(&ibwdt_lock);
+ return -EBUSY;
+ }
+ /*
+ * Activate
+ */
+
+ ibwdt_is_open = 1;
+ ibwdt_ping();
+ spin_unlock(&ibwdt_lock);
+ return 0;
+ default:
+ return -ENODEV;
+ }
+}
+
+static int
+ibwdt_close(struct inode *inode, struct file *file)
+{
+ lock_kernel();
+ if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+ spin_lock(&ibwdt_lock);
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
+ outb_p(WD_TIMO, WDT_STOP);
+#endif
+ ibwdt_is_open = 0;
+ spin_unlock(&ibwdt_lock);
+ }
+ unlock_kernel();
+ return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int
+ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT) {
+ /* Turn the WDT off */
+ outb_p(WD_TIMO, WDT_STOP);
+ }
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations ibwdt_fops = {
+ owner: THIS_MODULE,
+ read: ibwdt_read,
+ write: ibwdt_write,
+ ioctl: ibwdt_ioctl,
+ open: ibwdt_open,
+ release: ibwdt_close,
+};
+
+static struct miscdevice ibwdt_miscdev = {
+ WATCHDOG_MINOR,
+ "watchdog",
+ &ibwdt_fops
+};
+
+/*
+ * The WDT needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block ibwdt_notifier = {
+ ibwdt_notify_sys,
+ NULL,
+ 0
+};
+
+static int __init
+ibwdt_init(void)
+{
+ printk("WDT driver for IB700 single board computer initialising.\n");
+
+ spin_lock_init(&ibwdt_lock);
+ misc_register(&ibwdt_miscdev);
+#if WDT_START != WDT_STOP
+ request_region(WDT_STOP, 1, "IB700 WDT");
+#endif
+ request_region(WDT_START, 1, "IB700 WDT");
+ register_reboot_notifier(&ibwdt_notifier);
+ return 0;
+}
+
+static void __exit
+ibwdt_exit(void)
+{
+ misc_deregister(&ibwdt_miscdev);
+ unregister_reboot_notifier(&ibwdt_notifier);
+#if WDT_START != WDT_STOP
+ release_region(WDT_STOP,1);
+#endif
+ release_region(WDT_START,1);
+}
+
+module_init(ibwdt_init);
+module_exit(ibwdt_exit);
+
+MODULE_AUTHOR("Charles Howes <chowes@vsol.net>");
+MODULE_DESCRIPTION("IB700 SBC watchdog driver");
+MODULE_LICENSE("GPL");
+
+/* end of ib700wdt.c */
}
+MODULE_LICENSE("GPL");
*/
MODULE_AUTHOR("Greg Ungerer");
MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
+MODULE_LICENSE("GPL");
+
MODULE_PARM(board0, "1-3s");
MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
#define __exit
#endif
+MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
+MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
+MODULE_LICENSE("GPL");
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
static int mwave_get_info(char *buf, char **start, off_t offset, int len);
#else
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>
+#include <asm/system.h>
#include "sonypi.h"
#include <linux/sonypi.h>
static int verbose; /* = 0 */
static int fnkeyinit; /* = 0 */
static int camera; /* = 0 */
-extern int is_sony_vaio_laptop; /* set in DMI table parse routines */
+static int compat; /* = 0 */
/* Inits the queue */
static inline void sonypi_initq(void) {
static void sonypi_ecrset(u16 addr, u16 value) {
- wait_on_command(inw_p(SONYPI_CST_IOPORT) & 3);
+ wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
outw_p(0x81, SONYPI_CST_IOPORT);
- wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2);
+ wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
outw_p(addr, SONYPI_DATA_IOPORT);
- wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2);
+ wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
outw_p(value, SONYPI_DATA_IOPORT);
- wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2);
+ wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
}
static u16 sonypi_ecrget(u16 addr) {
- wait_on_command(inw_p(SONYPI_CST_IOPORT) & 3);
+ wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
outw_p(0x80, SONYPI_CST_IOPORT);
- wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2);
+ wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
outw_p(addr, SONYPI_DATA_IOPORT);
- wait_on_command(inw_p(SONYPI_CST_IOPORT) & 2);
+ wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
return inw_p(SONYPI_DATA_IOPORT);
}
/* Initializes the device - this comes from the AML code in the ACPI bios */
-static void __devinit sonypi_normal_srs(void) {
+static void __devinit sonypi_type1_srs(void) {
u32 v;
pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
}
-static void __devinit sonypi_r505_srs(void) {
+static void __devinit sonypi_type2_srs(void) {
sonypi_ecrset(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8);
sonypi_ecrset(SONYPI_SLOB, sonypi_device.ioport1 & 0x00FF);
sonypi_ecrset(SONYPI_SIRQ, sonypi_device.bits);
}
/* Disables the device - this comes from the AML code in the ACPI bios */
-static void __devexit sonypi_normal_dis(void) {
+static void __devexit sonypi_type1_dis(void) {
u32 v;
pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
outl(v, SONYPI_IRQ_PORT);
}
-static void __devexit sonypi_r505_dis(void) {
+static void __devexit sonypi_type2_dis(void) {
sonypi_ecrset(SONYPI_SHIB, 0);
sonypi_ecrset(SONYPI_SLOB, 0);
sonypi_ecrset(SONYPI_SIRQ, 0);
static u8 sonypi_call1(u8 dev) {
u8 v1, v2;
- wait_on_command(inb_p(sonypi_device.ioport2) & 2);
+ wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
outb(dev, sonypi_device.ioport2);
v1 = inb_p(sonypi_device.ioport2);
v2 = inb_p(sonypi_device.ioport1);
static u8 sonypi_call2(u8 dev, u8 fn) {
u8 v1;
- wait_on_command(inb_p(sonypi_device.ioport2) & 2);
+ wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
outb(dev, sonypi_device.ioport2);
- wait_on_command(inb_p(sonypi_device.ioport2) & 2);
+ wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
outb(fn, sonypi_device.ioport1);
v1 = inb_p(sonypi_device.ioport1);
return v1;
static u8 sonypi_call3(u8 dev, u8 fn, u8 v) {
u8 v1;
- wait_on_command(inb_p(sonypi_device.ioport2) & 2);
+ wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
outb(dev, sonypi_device.ioport2);
- wait_on_command(inb_p(sonypi_device.ioport2) & 2);
+ wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
outb(fn, sonypi_device.ioport1);
- wait_on_command(inb_p(sonypi_device.ioport2) & 2);
+ wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
outb(v, sonypi_device.ioport1);
v1 = inb_p(sonypi_device.ioport1);
return v1;
/* Set brightness, hue etc */
static void sonypi_set(u8 fn, u8 v) {
- wait_on_command(sonypi_call3(0x90, fn, v));
+ wait_on_command(0, sonypi_call3(0x90, fn, v));
}
/* Tests if the camera is ready */
int i;
u8 sonypi_jogger_ev, sonypi_fnkey_ev;
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_R505) {
- sonypi_jogger_ev = SONYPI_R505_JOGGER_EV;
- sonypi_fnkey_ev = SONYPI_R505_FNKEY_EV;
+ if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
+ sonypi_jogger_ev = SONYPI_TYPE2_JOGGER_EV;
+ sonypi_fnkey_ev = SONYPI_TYPE2_FNKEY_EV;
}
else {
- sonypi_jogger_ev = SONYPI_NORMAL_JOGGER_EV;
- sonypi_fnkey_ev = SONYPI_NORMAL_FNKEY_EV;
+ sonypi_jogger_ev = SONYPI_TYPE1_JOGGER_EV;
+ sonypi_fnkey_ev = SONYPI_TYPE1_FNKEY_EV;
}
v1 = inb_p(sonypi_device.ioport1);
v2 = inb_p(sonypi_device.ioport2);
- if ((v2 & SONYPI_NORMAL_PKEY_EV) == SONYPI_NORMAL_PKEY_EV) {
+ if ((v2 & SONYPI_TYPE1_PKEY_EV) == SONYPI_TYPE1_PKEY_EV) {
for (i = 0; sonypi_pkeyev[i].event; i++)
if (sonypi_pkeyev[i].data == v1) {
event = sonypi_pkeyev[i].event;
goto found;
}
}
+ if ((v2 & SONYPI_BACK_EV) == SONYPI_BACK_EV) {
+ for (i = 0; sonypi_backev[i].event; i++)
+ if (sonypi_backev[i].data == v1) {
+ event = sonypi_backev[i].event;
+ goto found;
+ }
+ }
+ if ((v2 & SONYPI_LID_EV) == SONYPI_LID_EV) {
+ for (i = 0; sonypi_lidev[i].event; i++)
+ if (sonypi_lidev[i].data == v1) {
+ event = sonypi_lidev[i].event;
+ goto found;
+ }
+ }
if (verbose)
printk(KERN_WARNING
- "sonypi: unknown event port1=0x%x,port2=0x%x\n",v1,v2);
+ "sonypi: unknown event port1=0x%02x,port2=0x%02x\n",v1,v2);
return;
found:
goto out1;
}
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_R505) {
- ioport_list = sonypi_r505_ioport_list;
- sonypi_device.region_size = SONYPI_R505_REGION_SIZE;
- irq_list = sonypi_r505_irq_list;
+ if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
+ ioport_list = sonypi_type2_ioport_list;
+ sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE;
+ irq_list = sonypi_type2_irq_list;
}
else {
- ioport_list = sonypi_normal_ioport_list;
- sonypi_device.region_size = SONYPI_NORMAL_REGION_SIZE;
- irq_list = sonypi_normal_irq_list;
+ ioport_list = sonypi_type1_ioport_list;
+ sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
+ irq_list = sonypi_type1_irq_list;
}
for (i = 0; ioport_list[i].port1; i++) {
if (fnkeyinit)
outb(0xf0, 0xb2);
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_R505)
- sonypi_r505_srs();
+ if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
+ sonypi_type2_srs();
else
- sonypi_normal_srs();
+ sonypi_type1_srs();
sonypi_call1(0x82);
sonypi_call2(0x81, 0xff);
- sonypi_call1(0x92);
+ if (compat)
+ sonypi_call1(0x92);
+ else
+ sonypi_call1(0x82);
printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver v%d.%d.\n",
SONYPI_DRIVER_MAJORVERSION,
SONYPI_DRIVER_MINORVERSION);
- printk(KERN_INFO "sonypi: detected %s model, camera = %s\n",
- (sonypi_device.model == SONYPI_DEVICE_MODEL_NORMAL) ?
- "normal" : "R505",
- camera ? "on" : "off");
+ printk(KERN_INFO "sonypi: detected %s model (%04x:%04x), "
+ "camera = %s, compat = %s\n",
+ (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ?
+ "type1" : "type2",
+ sonypi_device.dev->vendor, sonypi_device.dev->device,
+ camera ? "on" : "off",
+ compat ? "on" : "off");
printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
sonypi_device.irq,
sonypi_device.ioport1, sonypi_device.ioport2);
sonypi_call2(0x81, 0); /* make sure we don't get any more events */
if (camera)
sonypi_camera_off();
- if (sonypi_device.model == SONYPI_DEVICE_MODEL_R505)
- sonypi_r505_dis();
+ if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
+ sonypi_type2_dis();
else
- sonypi_normal_dis();
+ sonypi_type1_dis();
free_irq(sonypi_device.irq, sonypi_irq);
release_region(sonypi_device.ioport1, sonypi_device.region_size);
misc_deregister(&sonypi_misc_device);
static struct pci_device_id sonypi_id_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- (unsigned long) SONYPI_DEVICE_MODEL_NORMAL },
+ (unsigned long) SONYPI_DEVICE_MODEL_TYPE1 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- (unsigned long) SONYPI_DEVICE_MODEL_R505 },
+ (unsigned long) SONYPI_DEVICE_MODEL_TYPE2 },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ (unsigned long) SONYPI_DEVICE_MODEL_TYPE2 },
{ }
};
pci_unregister_driver(&sonypi_driver);
}
+#ifndef MODULE
+static int __init sonypi_setup(char *str) {
+ int ints[6];
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+ if (ints[0] <= 0)
+ goto out;
+ minor = ints[1];
+ if (ints[0] == 1)
+ goto out;
+ verbose = ints[2];
+ if (ints[0] == 2)
+ goto out;
+ fnkeyinit = ints[3];
+ if (ints[0] == 3)
+ goto out;
+ camera = ints[4];
+ if (ints[0] == 4)
+ goto out;
+ compat = ints[5];
+out:
+ return 1;
+}
+
+__setup("sonypi=", sonypi_setup);
+#endif /* !MODULE */
+
/* Module entry points */
module_init(sonypi_init_module);
module_exit(sonypi_cleanup_module);
MODULE_PARM_DESC(fnkeyinit, "set this if your Fn keys do not generate any event");
MODULE_PARM(camera,"i");
MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)");
+MODULE_PARM(compat,"i");
+MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode");
EXPORT_SYMBOL(sonypi_camera_command);
#ifdef __KERNEL__
#define SONYPI_DRIVER_MAJORVERSION 1
-#define SONYPI_DRIVER_MINORVERSION 5
+#define SONYPI_DRIVER_MINORVERSION 6
#include <linux/types.h>
#include <linux/pci.h>
#include "linux/sonypi.h"
-/* Normal models use those */
+/* type1 models use those */
#define SONYPI_IRQ_PORT 0x8034
#define SONYPI_IRQ_SHIFT 22
#define SONYPI_BASE 0x50
#define SONYPI_G10A (SONYPI_BASE+0x14)
-#define SONYPI_NORMAL_REGION_SIZE 0x08
+#define SONYPI_TYPE1_REGION_SIZE 0x08
-/* R505 series specifics */
-#define SONYPI_SIRQ 0x9b
-#define SONYPI_SLOB 0x9c
-#define SONYPI_SHIB 0x9d
-#define SONYPI_R505_REGION_SIZE 0x20
+/* type2 series specifics */
+#define SONYPI_SIRQ 0x9b
+#define SONYPI_SLOB 0x9c
+#define SONYPI_SHIB 0x9d
+#define SONYPI_TYPE2_REGION_SIZE 0x20
-/* ioports used for brightness and R505 events */
+/* ioports used for brightness and type2 events */
#define SONYPI_DATA_IOPORT 0x62
#define SONYPI_CST_IOPORT 0x66
u16 port2;
};
-static struct sonypi_ioport_list sonypi_normal_ioport_list[] = {
+static struct sonypi_ioport_list sonypi_type1_ioport_list[] = {
{ 0x10c0, 0x10c4 }, /* looks like the default on C1Vx */
{ 0x1080, 0x1084 },
{ 0x1090, 0x1094 },
{ 0x0, 0x0 }
};
-static struct sonypi_ioport_list sonypi_r505_ioport_list[] = {
+static struct sonypi_ioport_list sonypi_type2_ioport_list[] = {
{ 0x1080, 0x1084 },
{ 0x10a0, 0x10a4 },
{ 0x10c0, 0x10c4 },
u16 bits;
};
-static struct sonypi_irq_list sonypi_normal_irq_list[] = {
+static struct sonypi_irq_list sonypi_type1_irq_list[] = {
{ 11, 0x2 }, /* IRQ 11, GO22=0,GO23=1 in AML */
{ 10, 0x1 }, /* IRQ 10, GO22=1,GO23=0 in AML */
{ 5, 0x0 }, /* IRQ 5, GO22=0,GO23=0 in AML */
{ 0, 0x3 } /* no IRQ, GO22=1,GO23=1 in AML */
};
-static struct sonypi_irq_list sonypi_r505_irq_list[] = {
+static struct sonypi_irq_list sonypi_type2_irq_list[] = {
{ 11, 0x80 }, /* IRQ 11, 0x80 in SIRQ in AML */
{ 10, 0x40 }, /* IRQ 10, 0x40 in SIRQ in AML */
{ 9, 0x20 }, /* IRQ 9, 0x20 in SIRQ in AML */
#define SONYPI_CAMERA_ROMVERSION 9
/* key press event data (ioport2) */
-#define SONYPI_NORMAL_JOGGER_EV 0x10
-#define SONYPI_R505_JOGGER_EV 0x08
+#define SONYPI_TYPE1_JOGGER_EV 0x10
+#define SONYPI_TYPE2_JOGGER_EV 0x08
#define SONYPI_CAPTURE_EV 0x60
-#define SONYPI_NORMAL_FNKEY_EV 0x20
-#define SONYPI_R505_FNKEY_EV 0x08
+#define SONYPI_TYPE1_FNKEY_EV 0x20
+#define SONYPI_TYPE2_FNKEY_EV 0x08
#define SONYPI_BLUETOOTH_EV 0x30
-#define SONYPI_NORMAL_PKEY_EV 0x40
+#define SONYPI_TYPE1_PKEY_EV 0x40
+#define SONYPI_BACK_EV 0x08
+#define SONYPI_LID_EV 0x38
struct sonypi_event {
u8 data;
{ 0x00, 0x00 }
};
+/* The set of possible back button events */
+static struct sonypi_event sonypi_backev[] = {
+ { 0x20, SONYPI_EVENT_BACK_PRESSED },
+ { 0x00, 0x00 }
+};
+
+/* The set of possible lid events */
+static struct sonypi_event sonypi_lidev[] = {
+ { 0x51, SONYPI_EVENT_LID_CLOSED },
+ { 0x50, SONYPI_EVENT_LID_OPENED },
+ { 0x00, 0x00 }
+};
+
#define SONYPI_BUF_SIZE 128
struct sonypi_queue {
unsigned long head;
unsigned char buf[SONYPI_BUF_SIZE];
};
-#define SONYPI_DEVICE_MODEL_NORMAL 1
-#define SONYPI_DEVICE_MODEL_R505 2
+#define SONYPI_DEVICE_MODEL_TYPE1 1
+#define SONYPI_DEVICE_MODEL_TYPE2 2
struct sonypi_device {
struct pci_dev *dev;
int model;
};
-#define wait_on_command(command) { \
+#define wait_on_command(quiet, command) { \
unsigned int n = 10000; \
while (--n && (command)) \
udelay(1); \
- if (!n) \
+ if (!n && (verbose || !quiet)) \
printk(KERN_WARNING "sonypi command failed at " __FILE__ " : " __FUNCTION__ "(line %d)\n", __LINE__); \
}
* 0xfc15: Tom May <tom@you-bastards.com>
* 0xfc17: Dave Konrad <konrad@xenia.it>
* 0xfc1a: George Betzos <betzos@engr.colostate.edu>
+ * 0xfc1b: Munemasa Wada <munemasa@jnovel.co.jp>
* 0xfc1d: Arthur Liu <armie@slap.mine.nu>
+ * 0xfc5a: Jacques L'helgoualc'h <lhh@free.fr>
* 0xfcd1: Mr. Dave Konrad <konrad@xenia.it>
*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*
*/
-#define TOSH_VERSION "1.9 22/3/2001"
+#define TOSH_VERSION "1.11 26/9/2001"
#define TOSH_DEBUG 0
#include <linux/module.h>
if (!arg)
return -EINVAL;
- if(copy_from_user(®s, (SMMRegisters *) arg, sizeof(SMMRegisters)))
+ if (copy_from_user(®s, (SMMRegisters *) arg, sizeof(SMMRegisters)))
return -EFAULT;
switch (cmd) {
return -EINVAL;
}
- if(copy_to_user((SMMRegisters *) arg, ®s, sizeof(SMMRegisters)))
+ if (copy_to_user((SMMRegisters *) arg, ®s, sizeof(SMMRegisters)))
return -EFAULT;
return (err==0) ? 0:-EINVAL;
{
switch (tosh_id) {
case 0xfc02: case 0xfc04: case 0xfc09: case 0xfc0a: case 0xfc10:
- case 0xfc11: case 0xfc13: case 0xfc15: case 0xfc1a:
+ case 0xfc11: case 0xfc13: case 0xfc15: case 0xfc1a: case 0xfc1b:
+ case 0xfc5a:
tosh_fn = 0x62;
break;
case 0xfc08: case 0xfc17: case 0xfc1d: case 0xfcd1: case 0xfce0:
*/
int tosh_probe(void)
{
- int major,minor,day,year,month,flag;
+ int i,major,minor,day,year,month,flag;
+ unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 };
SMMRegisters regs;
+ /* extra sanity check for the string "TOSHIBA" in the BIOS because
+ some machines that are not Toshiba's pass the next test */
+
+ for (i=0;i<7;i++) {
+ if (isa_readb(0xfe010+i)!=signature[i]) {
+ printk("toshiba: not a supported Toshiba laptop\n");
+ return -ENODEV;
+ }
+ }
+
/* call the Toshiba SCI support check routine */
regs.eax = 0xf0f0;
module_init(soc_probe);
module_exit(soc_cleanup);
+MODULE_LICENSE("GPL");
module_init(socal_probe);
module_exit(socal_cleanup);
+MODULE_LICENSE("GPL");
dep_tristate ' ITE I2C Adapter' CONFIG_ITE_I2C_ADAP $CONFIG_ITE_I2C_ALGO
fi
fi
+ if [ "$CONFIG_8xx" = "y" ]; then
+ dep_tristate 'MPC8xx CPM I2C interface' CONFIG_I2C_ALGO8XX $CONFIG_I2C
+ if [ "$CONFIG_RPXLITE" = "y" -o "$CONFIG_RPXCLASSIC" = "y" ]; then
+ dep_tristate ' Embedded Planet RPX Lite/Classic suppoort' CONFIG_I2C_RPXLITE $CONFIG_I2C_ALGO8XX
+ fi
+ fi
+ if [ "$CONFIG_405" = "y" ]; then
+ dep_tristate 'PPC 405 I2C Algorithm' CONFIG_I2C_PPC405_ALGO $CONFIG_I2C
+ if [ "$CONFIG_I2C_PPC405_ALGO" != "n" ]; then
+ dep_tristate ' PPC 405 I2C Adapter' CONFIG_I2C_PPC405_ADAP $CONFIG_I2C_PPC405_ALGO
+ fi
+ fi
# This is needed for automatic patch generation: sensors code starts here
# This is needed for automatic patch generation: sensors code ends here
dep_tristate 'I2C device interface' CONFIG_I2C_CHARDEV $CONFIG_I2C
+ dep_tristate 'I2C /proc interface (required for hardware sensors)' CONFIG_I2C_PROC $CONFIG_I2C
fi
endmenu
O_TARGET := i2c.o
-export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o
+export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \
+ i2c-algo-ite.o i2c-proc.o
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
+obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o
+obj-$(CONFIG_ITE_I2C_ADAP) += i2c-adap-ite.o
+obj-$(CONFIG_I2C_PROC) += i2c-proc.o
# This is needed for automatic patch generation: sensors code starts here
# This is needed for automatic patch generation: sensors code ends here
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/version.h>
#include <linux/init.h>
#include <asm/irq.h>
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-algo-bit.c,v 1.27 2000/07/09 15:16:16 frodo Exp $ */
+/* $Id: i2c-algo-bit.c,v 1.30 2001/07/29 02:44:25 mds Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/version.h>
#include <linux/init.h>
#include <asm/uaccess.h>
-
/* ------------------------------------------------------------------------- */
/* i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters */
/* ------------------------------------------------------------------------- */
Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
<mbailey@littlefeet-inc.com> */
-/* $Id: i2c-algo-pcf.c,v 1.25 2000/11/10 13:43:32 frodo Exp $ */
+/* Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple
+ messages, proper stop/repstart signaling during receive,
+ added detect code */
#include <linux/kernel.h>
#include <linux/module.h>
/* debug the protocol by showing transferred bits */
#define DEF_TIMEOUT 16
-/* debugging - slow down transfer to have a look at the data .. */
-/* I use this with two leds&resistors, each one connected to sda,scl */
-/* respectively. This makes sure that the algorithm works. Some chips */
-/* might not like this, as they have an internal timeout of some mils */
-/*
-#define SLO_IO jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
- if (need_resched) schedule();
-*/
-
-
-/* ----- global variables --------------------------------------------- */
-
-#ifdef SLO_IO
- int jif;
-#endif
-
/* module parameters:
*/
-static int i2c_debug=1;
-static int pcf_test=0; /* see if the line-setting functions work */
+static int i2c_debug=0;
static int pcf_scan=0; /* have a look at what's hanging 'round */
/* --- setting states on the bus with the right timing: --------------- */
#define i2c_outb(adap, val) adap->setpcf(adap->data, 0, val)
#define i2c_inb(adap) adap->getpcf(adap->data, 0)
-
/* --- other auxiliary functions -------------------------------------- */
static void i2c_start(struct i2c_algo_pcf_data *adap)
status = get_pcf(adap, 1);
#ifndef STUB_I2C
while (timeout-- && !(status & I2C_PCF_BB)) {
- udelay(1000); /* How much is this? */
+ udelay(100); /* wait for 100 us */
status = get_pcf(adap, 1);
}
#endif
- if (timeout<=0)
+ if (timeout <= 0) {
printk("Timeout waiting for Bus Busy\n");
- /*
- set_pcf(adap, 1, I2C_PCF_STOP);
- */
- return(timeout<=0);
+ }
+
+ return (timeout<=0);
}
return(0);
}
-
/*
* This should perform the 'PCF8584 initialization sequence' as described
* in the Philips IC12 data book (1995, Aug 29).
* There should be a delay at the end equal to the longest I2C message
* to synchronize the BB-bit (in multimaster systems). How long is
* this? I assume 1 second is always long enough.
+ *
+ * vdovikin: added detect code for PCF8584
*/
static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
{
+ unsigned char temp;
+
+ DEB3(printk("i2c-algo-pcf.o: PCF state 0x%02x\n", get_pcf(adap, 1)));
- /* S1=0x80: S0 selected, serial interface off */
+ /* S1=0x80: S0 selected, serial interface off */
set_pcf(adap, 1, I2C_PCF_PIN);
+ /* check to see S1 now used as R/W ctrl -
+ PCF8584 does that when ESO is zero */
+ /* PCF also resets PIN bit */
+ if ((temp = get_pcf(adap, 1)) != (0)) {
+ DEB2(printk("i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp));
+ return -ENXIO; /* definetly not PCF8584 */
+ }
/* load own address in S0, effective address is (own << 1) */
i2c_outb(adap, get_own(adap));
+ /* check it's realy writen */
+ if ((temp = i2c_inb(adap)) != get_own(adap)) {
+ DEB2(printk("i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp));
+ return -ENXIO;
+ }
/* S1=0xA0, next byte in S2 */
set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1);
+ /* check to see S2 now selected */
+ if ((temp = get_pcf(adap, 1)) != I2C_PCF_ES1) {
+ DEB2(printk("i2c-algo-pcf.o: PCF detection failed -- can't select S2 (0x%02x).\n", temp));
+ return -ENXIO;
+ }
/* load clock register S2 */
i2c_outb(adap, get_clock(adap));
+ /* check it's realy writen, the only 5 lowest bits does matter */
+ if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) {
+ DEB2(printk("i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp));
+ return -ENXIO;
+ }
/* Enable serial interface, idle, S0 selected */
set_pcf(adap, 1, I2C_PCF_IDLE);
- DEB2(printk("i2c-algo-pcf.o: irq: Initialized 8584.\n"));
- return 0;
-}
-
-
-/*
- * Sanity check for the adapter hardware - check the reaction of
- * the bus lines only if it seems to be idle.
- */
-static int test_bus(struct i2c_algo_pcf_data *adap, char *name) {
-#if 0
- int scl,sda;
- sda=getsda(adap);
- if (adap->getscl==NULL) {
- printk("i2c-algo-pcf.o: Warning: Adapter can't read from clock line - skipping test.\n");
- return 0;
- }
- scl=getscl(adap);
- printk("i2c-algo-pcf.o: Adapter: %s scl: %d sda: %d -- testing...\n",
- name,getscl(adap),getsda(adap));
- if (!scl || !sda ) {
- printk("i2c-algo-pcf.o: %s seems to be busy.\n",adap->name);
- goto bailout;
+ /* check to see PCF is realy idled and we can access status register */
+ if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) {
+ DEB2(printk("i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp));
+ return -ENXIO;
}
- sdalo(adap);
- printk("i2c-algo-pcf.o:1 scl: %d sda: %d \n",getscl(adap),
- getsda(adap));
- if ( 0 != getsda(adap) ) {
- printk("i2c-algo-pcf.o: %s SDA stuck high!\n",name);
- sdahi(adap);
- goto bailout;
- }
- if ( 0 == getscl(adap) ) {
- printk("i2c-algo-pcf.o: %s SCL unexpected low while pulling SDA low!\n",
- name);
- goto bailout;
- }
- sdahi(adap);
- printk("i2c-algo-pcf.o:2 scl: %d sda: %d \n",getscl(adap),
- getsda(adap));
- if ( 0 == getsda(adap) ) {
- printk("i2c-algo-pcf.o: %s SDA stuck low!\n",name);
- sdahi(adap);
- goto bailout;
- }
- if ( 0 == getscl(adap) ) {
- printk("i2c-algo-pcf.o: %s SCL unexpected low while SDA high!\n",
- adap->name);
- goto bailout;
- }
- scllo(adap);
- printk("i2c-algo-pcf.o:3 scl: %d sda: %d \n",getscl(adap),
- getsda(adap));
- if ( 0 != getscl(adap) ) {
- printk("i2c-algo-pcf.o: %s SCL stuck high!\n",name);
- sclhi(adap);
- goto bailout;
- }
- if ( 0 == getsda(adap) ) {
- printk("i2c-algo-pcf.o: %s SDA unexpected low while pulling SCL low!\n",
- name);
- goto bailout;
- }
- sclhi(adap);
- printk("i2c-algo-pcf.o:4 scl: %d sda: %d \n",getscl(adap),
- getsda(adap));
- if ( 0 == getscl(adap) ) {
- printk("i2c-algo-pcf.o: %s SCL stuck low!\n",name);
- sclhi(adap);
- goto bailout;
- }
- if ( 0 == getsda(adap) ) {
- printk("i2c-algo-pcf.o: %s SDA unexpected low while SCL high!\n",
- name);
- goto bailout;
- }
- printk("i2c-algo-pcf.o: %s passed test.\n",name);
+
+ printk("i2c-algo-pcf.o: deteted and initialized PCF8584.\n");
+
return 0;
-bailout:
- sdahi(adap);
- sclhi(adap);
- return -ENODEV;
-#endif
- return (0);
}
+
/* ----- Utility functions
*/
}
-static int pcf_sendbytes(struct i2c_adapter *i2c_adap,const char *buf,
- int count)
+static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
+ int count, int last)
{
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
int wrcount, status, timeout;
}
#endif
}
- i2c_stop(adap);
+ if (last) {
+ i2c_stop(adap);
+ }
+ else {
+ i2c_repstart(adap);
+ }
+
return (wrcount);
}
-static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
+static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
+ int count, int last)
{
- int rdcount=0, i, status, timeout, dummy=1;
+ int i, status;
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
-
- for (i=0; i<count; ++i) {
- buf[rdcount] = i2c_inb(adap);
- if (dummy) {
- dummy = 0;
- } else {
- rdcount++;
- }
- timeout = wait_for_pin(adap, &status);
- if (timeout) {
+
+ /* increment number of bytes to read by one -- read dummy byte */
+ for (i = 0; i <= count; i++) {
+
+ if (wait_for_pin(adap, &status)) {
i2c_stop(adap);
- printk("i2c-algo-pcf.o: i2c_read: "
- "i2c_inb timed out.\n");
+ printk("i2c-algo-pcf.o: pcf_readbytes timed out.\n");
return (-1);
}
+
#ifndef STUB_I2C
- if (status & I2C_PCF_LRB) {
+ if ((status & I2C_PCF_LRB) && (i != count)) {
i2c_stop(adap);
printk("i2c-algo-pcf.o: i2c_read: i2c_inb, No ack.\n");
return (-1);
}
#endif
- }
- set_pcf(adap, 1, I2C_PCF_ESO);
- buf[rdcount] = i2c_inb(adap);
- if (dummy) {
- dummy = 0;
- } else {
- rdcount++;
- }
- timeout = wait_for_pin(adap, &status);
- if (timeout) {
- i2c_stop(adap);
- printk("i2c-algo-pcf.o: i2c_read: i2c_inb timed out.\n");
- return (-1);
- }
-
- i2c_stop(adap);
+
+ if (i == count - 1) {
+ set_pcf(adap, 1, I2C_PCF_ESO);
+ } else
+ if (i == count) {
+ if (last) {
+ i2c_stop(adap);
+ } else {
+ i2c_repstart(adap);
+ }
+ };
- /* Read final byte from S0 register */
- buf[rdcount++] = i2c_inb(adap);
+ if (i) {
+ buf[i - 1] = i2c_inb(adap);
+ } else {
+ i2c_inb(adap); /* dummy read */
+ }
+ }
- return (rdcount);
+ return (i - 1);
}
{
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
struct i2c_msg *pmsg;
- int i = 0;
- int ret, timeout, status;
-
- pmsg = &msgs[i];
-
- /* Send address here if Read */
- if (pmsg->flags & I2C_M_RD) {
- ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
- }
+ int i;
+ int ret=0, timeout, status;
+
/* Check for bus busy */
timeout = wait_for_bb(adap);
if (timeout) {
"Timeout waiting for BB in pcf_xfer\n");)
return -EIO;
}
+
+ for (i = 0;ret >= 0 && i < num; i++) {
+ pmsg = &msgs[i];
+
+ DEB2(printk("i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n",
+ pmsg->flags & I2C_M_RD ? "read" : "write",
+ pmsg->len, pmsg->addr, i + 1, num);)
- /* Send address here if Write */
- if (!(pmsg->flags & I2C_M_RD)) {
ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
- }
- /* Send START */
- i2c_start(adap);
+
+ /* Send START */
+ if (i == 0) {
+ i2c_start(adap);
+ }
- /* Wait for PIN (pending interrupt NOT) */
- timeout = wait_for_pin(adap, &status);
- if (timeout) {
- i2c_stop(adap);
- DEB2(printk("i2c-algo-pcf.o: Timeout waiting "
- "for PIN(1) in pcf_xfer\n");)
- return (-EREMOTEIO);
- }
+ /* Wait for PIN (pending interrupt NOT) */
+ timeout = wait_for_pin(adap, &status);
+ if (timeout) {
+ i2c_stop(adap);
+ DEB2(printk("i2c-algo-pcf.o: Timeout waiting "
+ "for PIN(1) in pcf_xfer\n");)
+ return (-EREMOTEIO);
+ }
#ifndef STUB_I2C
- /* Check LRB (last rcvd bit - slave ack) */
- if (status & I2C_PCF_LRB) {
- i2c_stop(adap);
- DEB2(printk("i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
- return (-EREMOTEIO);
- }
+ /* Check LRB (last rcvd bit - slave ack) */
+ if (status & I2C_PCF_LRB) {
+ i2c_stop(adap);
+ DEB2(printk("i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
+ return (-EREMOTEIO);
+ }
#endif
- DEB3(printk("i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
- i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
+ DEB3(printk("i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
+ i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
- /* Read */
- if (pmsg->flags & I2C_M_RD) {
-
- /* read bytes into buffer*/
- ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len);
-
- if (ret != pmsg->len) {
- DEB2(printk("i2c-algo-pcf.o: fail: "
- "only read %d bytes.\n",ret));
- } else {
- DEB2(printk("i2c-algo-pcf.o: read %d bytes.\n",ret));
- }
- } else { /* Write */
+ /* Read */
+ if (pmsg->flags & I2C_M_RD) {
+ /* read bytes into buffer*/
+ ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len,
+ (i + 1 == num));
- /* Write bytes from buffer */
- ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len);
+ if (ret != pmsg->len) {
+ DEB2(printk("i2c-algo-pcf.o: fail: "
+ "only read %d bytes.\n",ret));
+ } else {
+ DEB2(printk("i2c-algo-pcf.o: read %d bytes.\n",ret));
+ }
+ } else { /* Write */
+ ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
+ (i + 1 == num));
- if (ret != pmsg->len) {
- DEB2(printk("i2c-algo-pcf.o: fail: "
- "only wrote %d bytes.\n",ret));
- } else {
- DEB2(printk("i2c-algo-pcf.o: wrote %d bytes.\n",ret));
+ if (ret != pmsg->len) {
+ DEB2(printk("i2c-algo-pcf.o: fail: "
+ "only wrote %d bytes.\n",ret));
+ } else {
+ DEB2(printk("i2c-algo-pcf.o: wrote %d bytes.\n",ret));
+ }
}
}
- return (num);
+
+ return (i);
}
static int algo_control(struct i2c_adapter *adapter,
int i, status;
struct i2c_algo_pcf_data *pcf_adap = adap->algo_data;
- if (pcf_test) {
- int ret = test_bus(pcf_adap, adap->name);
- if (ret<0)
- return -ENODEV;
- }
-
DEB2(printk("i2c-algo-pcf.o: hw routines for %s registered.\n",
adap->name));
adap->id |= pcf_algo.id;
adap->algo = &pcf_algo;
- adap->timeout = 100; /* default values, should */
+ adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
+ if ((i = pcf_init_8584(pcf_adap))) {
+ return i;
+ }
+
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
i2c_add_adapter(adap);
- pcf_init_8584(pcf_adap);
/* scan bus */
if (pcf_scan) {
printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s.\n",
adap->name);
for (i = 0x00; i < 0xff; i+=2) {
+ if (wait_for_bb(pcf_adap)) {
+ printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s - TIMEOUTed.\n",
+ adap->name);
+ break;
+ }
i2c_outb(pcf_adap, i);
i2c_start(pcf_adap);
if ((wait_for_pin(pcf_adap, &status) >= 0) &&
MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
MODULE_LICENSE("GPL");
-MODULE_PARM(pcf_test, "i");
MODULE_PARM(pcf_scan, "i");
MODULE_PARM(i2c_debug,"i");
-MODULE_PARM_DESC(pcf_test, "Test if the I2C bus is available");
MODULE_PARM_DESC(pcf_scan, "Scan for active chips on the bus");
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-core.c,v 1.58 2000/10/29 22:57:38 frodo Exp $ */
+/* $Id: i2c-core.c,v 1.64 2001/08/13 01:35:56 mds Exp $ */
#include <linux/module.h>
#include <linux/kernel.h>
*/
if ((res=client->driver->detach_client(client))) {
printk("i2c-core.o: adapter %s not "
- "unregisted, because client at "
+ "unregistered, because client at "
"address %02x can't be detached. ",
adap->name, client->addr);
goto ERROR0;
if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
return adapters[j]->clients[i];
}
+ i = 0;
}
return 0;
int i,j,k,order_nr,len=0,len_total;
int order[I2C_CLIENT_MAX];
- if (count < 0)
+ if (count > 4000)
return -EINVAL;
len_total = file->f_pos + count;
/* Too bad if this gets longer (unlikely) */
}
#ifndef MODULE
+#ifdef CONFIG_I2C_CHARDEV
extern int i2c_dev_init(void);
+#endif
+#ifdef CONFIG_I2C_ALGOBIT
extern int i2c_algo_bit_init(void);
+#endif
+#ifdef CONFIG_I2C_CONFIG_I2C_PHILIPSPAR
extern int i2c_bitlp_init(void);
+#endif
+#ifdef CONFIG_I2C_ELV
extern int i2c_bitelv_init(void);
+#endif
+#ifdef CONFIG_I2C_VELLEMAN
extern int i2c_bitvelle_init(void);
+#endif
+#ifdef CONFIG_I2C_BITVIA
extern int i2c_bitvia_init(void);
+#endif
+
+#ifdef CONFIG_I2C_ALGOPCF
extern int i2c_algo_pcf_init(void);
+#endif
+#ifdef CONFIG_I2C_ELEKTOR
extern int i2c_pcfisa_init(void);
+#endif
+
+#ifdef CONFIG_I2C_ALGO8XX
+ extern int i2c_algo_8xx_init(void);
+#endif
+#ifdef CONFIG_I2C_RPXLITE
+ extern int i2c_rpx_init(void);
+#endif
+#ifdef CONFIG_I2C_PROC
+ extern int sensors_init(void);
+#endif
/* This is needed for automatic patch generation: sensors code starts here */
/* This is needed for automatic patch generation: sensors code ends here */
#ifdef CONFIG_I2C_ELEKTOR
i2c_pcfisa_init();
#endif
+
+ /* --------------------- 8xx -------- */
+#ifdef CONFIG_I2C_ALGO8XX
+ i2c_algo_8xx_init();
+#endif
+#ifdef CONFIG_I2C_RPXLITE
+ i2c_rpx_init();
+#endif
+
+ /* -------------- proc interface ---- */
+#ifdef CONFIG_I2C_PROC
+ sensors_init();
+#endif
/* This is needed for automatic patch generation: sensors code starts here */
/* This is needed for automatic patch generation: sensors code ends here */
/* The devfs code is contributed by Philipp Matthias Hahn
<pmhahn@titan.lahn.de> */
-/* $Id: i2c-dev.c,v 1.36 2000/09/22 02:19:35 mds Exp $ */
+/* $Id: i2c-dev.c,v 1.40 2001/08/25 01:28:01 mds Exp $ */
#include <linux/config.h>
#include <linux/kernel.h>
/* struct file_operations changed too often in the 2.1 series for nice code */
+#if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,9)
+static loff_t i2cdev_lseek (struct file *file, loff_t offset, int origin);
+#endif
static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
loff_t *offset);
static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
owner: THIS_MODULE,
#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
+#if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,9)
+ llseek: i2cdev_lseek,
+#else
llseek: no_llseek,
+#endif
read: i2cdev_read,
write: i2cdev_write,
ioctl: i2cdev_ioctl,
static int i2cdev_initialized;
+#if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,9)
+/* Note that the lseek function is called llseek in 2.1 kernels. But things
+ are complicated enough as is. */
+loff_t i2cdev_lseek (struct file *file, loff_t offset, int origin)
+{
+#ifdef DEBUG
+ struct inode *inode = file->f_dentry->d_inode;
+ printk("i2c-dev.o: i2c-%d lseek to %ld bytes relative to %d.\n",
+ MINOR(inode->i_rdev),(long) offset,origin);
+#endif /* DEBUG */
+ return -ESPIPE;
+}
+#endif
+
static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
loff_t *offset)
{
sizeof(rdwr_arg)))
return -EFAULT;
- if(rdwr_arg.nmsgs > 2048)
- return -EINVAL;
-
rdwr_pa = (struct i2c_msg *)
kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
GFP_KERNEL);
"module not removed.\n");
return res;
}
- i2cdev_initialized ++;
+ i2cdev_initialized --;
}
if (i2cdev_initialized >= 1) {
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-elektor.c,v 1.19 2000/07/25 23:52:17 frodo Exp $ */
+/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
+ for Alpha Processor Inc. UP-2000(+) boards */
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/init.h>
+#include <linux/pci.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/i2c-elektor.h>
#include "i2c-pcf8584.h"
-#define DEFAULT_BASE 0x300
-#define DEFAULT_IRQ 0
-#define DEFAULT_CLOCK 0x1c
-#define DEFAULT_OWN 0x55
-
-static int base = 0;
-static int irq = 0;
-static int clock = 0;
-static int own = 0;
-static int i2c_debug=0;
-static struct i2c_pcf_isa gpi;
+#define DEFAULT_BASE 0x330
+
+static int base = 0;
+static int irq = 0;
+static int clock = 0x1c;
+static int own = 0x55;
+static int mmapped = 0;
+static int i2c_debug = 0;
+
+/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
+ this module in real supports only one device, due to missing arguments
+ in some functions, called from the algo-pcf module. Sometimes it's
+ need to be rewriten - but for now just remove this for simpler reading */
+
#if (LINUX_VERSION_CODE < 0x020301)
static struct wait_queue *pcf_wait = NULL;
#else
#define DEB3(x) if (i2c_debug>=3) x
#define DEBE(x) x /* error messages */
-
-/* --- Convenience defines for the i2c port: */
-#define BASE ((struct i2c_pcf_isa *)(data))->pi_base
-#define DATA BASE /* Adapter data port */
-#define CTRL (BASE+1) /* Adapter control port */
-
/* ----- local functions ---------------------------------------------- */
static void pcf_isa_setbyte(void *data, int ctl, int val)
{
- unsigned long j = jiffies + 10;
-
- if (ctl) {
- if (gpi.pi_irq > 0) {
- DEB3(printk("i2c-elektor.o: Write Ctrl 0x%02X\n",
- val|I2C_PCF_ENI));
- DEB3({while (jiffies < j) schedule();})
- outb(val | I2C_PCF_ENI, CTRL);
- } else {
- DEB3(printk("i2c-elektor.o: Write Ctrl 0x%02X\n", val|I2C_PCF_ENI));
- DEB3({while (jiffies < j) schedule();})
- outb(val|I2C_PCF_ENI, CTRL);
- }
- } else {
- DEB3(printk("i2c-elektor.o: Write Data 0x%02X\n", val&0xff));
- DEB3({while (jiffies < j) schedule();})
- outb(val, DATA);
+ int address = ctl ? (base + 1) : base;
+
+ if (ctl && irq) {
+ val |= I2C_PCF_ENI;
+ }
+
+ DEB3(printk("i2c-elektor.o: Write 0x%X 0x%02X\n", address, val & 255));
+
+ switch (mmapped) {
+ case 0: /* regular I/O */
+ outb(val, address);
+ break;
+ case 2: /* double mapped I/O needed for UP2000 board,
+ I don't know why this... */
+ writeb(val, address);
+ /* fall */
+ case 1: /* memory mapped I/O */
+ writeb(val, address);
+ break;
}
}
static int pcf_isa_getbyte(void *data, int ctl)
{
- int val;
+ int address = ctl ? (base + 1) : base;
+ int val = mmapped ? readb(address) : inb(address);
+
+ DEB3(printk("i2c-elektor.o: Read 0x%X 0x%02X\n", address, val));
- if (ctl) {
- val = inb(CTRL);
- DEB3(printk("i2c-elektor.o: Read Ctrl 0x%02X\n", val));
- } else {
- val = inb(DATA);
- DEB3(printk("i2c-elektor.o: Read Data 0x%02X\n", val));
- }
return (val);
}
static int pcf_isa_getown(void *data)
{
- return (gpi.pi_own);
+ return (own);
}
static int pcf_isa_getclock(void *data)
{
- return (gpi.pi_clock);
-}
-
-
-
-#if 0
-static void pcf_isa_sleep(unsigned long timeout)
-{
- schedule_timeout( timeout * HZ);
+ return (clock);
}
-#endif
-
static void pcf_isa_waitforpin(void) {
int timeout = 2;
- if (gpi.pi_irq > 0) {
+ if (irq > 0) {
cli();
- if (pcf_pending == 0) {
- interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
- } else
- pcf_pending = 0;
+ if (pcf_pending == 0) {
+ interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
+ } else
+ pcf_pending = 0;
sti();
} else {
udelay(100);
static int pcf_isa_init(void)
{
- if (check_region(gpi.pi_base, 2) < 0 ) {
- return -ENODEV;
- } else {
- request_region(gpi.pi_base, 2, "i2c (isa bus adapter)");
+ if (!mmapped) {
+ if (check_region(base, 2) < 0 ) {
+ printk("i2c-elektor.o: requested I/O region (0x%X:2) is in use.\n", base);
+ return -ENODEV;
+ } else {
+ request_region(base, 2, "i2c (isa bus adapter)");
+ }
}
- if (gpi.pi_irq > 0) {
- if (request_irq(gpi.pi_irq, pcf_isa_handler, 0, "PCF8584", 0)
- < 0) {
- printk("i2c-elektor.o: Request irq%d failed\n", gpi.pi_irq);
- gpi.pi_irq = 0;
- } else
- enable_irq(gpi.pi_irq);
+ if (irq > 0) {
+ if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", 0) < 0) {
+ printk("i2c-elektor.o: Request irq%d failed\n", irq);
+ irq = 0;
+ } else
+ enable_irq(irq);
}
return 0;
}
-static void pcf_isa_exit(void)
+static void __exit pcf_isa_exit(void)
{
- if (gpi.pi_irq > 0) {
- disable_irq(gpi.pi_irq);
- free_irq(gpi.pi_irq, 0);
+ if (irq > 0) {
+ disable_irq(irq);
+ free_irq(irq, 0);
+ }
+ if (!mmapped) {
+ release_region(base , 2);
}
- release_region(gpi.pi_base , 2);
}
pcf_isa_getown,
pcf_isa_getclock,
pcf_isa_waitforpin,
- 80, 80, 100, /* waits, timeout */
+ 10, 10, 100, /* waits, timeout */
};
static struct i2c_adapter pcf_isa_ops = {
int __init i2c_pcfisa_init(void)
{
+#ifdef __alpha__
+ /* check to see we have memory mapped PCF8584 connected to the
+ Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
+ if ((base == 0) && pci_present()) {
+
+ struct pci_dev *cy693_dev =
+ pci_find_device(PCI_VENDOR_ID_CONTAQ,
+ PCI_DEVICE_ID_CONTAQ_82C693, NULL);
+
+ if (cy693_dev) {
+ char config;
+ /* yeap, we've found cypress, let's check config */
+ if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
+
+ DEB3(printk("i2c-elektor.o: found cy82c693, config register 0x47 = 0x%02x.\n", config));
+
+ /* UP2000 board has this register set to 0xe1,
+ but the most significant bit as seems can be
+ reset during the proper initialisation
+ sequence if guys from API decides to do that
+ (so, we can even enable Tsunami Pchip
+ window for the upper 1 Gb) */
+
+ /* so just check for ROMCS at 0xe0000,
+ ROMCS enabled for writes
+ and external XD Bus buffer in use. */
+ if ((config & 0x7f) == 0x61) {
+ /* seems to be UP2000 like board */
+ base = 0xe0000;
+ /* I don't know why we need to
+ write twice */
+ mmapped = 2;
+ /* UP2000 drives ISA with
+ 8.25 MHz (PCI/4) clock
+ (this can be read from cypress) */
+ clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
+ printk("i2c-elektor.o: found API UP2000 like board, will probe PCF8584 later.\n");
+ }
+ }
+ }
+ }
+#endif
- struct i2c_pcf_isa *pisa = &gpi;
+ /* sanity checks for mmapped I/O */
+ if (mmapped && base < 0xc8000) {
+ printk("i2c-elektor.o: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
+ return -ENODEV;
+ }
printk("i2c-elektor.o: i2c pcf8584-isa adapter module\n");
- if (base == 0)
- pisa->pi_base = DEFAULT_BASE;
- else
- pisa->pi_base = base;
-
- if (irq == 0)
- pisa->pi_irq = DEFAULT_IRQ;
- else
- pisa->pi_irq = irq;
-
- if (clock == 0)
- pisa->pi_clock = DEFAULT_CLOCK;
- else
- pisa->pi_clock = clock;
-
- if (own == 0)
- pisa->pi_own = DEFAULT_OWN;
- else
- pisa->pi_own = own;
-
- pcf_isa_data.data = (void *)pisa;
+
+ if (base == 0) {
+ base = DEFAULT_BASE;
+ }
+
#if (LINUX_VERSION_CODE >= 0x020301)
init_waitqueue_head(&pcf_wait);
#endif
} else {
return -ENODEV;
}
- printk("i2c-elektor.o: found device at %#x.\n", pisa->pi_base);
+
+ printk("i2c-elektor.o: found device at %#x.\n", base);
+
return 0;
}
MODULE_PARM(irq, "i");
MODULE_PARM(clock, "i");
MODULE_PARM(own, "i");
-MODULE_PARM(i2c_debug,"i");
+MODULE_PARM(mmapped, "i");
+MODULE_PARM(i2c_debug, "i");
int init_module(void)
{
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-elv.c,v 1.16 2000/01/18 23:54:07 frodo Exp $ */
+/* $Id: i2c-elv.c,v 1.17 2001/07/29 02:44:25 mds Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
return 0;
}
-static void bit_elv_exit(void)
+static void __exit bit_elv_exit(void)
{
release_region( base , (base == 0x3bc)? 3 : 8 );
}
--- /dev/null
+/*
+ i2c-proc.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ This driver puts entries in /proc/sys/dev/sensors for each I2C device
+*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-proc.h>
+
+#include <linux/init.h>
+
+/* FIXME need i2c versioning */
+#define LM_DATE "20010825"
+#define LM_VERSION "2.6.1"
+
+#ifndef THIS_MODULE
+#define THIS_MODULE NULL
+#endif
+
+static int i2c_create_name(char **name, const char *prefix,
+ struct i2c_adapter *adapter, int addr);
+static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
+ long *results, int magnitude);
+static int i2c_write_reals(int nrels, void *buffer, int *bufsize,
+ long *results, int magnitude);
+static int i2c_proc_chips(ctl_table * ctl, int write,
+ struct file *filp, void *buffer,
+ size_t * lenp);
+static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
+ void *oldval, size_t * oldlenp,
+ void *newval, size_t newlen,
+ void **context);
+
+int __init sensors_init(void);
+
+#define SENSORS_ENTRY_MAX 20
+static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
+
+static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
+static unsigned short i2c_inodes[SENSORS_ENTRY_MAX];
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+static void i2c_fill_inode(struct inode *inode, int fill);
+static void i2c_dir_fill_inode(struct inode *inode, int fill);
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) */
+
+static ctl_table sysctl_table[] = {
+ {CTL_DEV, "dev", NULL, 0, 0555},
+ {0},
+ {DEV_SENSORS, "sensors", NULL, 0, 0555},
+ {0},
+ {0, NULL, NULL, 0, 0555},
+ {0}
+};
+
+static ctl_table i2c_proc_dev_sensors[] = {
+ {SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips,
+ &i2c_sysctl_chips},
+ {0}
+};
+
+static ctl_table i2c_proc_dev[] = {
+ {DEV_SENSORS, "sensors", NULL, 0, 0555, i2c_proc_dev_sensors},
+ {0},
+};
+
+
+static ctl_table i2c_proc[] = {
+ {CTL_DEV, "dev", NULL, 0, 0555, i2c_proc_dev},
+ {0}
+};
+
+
+static struct ctl_table_header *i2c_proc_header;
+static int i2c_initialized;
+
+/* This returns a nice name for a new directory; for example lm78-isa-0310
+ (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for
+ a LM75 chip on the third i2c bus at address 0x4e).
+ name is allocated first. */
+int i2c_create_name(char **name, const char *prefix,
+ struct i2c_adapter *adapter, int addr)
+{
+ char name_buffer[50];
+ int id;
+ if (i2c_is_isa_adapter(adapter))
+ sprintf(name_buffer, "%s-isa-%04x", prefix, addr);
+ else {
+ if ((id = i2c_adapter_id(adapter)) < 0)
+ return -ENOENT;
+ sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
+ }
+ *name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
+ strcpy(*name, name_buffer);
+ return 0;
+}
+
+/* This rather complex function must be called when you want to add an entry
+ to /proc/sys/dev/sensors/chips. It also creates a new directory within
+ /proc/sys/dev/sensors/.
+ ctl_template should be a template of the newly created directory. It is
+ copied in memory. The extra2 field of each file is set to point to client.
+ If any driver wants subdirectories within the newly created directory,
+ this function must be updated!
+ controlling_mod is the controlling module. It should usually be
+ THIS_MODULE when calling. Note that this symbol is not defined in
+ kernels before 2.3.13; define it to NULL in that case. We will not use it
+ for anything older than 2.3.27 anyway. */
+int i2c_register_entry(struct i2c_client *client, const char *prefix,
+ ctl_table * ctl_template,
+ struct module *controlling_mod)
+{
+ int i, res, len, id;
+ ctl_table *new_table;
+ char *name;
+ struct ctl_table_header *new_header;
+
+ if ((res = i2c_create_name(&name, prefix, client->adapter,
+ client->addr))) return res;
+
+ for (id = 0; id < SENSORS_ENTRY_MAX; id++)
+ if (!i2c_entries[id]) {
+ break;
+ }
+ if (id == SENSORS_ENTRY_MAX) {
+ kfree(name);
+ return -ENOMEM;
+ }
+ id += 256;
+
+ len = 0;
+ while (ctl_template[len].procname)
+ len++;
+ len += 7;
+ if (!(new_table = kmalloc(sizeof(ctl_table) * len, GFP_KERNEL))) {
+ kfree(name);
+ return -ENOMEM;
+ }
+
+ memcpy(new_table, sysctl_table, 6 * sizeof(ctl_table));
+ new_table[0].child = &new_table[2];
+ new_table[2].child = &new_table[4];
+ new_table[4].child = &new_table[6];
+ new_table[4].procname = name;
+ new_table[4].ctl_name = id;
+ memcpy(new_table + 6, ctl_template, (len - 6) * sizeof(ctl_table));
+ for (i = 6; i < len; i++)
+ new_table[i].extra2 = client;
+
+ if (!(new_header = register_sysctl_table(new_table, 0))) {
+ kfree(new_table);
+ kfree(name);
+ return -ENOMEM;
+ }
+
+ i2c_entries[id - 256] = new_header;
+
+ i2c_clients[id - 256] = client;
+#ifdef DEBUG
+ if (!new_header || !new_header->ctl_table ||
+ !new_header->ctl_table->child ||
+ !new_header->ctl_table->child->child ||
+ !new_header->ctl_table->child->child->de) {
+ printk
+ ("i2c-proc.o: NULL pointer when trying to install fill_inode fix!\n");
+ return id;
+ }
+#endif /* DEBUG */
+ i2c_inodes[id - 256] =
+ new_header->ctl_table->child->child->de->low_ino;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27))
+ new_header->ctl_table->child->child->de->owner = controlling_mod;
+#else
+ new_header->ctl_table->child->child->de->fill_inode =
+ &i2c_dir_fill_inode;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27)) */
+
+ return id;
+}
+
+void i2c_deregister_entry(int id)
+{
+ ctl_table *table;
+ char *temp;
+ id -= 256;
+ if (i2c_entries[id]) {
+ table = i2c_entries[id]->ctl_table;
+ unregister_sysctl_table(i2c_entries[id]);
+ /* 2-step kfree needed to keep gcc happy about const points */
+ (const char *) temp = table[4].procname;
+ kfree(temp);
+ kfree(table);
+ i2c_entries[id] = NULL;
+ i2c_clients[id] = NULL;
+ }
+}
+
+/* Monitor access for /proc/sys/dev/sensors; make unloading i2c-proc.o
+ impossible if some process still uses it or some file in it */
+void i2c_fill_inode(struct inode *inode, int fill)
+{
+ if (fill)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+}
+
+/* Monitor access for /proc/sys/dev/sensors/ directories; make unloading
+ the corresponding module impossible if some process still uses it or
+ some file in it */
+void i2c_dir_fill_inode(struct inode *inode, int fill)
+{
+ int i;
+ struct i2c_client *client;
+
+#ifdef DEBUG
+ if (!inode) {
+ printk("i2c-proc.o: Warning: inode NULL in fill_inode()\n");
+ return;
+ }
+#endif /* def DEBUG */
+
+ for (i = 0; i < SENSORS_ENTRY_MAX; i++)
+ if (i2c_clients[i]
+ && (i2c_inodes[i] == inode->i_ino)) break;
+#ifdef DEBUG
+ if (i == SENSORS_ENTRY_MAX) {
+ printk
+ ("i2c-proc.o: Warning: inode (%ld) not found in fill_inode()\n",
+ inode->i_ino);
+ return;
+ }
+#endif /* def DEBUG */
+ client = i2c_clients[i];
+ if (fill)
+ client->driver->inc_use(client);
+ else
+ client->driver->dec_use(client);
+}
+
+int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ char BUF[SENSORS_PREFIX_MAX + 30];
+ int buflen, curbufsize, i;
+ struct ctl_table *client_tbl;
+
+ if (write)
+ return 0;
+
+ /* If buffer is size 0, or we try to read when not at the start, we
+ return nothing. Note that I think writing when not at the start
+ does not work either, but anyway, this is straight from the kernel
+ sources. */
+ if (!*lenp || (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+ curbufsize = 0;
+ for (i = 0; i < SENSORS_ENTRY_MAX; i++)
+ if (i2c_entries[i]) {
+ client_tbl =
+ i2c_entries[i]->ctl_table->child->child;
+ buflen =
+ sprintf(BUF, "%d\t%s\n", client_tbl->ctl_name,
+ client_tbl->procname);
+ if (buflen + curbufsize > *lenp)
+ buflen = *lenp - curbufsize;
+ if(copy_to_user(buffer, BUF, buflen))
+ return -EFAULT;
+ curbufsize += buflen;
+ (char *) buffer += buflen;
+ }
+ *lenp = curbufsize;
+ filp->f_pos += curbufsize;
+ return 0;
+}
+
+int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
+ void *oldval, size_t * oldlenp, void *newval,
+ size_t newlen, void **context)
+{
+ struct i2c_chips_data data;
+ int i, oldlen, nrels, maxels,ret=0;
+ struct ctl_table *client_tbl;
+
+ if (oldval && oldlenp && !((ret = get_user(oldlen, oldlenp))) &&
+ oldlen) {
+ maxels = oldlen / sizeof(struct i2c_chips_data);
+ nrels = 0;
+ for (i = 0; (i < SENSORS_ENTRY_MAX) && (nrels < maxels);
+ i++)
+ if (i2c_entries[i]) {
+ client_tbl =
+ i2c_entries[i]->ctl_table->child->
+ child;
+ data.sysctl_id = client_tbl->ctl_name;
+ strcpy(data.name, client_tbl->procname);
+ if(copy_to_user(oldval, &data,
+ sizeof(struct
+ i2c_chips_data)))
+ return -EFAULT;
+ (char *) oldval +=
+ sizeof(struct i2c_chips_data);
+ nrels++;
+ }
+ oldlen = nrels * sizeof(struct i2c_chips_data);
+ if(put_user(oldlen, oldlenp))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+
+/* This funcion reads or writes a 'real' value (encoded by the combination
+ of an integer and a magnitude, the last is the power of ten the value
+ should be divided with) to a /proc/sys directory. To use this function,
+ you must (before registering the ctl_table) set the extra2 field to the
+ client, and the extra1 field to a function of the form:
+ void func(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+ This function can be called for three values of operation. If operation
+ equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in
+ nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
+ be read into results. nrels_mag should return the number of elements
+ read; the maximum number is put in it on entry. Finally, if operation
+ equals SENSORS_PROC_REAL_WRITE, the values in results should be
+ written to the chip. nrels_mag contains on entry the number of elements
+ found.
+ In all cases, client points to the client we wish to interact with,
+ and ctl_name is the SYSCTL id of the file we are accessing. */
+int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+#define MAX_RESULTS 32
+ int mag, nrels = MAX_RESULTS;
+ long results[MAX_RESULTS];
+ i2c_real_callback callback = ctl->extra1;
+ struct i2c_client *client = ctl->extra2;
+ int res;
+
+ /* If buffer is size 0, or we try to read when not at the start, we
+ return nothing. Note that I think writing when not at the start
+ does not work either, but anyway, this is straight from the kernel
+ sources. */
+ if (!*lenp || (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ /* Get the magnitude */
+ callback(client, SENSORS_PROC_REAL_INFO, ctl->ctl_name, &mag,
+ NULL);
+
+ if (write) {
+ /* Read the complete input into results, converting to longs */
+ res = i2c_parse_reals(&nrels, buffer, *lenp, results, mag);
+ if (res)
+ return res;
+
+ if (!nrels)
+ return 0;
+
+ /* Now feed this information back to the client */
+ callback(client, SENSORS_PROC_REAL_WRITE, ctl->ctl_name,
+ &nrels, results);
+
+ filp->f_pos += *lenp;
+ return 0;
+ } else { /* read */
+ /* Get the information from the client into results */
+ callback(client, SENSORS_PROC_REAL_READ, ctl->ctl_name,
+ &nrels, results);
+
+ /* And write them to buffer, converting to reals */
+ res = i2c_write_reals(nrels, buffer, lenp, results, mag);
+ if (res)
+ return res;
+ filp->f_pos += *lenp;
+ return 0;
+ }
+}
+
+/* This function is equivalent to i2c_proc_real, only it interacts with
+ the sysctl(2) syscall, and returns no reals, but integers */
+int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
+ void *oldval, size_t * oldlenp, void *newval,
+ size_t newlen, void **context)
+{
+ long results[MAX_RESULTS];
+ int oldlen, nrels = MAX_RESULTS,ret=0;
+ i2c_real_callback callback = table->extra1;
+ struct i2c_client *client = table->extra2;
+
+ /* Check if we need to output the old values */
+ if (oldval && oldlenp && !((ret=get_user(oldlen, oldlenp))) && oldlen) {
+ callback(client, SENSORS_PROC_REAL_READ, table->ctl_name,
+ &nrels, results);
+
+ /* Note the rounding factor! */
+ if (nrels * sizeof(long) < oldlen)
+ oldlen = nrels * sizeof(long);
+ oldlen = (oldlen / sizeof(long)) * sizeof(long);
+ if(copy_to_user(oldval, results, oldlen))
+ return -EFAULT;
+ if(put_user(oldlen, oldlenp))
+ return -EFAULT;
+ }
+
+ if (newval && newlen) {
+ /* Note the rounding factor! */
+ newlen -= newlen % sizeof(long);
+ nrels = newlen / sizeof(long);
+ if(copy_from_user(results, newval, newlen))
+ return -EFAULT;
+
+ /* Get the new values back to the client */
+ callback(client, SENSORS_PROC_REAL_WRITE, table->ctl_name,
+ &nrels, results);
+ }
+ return ret;
+}
+
+
+/* nrels contains initially the maximum number of elements which can be
+ put in results, and finally the number of elements actually put there.
+ A magnitude of 1 will multiply everything with 10; etc.
+ buffer, bufsize is the character buffer we read from and its length.
+ results will finally contain the parsed integers.
+
+ Buffer should contain several reals, separated by whitespace. A real
+ has the following syntax:
+ [ Minus ] Digit* [ Dot Digit* ]
+ (everything between [] is optional; * means zero or more).
+ When the next character is unparsable, everything is skipped until the
+ next whitespace.
+
+ WARNING! This is tricky code. I have tested it, but there may still be
+ hidden bugs in it, even leading to crashes and things!
+*/
+int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
+ long *results, int magnitude)
+{
+ int maxels, min, mag;
+ long res,ret=0;
+ char nextchar = 0;
+
+ maxels = *nrels;
+ *nrels = 0;
+
+ while (bufsize && (*nrels < maxels)) {
+
+ /* Skip spaces at the start */
+ while (bufsize &&
+ !((ret=get_user(nextchar, (char *) buffer))) &&
+ isspace((int) nextchar)) {
+ bufsize--;
+ ((char *) buffer)++;
+ }
+
+ if (ret)
+ return -EFAULT;
+ /* Well, we may be done now */
+ if (!bufsize)
+ return 0;
+
+ /* New defaults for our result */
+ min = 0;
+ res = 0;
+ mag = magnitude;
+
+ /* Check for a minus */
+ if (!((ret=get_user(nextchar, (char *) buffer)))
+ && (nextchar == '-')) {
+ min = 1;
+ bufsize--;
+ ((char *) buffer)++;
+ }
+ if (ret)
+ return -EFAULT;
+
+ /* Digits before a decimal dot */
+ while (bufsize &&
+ !((ret=get_user(nextchar, (char *) buffer))) &&
+ isdigit((int) nextchar)) {
+ res = res * 10 + nextchar - '0';
+ bufsize--;
+ ((char *) buffer)++;
+ }
+ if (ret)
+ return -EFAULT;
+
+ /* If mag < 0, we must actually divide here! */
+ while (mag < 0) {
+ res = res / 10;
+ mag++;
+ }
+
+ if (bufsize && (nextchar == '.')) {
+ /* Skip the dot */
+ bufsize--;
+ ((char *) buffer)++;
+
+ /* Read digits while they are significant */
+ while (bufsize && (mag > 0) &&
+ !((ret=get_user(nextchar, (char *) buffer))) &&
+ isdigit((int) nextchar)) {
+ res = res * 10 + nextchar - '0';
+ mag--;
+ bufsize--;
+ ((char *) buffer)++;
+ }
+ if (ret)
+ return -EFAULT;
+ }
+ /* If we are out of data, but mag > 0, we need to scale here */
+ while (mag > 0) {
+ res = res * 10;
+ mag--;
+ }
+
+ /* Skip everything until we hit whitespace */
+ while (bufsize &&
+ !((ret=get_user(nextchar, (char *) buffer))) &&
+ isspace((int) nextchar)) {
+ bufsize--;
+ ((char *) buffer)++;
+ }
+ if (ret)
+ return -EFAULT;
+
+ /* Put res in results */
+ results[*nrels] = (min ? -1 : 1) * res;
+ (*nrels)++;
+ }
+
+ /* Well, there may be more in the buffer, but we need no more data.
+ Ignore anything that is left. */
+ return 0;
+}
+
+int i2c_write_reals(int nrels, void *buffer, int *bufsize,
+ long *results, int magnitude)
+{
+#define BUFLEN 20
+ char BUF[BUFLEN + 1]; /* An individual representation should fit! */
+ char printfstr[10];
+ int nr = 0;
+ int buflen, mag, times;
+ int curbufsize = 0;
+
+ while ((nr < nrels) && (curbufsize < *bufsize)) {
+ mag = magnitude;
+
+ if (nr != 0) {
+ if(put_user(' ', (char *) buffer))
+ return -EFAULT;
+ curbufsize++;
+ ((char *) buffer)++;
+ }
+
+ /* Fill BUF with the representation of the next string */
+ if (mag <= 0) {
+ buflen = sprintf(BUF, "%ld", results[nr]);
+ if (buflen < 0) { /* Oops, a sprintf error! */
+ *bufsize = 0;
+ return -EINVAL;
+ }
+ while ((mag < 0) && (buflen < BUFLEN)) {
+ BUF[buflen++] = '0';
+ mag++;
+ }
+ BUF[buflen] = 0;
+ } else {
+ times = 1;
+ for (times = 1; mag-- > 0; times *= 10);
+ if (results[nr] < 0) {
+ BUF[0] = '-';
+ buflen = 1;
+ } else
+ buflen = 0;
+ strcpy(printfstr, "%ld.%0Xld");
+ printfstr[6] = magnitude + '0';
+ buflen +=
+ sprintf(BUF + buflen, printfstr,
+ abs(results[nr]) / times,
+ abs(results[nr]) % times);
+ if (buflen < 0) { /* Oops, a sprintf error! */
+ *bufsize = 0;
+ return -EINVAL;
+ }
+ }
+
+ /* Now copy it to the user-space buffer */
+ if (buflen + curbufsize > *bufsize)
+ buflen = *bufsize - curbufsize;
+ if(copy_to_user(buffer, BUF, buflen))
+ return -EFAULT;
+ curbufsize += buflen;
+ (char *) buffer += buflen;
+
+ nr++;
+ }
+ if (curbufsize < *bufsize) {
+ if(put_user('\n', (char *) buffer))
+ return -EFAULT;
+ curbufsize++;
+ }
+ *bufsize = curbufsize;
+ return 0;
+}
+
+
+/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
+int i2c_detect(struct i2c_adapter *adapter,
+ struct i2c_address_data *address_data,
+ i2c_found_addr_proc * found_proc)
+{
+ int addr, i, found, j, err;
+ struct i2c_force_data *this_force;
+ int is_isa = i2c_is_isa_adapter(adapter);
+ int adapter_id =
+ is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter);
+
+ /* Forget it if we can't probe using SMBUS_QUICK */
+ if ((!is_isa)
+ && !i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_QUICK)) return -1;
+
+ for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
+ if ((is_isa && check_region(addr, 1)) ||
+ (!is_isa && i2c_check_addr(adapter, addr)))
+ continue;
+
+ /* If it is in one of the force entries, we don't do any
+ detection at all */
+ found = 0;
+ for (i = 0;
+ !found
+ && (this_force =
+ address_data->forces + i, this_force->force); i++) {
+ for (j = 0;
+ !found
+ && (this_force->force[j] != SENSORS_I2C_END);
+ j += 2) {
+ if (
+ ((adapter_id == this_force->force[j])
+ ||
+ ((this_force->
+ force[j] == SENSORS_ANY_I2C_BUS)
+ && !is_isa))
+ && (addr == this_force->force[j + 1])) {
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found force parameter for adapter %d, addr %04x\n",
+ adapter_id, addr);
+#endif
+ if (
+ (err =
+ found_proc(adapter, addr, 0,
+ this_force->
+ kind))) return err;
+ found = 1;
+ }
+ }
+ }
+ if (found)
+ continue;
+
+ /* If this address is in one of the ignores, we can forget about it
+ right now */
+ for (i = 0;
+ !found
+ && (address_data->ignore[i] != SENSORS_I2C_END);
+ i += 2) {
+ if (
+ ((adapter_id == address_data->ignore[i])
+ ||
+ ((address_data->
+ ignore[i] == SENSORS_ANY_I2C_BUS)
+ && !is_isa))
+ && (addr == address_data->ignore[i + 1])) {
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found ignore parameter for adapter %d, "
+ "addr %04x\n", adapter_id, addr);
+#endif
+ found = 1;
+ }
+ }
+ for (i = 0;
+ !found
+ && (address_data->ignore_range[i] != SENSORS_I2C_END);
+ i += 3) {
+ if (
+ ((adapter_id == address_data->ignore_range[i])
+ ||
+ ((address_data->
+ ignore_range[i] ==
+ SENSORS_ANY_I2C_BUS) & !is_isa))
+ && (addr >= address_data->ignore_range[i + 1])
+ && (addr <= address_data->ignore_range[i + 2])) {
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found ignore_range parameter for adapter %d, "
+ "addr %04x\n", adapter_id, addr);
+#endif
+ found = 1;
+ }
+ }
+ if (found)
+ continue;
+
+ /* Now, we will do a detection, but only if it is in the normal or
+ probe entries */
+ if (is_isa) {
+ for (i = 0;
+ !found
+ && (address_data->normal_isa[i] !=
+ SENSORS_ISA_END); i += 1) {
+ if (addr == address_data->normal_isa[i]) {
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found normal isa entry for adapter %d, "
+ "addr %04x\n", adapter_id,
+ addr);
+#endif
+ found = 1;
+ }
+ }
+ for (i = 0;
+ !found
+ && (address_data->normal_isa_range[i] !=
+ SENSORS_ISA_END); i += 3) {
+ if ((addr >=
+ address_data->normal_isa_range[i])
+ && (addr <=
+ address_data->normal_isa_range[i + 1])
+ &&
+ ((addr -
+ address_data->normal_isa_range[i]) %
+ address_data->normal_isa_range[i + 2] ==
+ 0)) {
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found normal isa_range entry for adapter %d, "
+ "addr %04x", adapter_id, addr);
+#endif
+ found = 1;
+ }
+ }
+ } else {
+ for (i = 0;
+ !found && (address_data->normal_i2c[i] !=
+ SENSORS_I2C_END); i += 1) {
+ if (addr == address_data->normal_i2c[i]) {
+ found = 1;
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found normal i2c entry for adapter %d, "
+ "addr %02x", adapter_id, addr);
+#endif
+ }
+ }
+ for (i = 0;
+ !found
+ && (address_data->normal_i2c_range[i] !=
+ SENSORS_I2C_END); i += 2) {
+ if ((addr >=
+ address_data->normal_i2c_range[i])
+ && (addr <=
+ address_data->normal_i2c_range[i + 1]))
+ {
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found normal i2c_range entry for adapter %d, "
+ "addr %04x\n", adapter_id, addr);
+#endif
+ found = 1;
+ }
+ }
+ }
+
+ for (i = 0;
+ !found && (address_data->probe[i] != SENSORS_I2C_END);
+ i += 2) {
+ if (((adapter_id == address_data->probe[i]) ||
+ ((address_data->
+ probe[i] == SENSORS_ANY_I2C_BUS) & !is_isa))
+ && (addr == address_data->probe[i + 1])) {
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found probe parameter for adapter %d, "
+ "addr %04x\n", adapter_id, addr);
+#endif
+ found = 1;
+ }
+ }
+ for (i = 0; !found &&
+ (address_data->probe_range[i] != SENSORS_I2C_END);
+ i += 3) {
+ if (
+ ((adapter_id == address_data->probe_range[i])
+ ||
+ ((address_data->probe_range[i] ==
+ SENSORS_ANY_I2C_BUS) & !is_isa))
+ && (addr >= address_data->probe_range[i + 1])
+ && (addr <= address_data->probe_range[i + 2])) {
+ found = 1;
+#ifdef DEBUG
+ printk
+ ("i2c-proc.o: found probe_range parameter for adapter %d, "
+ "addr %04x\n", adapter_id, addr);
+#endif
+ }
+ }
+ if (!found)
+ continue;
+
+ /* OK, so we really should examine this address. First check
+ whether there is some client here at all! */
+ if (is_isa ||
+ (i2c_smbus_xfer
+ (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
+ if ((err = found_proc(adapter, addr, 0, -1)))
+ return err;
+ }
+ return 0;
+}
+
+int __init sensors_init(void)
+{
+ printk("i2c-proc.o version %s (%s)\n", LM_VERSION, LM_DATE);
+ i2c_initialized = 0;
+ if (!
+ (i2c_proc_header =
+ register_sysctl_table(i2c_proc, 0))) return -ENOMEM;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1))
+ i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE;
+#else
+ i2c_proc_header->ctl_table->child->de->fill_inode =
+ &i2c_fill_inode;
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)) */
+ i2c_initialized++;
+ return 0;
+}
+
+EXPORT_SYMBOL(i2c_deregister_entry);
+EXPORT_SYMBOL(i2c_detect);
+EXPORT_SYMBOL(i2c_proc_real);
+EXPORT_SYMBOL(i2c_register_entry);
+EXPORT_SYMBOL(i2c_sysctl_real);
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+MODULE_DESCRIPTION("i2c-proc driver");
+MODULE_LICENSE("GPL");
+
+int i2c_cleanup(void)
+{
+ if (i2c_initialized >= 1) {
+ unregister_sysctl_table(i2c_proc_header);
+ i2c_initialized--;
+ }
+ return 0;
+}
+
+int init_module(void)
+{
+ return sensors_init();
+}
+
+int cleanup_module(void)
+{
+ return i2c_cleanup();
+}
+#endif /* MODULE */
return 0;
}
-static void bit_velle_exit(void)
+static void __exit bit_velle_exit(void)
{
release_region( base , (base == 0x3bc)? 3 : 8 );
}
Based on work
Copyleft (C) 2001 by Wilfried Weissmann <wweissmann@gmx.at>
Copyright (C) 1994-96 Marc ZYNGIER <zyngier@ufr-info-p7.ibp.fr>
+ Based on work done by Søren Schmidt for FreeBSD
+
*/
-
+/*-
+ * Copyright (c) 2000,2001 Søren Schmidt <sos@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
struct highpoint_raid_conf
{
int8_t filler1[32];
module_init(idedisk_init);
module_exit(idedisk_exit);
+MODULE_LICENSE("GPL");
module_init(idefloppy_init);
module_exit(idefloppy_exit);
+MODULE_LICENSE("GPL");
{
ide_probe = NULL;
}
+MODULE_LICENSE("GPL");
#endif /* MODULE */
#ifdef MODULE
char *options = NULL;
MODULE_PARM(options,"s");
+MODULE_LICENSE("GPL");
static void __init parse_options (char *line)
{
}
#ifdef MODULE
+MODULE_LICENSE("GPL");
int init_module (void)
{
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input driver to keyboard driver binding");
MODULE_PARM(jp_kbd_109, "i");
+MODULE_LICENSE("GPL");
/*
* QuickCam Driver For Video4Linux.
*
- * This version only works as a module.
- *
* Video4Linux conversion work by Alan Cox.
* Parport compatibility by Phil Blundell.
* Busy loop avoidance by Mark Cooke.
MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "s");
#endif
-#ifdef MODULE
-int init_module(void)
+static void __exit exit_bw_qcams(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_cams; i++)
+ close_bwqcam(qcams[i]);
+}
+
+static int __init init_bw_qcams(void)
{
struct parport *port;
+#ifdef MODULE
int n;
+
if(parport[0] && strncmp(parport[0], "auto", 4)){
/* user gave parport parameters */
for(n=0; parport[n] && n<MAX_CAMS; n++){
}
return (num_cams)?0:-ENODEV;
-}
-
-void cleanup_module(void)
-{
- unsigned int i;
- for (i = 0; i < num_cams; i++)
- close_bwqcam(qcams[i]);
-}
#else
-int __init init_bw_qcams(struct video_init *unused)
-{
- struct parport *port;
-
for (port = parport_enumerate(); port; port=port->next)
init_bwqcam(port);
return 0;
-}
#endif
+}
+
+module_init(init_bw_qcams);
+module_exit(exit_bw_qcams);
+
MODULE_LICENSE("GPL");
#include "planb.h"
#include "saa7196.h"
-
/* Would you mind for some ugly debugging? */
-//#define DEBUG(x...) printk(KERN_DEBUG ## x) /* Debug driver */
-#define DEBUG(x...) /* Don't debug driver */
-//#define IDEBUG(x...) printk(KERN_DEBUG ## x) /* Debug interrupt part */
+#if 0
+#define DEBUG(x...) printk(KERN_DEBUG ## x) /* Debug driver */
+#else
+#define DEBUG(x...) /* Don't debug driver */
+#endif
+
+#if 0
+#define IDEBUG(x...) printk(KERN_DEBUG ## x) /* Debug interrupt part */
+#endif
#define IDEBUG(x...) /* Don't debug interrupt part */
+#endif
/* Ever seen a Mac with more than 1 of these? */
#define PLANB_MAX 1
}
}
-#ifdef MODULE
-
-int init_module(void)
-{
-#else
-int __init init_planbs(struct video_init *unused)
+static int __init init_planbs(void)
{
-#endif
int i;
if (find_planb()<=0)
return 0;
}
-#ifdef MODULE
-
-void cleanup_module(void)
+static void __exit exit_planbs(void)
{
release_planb();
}
-#endif
+module_init(init_planbs);
+module_exit(exit_planbs);
saa7110_write(decoder, 0x0D, 0x06);
saa7110_write(decoder, 0x11, 0x2C);
saa7110_write(decoder, 0x30, 0x81);
-saa7110_write(decoder, 0x2A, 0xDF);
+ saa7110_write(decoder, 0x2A, 0xDF);
break;
case VIDEO_MODE_PAL:
saa7110_write(decoder, 0x0D, 0x06);
#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
-#ifdef CONFIG_VIDEO_BWQCAM
-extern int init_bw_qcams(struct video_init *);
-#endif
-#ifdef CONFIG_VIDEO_CPIA
-extern int cpia_init(struct video_init *);
-#endif
-#ifdef CONFIG_VIDEO_PLANB
-extern int init_planbs(struct video_init *);
-#endif
-
-static struct video_init video_init_list[]={
-#ifdef CONFIG_VIDEO_BWQCAM
- {"bw-qcam", init_bw_qcams},
-#endif
-#ifdef CONFIG_VIDEO_CPIA
- {"cpia", cpia_init},
-#endif
-#ifdef CONFIG_VIDEO_PLANB
- {"planb", init_planbs},
-#endif
- {"end", NULL}
-};
-
/*
* Read will do some smarts later on. Buffer pin etc.
*/
/*
* Poll to see if we're readable, can probably be used for timing on incoming
- * frames, etc..
+ * frames, etc..
*/
static unsigned int video_poll(struct file *file, poll_table * wait)
/*
* We need to do MMAP support
*/
-
-
+
int video_mmap(struct file *file, struct vm_area_struct *vma)
{
int ret = -EINVAL;
static int __init videodev_init(void)
{
- struct video_init *vfli = video_init_list;
-
printk(KERN_INFO "Linux video capture interface: v1.00\n");
if(devfs_register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops))
{
return -EIO;
}
- /*
- * Init kernel installed video drivers
- */
-
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
videodev_proc_create ();
#endif
- while(vfli->init!=NULL)
- {
- vfli->init(vfli);
- vfli++;
- }
return 0;
}
EXPORT_NO_SYMBOLS;
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
+MODULE_LICENSE("GPL");
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int __init isense_init(void)
fi
dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
-if [ "$CONFIG_ARM" = "y" ]; then
- dep_tristate ' Compaq bootldr partition table parsing' CONFIG_MTD_BOOTLDR_PARTS $CONFIG_MTD_PARTITIONS
- dep_tristate ' ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS
-fi
+ if [ "$CONFIG_ARM" = "y" ]; then
+ dep_tristate ' Compaq bootldr partition table parsing' CONFIG_MTD_BOOTLDR_PARTS $CONFIG_MTD_PARTITIONS
+ dep_tristate ' ARM Firmware Suite partition parsing' CONFIG_MTD_AFS_PARTS $CONFIG_MTD_PARTITIONS
+ fi
comment 'User Modules And Translation Layers'
dep_tristate ' Direct char device access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD
if [ "$CONFIG_OBSOLETE" = "y" ]; then
dep_bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET $CONFIG_ISA
fi
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_MIPS" = "y" ]; then
bool ' Philips SAA9730 Ethernet support (EXPERIMENTAL)' CONFIG_LAN_SAA9730
fi
fi
EXPORT_SYMBOL(ppp_unregister_compressor);
EXPORT_SYMBOL(all_ppp_units); /* for debugging */
EXPORT_SYMBOL(all_channels); /* for debugging */
+MODULE_LICENSE("GPL");
#include <linux/init.h>
#include <asm/uaccess.h>
-#ifndef spin_trylock_bh
-#define spin_trylock_bh(lock) ({ int __r; local_bh_disable(); \
- __r = spin_trylock(lock); \
- if (!__r) local_bh_enable(); \
- __r; })
-#endif
-
#define PPP_VERSION "2.4.1"
/* Structure for storing local state. */
module_init(ppp_sync_init);
module_exit(ppp_sync_cleanup);
+MODULE_LICENSE("GPL");
EXPORT_SYMBOL(nubus_proc_detach_device);
#endif
+MODULE_LICENSE("GPL");
+
EXPORT_SYMBOL(nubus_find_device);
EXPORT_SYMBOL(nubus_find_type);
EXPORT_SYMBOL(nubus_find_slot);
} else {
DPRINTK (KERN_DEBUG "%s: ECP direction: failed to reverse\n",
port->name);
- port->ieee1284.phase = IEEE1284_PH_DIR_UNKNOWN;
+ port->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN;
}
return retval;
DPRINTK (KERN_DEBUG
"%s: ECP direction: failed to switch forward\n",
port->name);
- port->ieee1284.phase = IEEE1284_PH_DIR_UNKNOWN;
+ port->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN;
}
MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port");
+MODULE_LICENSE("GPL");
module_init(parport_amiga_init)
module_exit(parport_amiga_exit)
MODULE_AUTHOR("Andreas Schwab");
MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
+MODULE_LICENSE("GPL");
int
init_module(void)
MODULE_AUTHOR("Phil Blundell, Tim Waugh, others");
MODULE_DESCRIPTION("PC-style parallel port driver");
+MODULE_LICENSE("GPL");
+
MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
MODULE_PARM_DESC(io_hi, "Base I/O address (ECR)");
bra[-1] = 0;
if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
fprintf(stderr, "Line %d: Device name too long\n", lino);
+ fprintf(stderr, "%s\n", c);
return 1;
}
}
0396 SDRAM controller
0397 BIOS scratchpad
127a Rockwell International
- 1002 HCF 56k V90 FaxModem
- 127a 1002 HCF 56k V90 Modem
- 1003 HCF 56k V90 FaxModem
- 127a 1003 PCI56RX Modem
- 13df 1003 PCI56RX Modem
- 1004 HCF 56k V90 FaxModem
- 1005 HCF 56k V90 FaxModem
- 122d 4008 MDP3858SP-A SVD Modem
- 127a 1005 PCI56RVP Modem
- 13df 1005 PCI56RVP Modem
- 1436 1005 WS-5614PS3G
- 1025 HCF 56k PCI Modem
- 127a 1025 HCF 56k PCI Modem
+ 1002 HCF 56k Data/Fax Modem
+ 122d 4002 HPG / MDP3858-U # Aztech
+ 122d 4005 MDP3858-E # Aztech
+ 122d 4007 MDP3858-A/-NZ # Aztech
+ 122d 4012 MDP3858-SA # Aztech
+ 122d 4017 MDP3858-W # Aztech
+ 122d 4018 MDP3858-W # Aztech
+ 1003 HCF 56k Data/Fax Modem
+ 0e11 b0bc 229-DF Zephyr # Compaq
+ 0e11 b114 229-DF Cheetah # Compaq
+ 1033 802b 229-DF # NEC
+ 13df 1003 PCI56RX Modem # E-Tech Inc
+ 13e0 0117 IBM # GVC
+ 13e0 0147 IBM # GVC
+ 13e0 0197 IBM # GVC
+ 13e0 01c7 IBM # GVC
+ 13e0 01f7 IBM # GVC
+ 1436 1003 IBM # CIS
+ 1436 1103 IBM # CIS
+ 1436 1602 Compaq 229-DF Ducati
+ 1004 HCF 56k Data/Fax/Voice Modem
+ 10cf 1059 Fujitsu 229-DFRT
+ 1005 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 1033 8029 229-DFSV # NEC
+ 1033 8054 Modem # NEC
+ 10cf 103c Fujitsu
+ 10cf 1055 Fujitsu 229-DFSV
+ 10cf 1056 Fujitsu 229-DFSV
+ 122d 4003 MDP3858SP-U # Aztech
+ 122d 4006 Packard Bell MDP3858V-E # Aztech
+ 122d 4008 MDP3858SP-A/SP-NZ # Aztech
+ 122d 4009 MDP3858SP-E # Aztech
+ 122d 4010 MDP3858V-U # Aztech
+ 122d 4011 MDP3858SP-SA # Aztech
+ 122d 4013 MDP3858V-A/V-NZ # Aztech
+ 122d 4015 MDP3858SP-W # Aztech
+ 122d 4016 MDP3858V-W # Aztech
+ 122d 4019 MDP3858V-SA # Aztech
+ 13df 1005 PCI56RVP Modem # E-Tech Inc
+ 13e0 0187 IBM # GVC
+ 13e0 01a7 IBM # GVC
+ 13e0 01b7 IBM # GVC
+ 13e0 01d7 IBM # GVC
+ 1436 1005 IBM # CIS
+ 1436 1105 IBM # CIS
+ 1023 HCF 56k Data/Fax Modem
+ 122d 4020 Packard Bell MDP3858-WE # Aztech
+ 122d 4023 MDP3858-UE # Aztech
+ 13e0 0247 IBM # GVC
+ 13e0 0297 IBM # GVC
+ 13e0 02c7 IBM # GVC
+ 1436 1203 IBM # CIS
+ 1436 1303 IBM # CIS
+ 1024 HCF 56k Data/Fax/Voice Modem
+ 1025 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 10cf 106a Fujitsu 235-DFSV
+ 122d 4021 Packard Bell MDP3858V-WE # Aztech
+ 122d 4022 MDP3858SP-WE # Aztech
+ 122d 4024 MDP3858V-UE # Aztech
+ 122d 4025 MDP3858SP-UE # Aztech
1026 HCF 56k PCI Speakerphone Modem
- 127a 1026 HCF 56k PCI Speakerphone Modem
1035 HCF 56k PCI Speakerphone Modem
- 127a 1035 HCF 56k PCI Speakerphone Modem
- 1085 Volcano HCF 56k PCI Modem
- 127a 1085 Volcano HCF 56k PCI Modem
- 2005 HCF 56k V90 FaxModem
- 127a 2005 Conexant SoftK56 Speakerphone Modem
- 2015 Conexant SoftK56 Speakerphone Modem
- 127a 2015 Conexant SoftK56 Speakerphone Modem
- 14c8 2115 Conexant SoftK56 Speakerphone Modem
+ 1085 HCF 56k Volcano PCI Modem
+ 2005 HCF 56k Data/Fax Modem
+ 104d 8044 229-DFSV # Sony
+ 104d 8045 229-DFSV # Sony
+ 104d 8055 PBE/Aztech 235W-DFSV # Sony
+ 104d 8056 235-DFSV # Sony
+ 104d 805a Modem # Sony
+ 104d 805f Modem # Sony
+ 104d 8074 Modem # Sony
+ 2013 HSF 56k Data/Fax Modem
+ 1179 0001 Modem # Toshiba
+ 1179 ff00 Modem # Toshiba
+ 2014 HSF 56k Data/Fax/Voice Modem
+ 10cf 1057 Fujitsu Citicorp III
+ 122d 4050 MSP3880-U # Aztech
+ 122d 4055 MSP3880-W # Aztech
+ 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 10cf 1063 Fujitsu
+ 10cf 1064 Fujitsu
+ 1468 2015 Fujitsu
+ 2016 HSF 56k Data/Fax/Voice/Spkp Modem
+ 122d 4051 MSP3880V-W # Aztech
+ 122d 4052 MSP3880SP-W # Aztech
+ 122d 4054 MSP3880V-U # Aztech
+ 122d 4056 MSP3880SP-U # Aztech
+ 122d 4057 MSP3880SP-A # Aztech
+ 4311 Riptide HSF 56k PCI Modem
+ 127a 4311 Ring Modular? Riptide HSF RT HP Dom
+ 13e0 0210 HP-GVC
4320 Riptide PCI Audio Controller
1235 4320 Riptide PCI Audio Controller
4321 Riptide HCF 56k PCI Modem
- 1235 4321 Riptide HCF 56k PCI Modem
+ 1235 4321 Hewlett Packard DF
+ 1235 4324 Hewlett Packard DF
+ 13e0 0210 Hewlett Packard DF
+ 144d 2321 Riptide # Samsung
4322 Riptide PCI Game Controller
1235 4322 Riptide PCI Game Controller
8234 RapidFire 616X ATM155 Adapter
148b INNOMEDIALOGIC Inc.
148c C.P. Technology Co. Ltd
148d DIGICOM Systems, Inc.
+ 1003 HCF 56k Data/Fax Modem
148e OSI Plus Corporation
148f Plant Equipment, Inc.
1490 Stone Microsystems PTY Ltd.
14ee MASPRO KENKOH Corp
14ef CARRY Computer ENG. CO Ltd
14f0 CANON RESEACH CENTRE FRANCE
-14f1 CONEXANT
- 1033 56K Winmodem
- 13e0 02b0 56K Winmodem
- 1035 PCI Modem Enumerator
- 2003 SoftK56 Winmodem
- 14f1 2003 SoftK56 Winmodem
- 2004 SoftK56 RemoteTAM Winmodem
- 14f1 2004 SoftK56 RemoteTAM Winmodem
- 2005 SoftK56 Speakerphone Winmodem
- 14f1 2005 SoftK56 Speakerphone Winmodem
- 2006 SoftK56 Speakerphone Winmodem
- 14f1 2006 SoftK56 Speakerphone Winmodem
- 2013 HSP MicroModem 56K
- 14f1 2013 SoftK56 Winmodem
- 2014 SoftK56 RemoteTAM Winmodem
- 144f 101c SoftK56 RemoteTAM Winmodem
- 144f 2014 SoftK56 RemoteTAM Winmodem
- 2015 SoftK56 Speakerphone Winmodem
- 14c8 2115 SoftK56 Speakerphone Winmodem
- 14f1 2015 SoftK56 Speakerphone Winmodem
- 2016 SoftK56 Speakerphone Winmodem
- 14f1 2016 SoftK56 Speakerphone Winmodem
- 2443 SoftK56 Speakerphone Winmodem
- 14f1 2443 SoftK56 Speakerphone Winmodem
+14f1 Conexant
+ 1033 HCF 56k Data/Fax Modem
+ 1033 8077 NEC
+ 122d 4027 Dell Zeus - MDP3880-W(B) Data Fax Modem # Aztech
+ 122d 4030 Dell Mercury - MDP3880-U(B) Data Fax Modem # Aztech
+ 122d 4034 Dell Thor - MDP3880-W(U) Data Fax Modem # Aztech
+ 13e0 020d Dell Copper
+ 13e0 020e Dell Silver
+ 13e0 0261 IBM # GVC
+ 13e0 0290 Compaq Goldwing
+ 13e0 02a0 IBM # GVC
+ 13e0 02b0 IBM # GVC
+ 13e0 02c0 Compaq Scooter
+ 13e0 02d0 IBM # GVC
+ 144f 1500 IBM P85-DF # Askey
+ 144f 1501 IBM P85-DF # Askey
+ 144f 150a IBM P85-DF # Askey
+ 144f 150b IBM P85-DF Low Profile # Askey
+ 144f 1510 IBM P85-DF Low Profile # Askey
+ 1034 HCF 56k Data/Fax/Voice Modem
+ 1035 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 10cf 1098 Fujitsu P85-DFSV
+ 1036 HCF 56k Data/Fax/Voice/Spkp Modem
+ 122d 4029 MDP3880SP-W # Aztech
+ 122d 4031 MDP3880SP-U # Aztech
+ 13e0 0209 Dell Titanium
+ 13e0 020a Dell Graphite
+ 13e0 0260 Gateway Red Owl
+ 13e0 0270 Gateway White Horse
+ 1052 HCF 56k Data/Fax Modem (Worldwide)
+ 1053 HCF 56k Data/Fax Modem (Worldwide)
+ 1054 HCF 56k Data/Fax/Voice Modem (Worldwide)
+ 1055 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Worldwide)
+ 1056 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
+ 1057 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
+ 1059 HCF 56k Data/Fax/Voice Modem (Worldwide)
+ 1063 HCF 56k Data/Fax Modem
+ 1064 HCF 56k Data/Fax/Voice Modem
+ 1065 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 1066 HCF 56k Data/Fax/Voice/Spkp Modem
+ 122d 4033 Dell Athena - MDP3900V-U # Aztech
+ 1433 HCF 56k Data/Fax Modem
+ 1434 HCF 56k Data/Fax/Voice Modem
+ 1435 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 1436 HCF 56k Data/Fax Modem
+ 1453 HCF 56k Data/Fax Modem
+ 13e0 0240 IBM # GVC
+ 13e0 0250 IBM # GVC
+ 144f 1502 IBM P95-DF # Askey
+ 144f 1503 IBM P95-DF # Askey
+ 1454 HCF 56k Data/Fax/Voice Modem
+ 1455 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 1456 HCF 56k Data/Fax/Voice/Spkp Modem
+ 122d 4035 Dell Europa - MDP3900V-W # Aztech
+ 122d 4302 MP3930V-W(C) MiniPCI # Aztech
+ 1803 HCF 56k Modem
+ 0e11 0023 623-LAN Grizzly # Compaq
+ 0e11 0043 623-LAN Yogi # Compaq
+ 1815 HCF 56k Modem
+ 0e11 0022 Grizzly # Compaq
+ 0e11 0042 Yogi # Compaq
+ 2003 HSF 56k Data/Fax Modem
+ 2004 HSF 56k Data/Fax/Voice Modem
+ 2005 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 2006 HSF 56k Data/Fax/Voice/Spkp Modem
+ 2013 HSF 56k Data/Fax Modem
+ 0e11 b195 Bear # Compaq
+ 0e11 b196 Seminole 1 # Compaq
+ 0e11 b1be Seminole 2 # Compaq
+ 1025 8013 Acer
+ 1033 809d NEC
+ 1033 80bc NEC
+ 155d 6793 HP
+ 155d 8850 E Machines
+ 2014 HSF 56k Data/Fax/Voice Modem
+ 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem
+ 2016 HSF 56k Data/Fax/Voice/Spkp Modem
+ 2043 HSF 56k Data/Fax Modem (Worldwide SmartDAA)
+ 2044 HSF 56k Data/Fax/Voice Modem (Worldwide SmartDAA)
+ 2045 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Worldwide SmartDAA)
+ 2046 HSF 56k Data/Fax/Voice/Spkp Modem (Worldwide SmartDAA)
+ 2063 HSF 56k Data/Fax Modem (SmartDAA)
+ 2064 HSF 56k Data/Fax/Voice Modem (SmartDAA)
+ 2065 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (SmartDAA)
+ 2066 HSF 56k Data/Fax/Voice/Spkp Modem (SmartDAA)
+ 2093 HSF 56k Modem
+ 155d 2f07 Legend
+ 2143 HSF 56k Data/Fax/Cell Modem (Mobile Worldwide SmartDAA)
+ 2144 HSF 56k Data/Fax/Voice/Cell Modem (Mobile Worldwide SmartDAA)
+ 2145 HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob WW SmartDAA)
+ 2146 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mobile Worldwide SmartDAA)
+ 2163 HSF 56k Data/Fax/Cell Modem (Mobile SmartDAA)
+ 2164 HSF 56k Data/Fax/Voice/Cell Modem (Mobile SmartDAA)
+ 2165 HSF 56k Data/Fax/Voice/Spkp (w/Handset)/Cell Modem (Mobile SmartDAA)
+ 2166 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mobile SmartDAA)
+ 2343 HSF 56k Data/Fax CardBus Modem (Mobile Worldwide SmartDAA)
+ 2344 HSF 56k Data/Fax/Voice CardBus Modem (Mobile Worldwide SmartDAA)
+ 2345 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob WW SmartDAA)
+ 2346 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mobile Worldwide SmartDAA)
+ 2363 HSF 56k Data/Fax CardBus Modem (Mobile SmartDAA)
+ 2364 HSF 56k Data/Fax/Voice CardBus Modem (Mobile SmartDAA)
+ 2365 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob SmartDAA)
+ 2366 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mobile SmartDAA)
+ 2443 HSF 56k Data/Fax Modem (Mobile Worldwide SmartDAA)
+ 104d 8075 Modem # Sony
+ 104d 8083 Modem # Sony
+ 104d 8097 Modem # Sony
+ 2444 HSF 56k Data/Fax/Voice Modem (Mobile Worldwide SmartDAA)
+ 2445 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mobile WW SmartDAA)
+ 2446 HSF 56k Data/Fax/Voice/Spkp Modem (Mobile Worldwide SmartDAA)
+ 2463 HSF 56k Data/Fax Modem (Mobile SmartDAA)
+ 2464 HSF 56k Data/Fax/Voice Modem (Mobile SmartDAA)
+ 2465 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Mobile SmartDAA)
+ 2466 HSF 56k Data/Fax/Voice/Spkp Modem (Mobile SmartDAA)
+ 2f00 HSF 56k HSFi Modem
+ 13e0 8d84 IBM HSFi V.90
+ 13e0 8d85 Compaq Stinger
14f2 MOBILITY Electronics
14f3 BROADLOGIC
14f4 TOKYO Electronic Industry CO Ltd
endif
endif
+obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
+
+sa1100_cs-objs-y := sa1100_generic.o
+sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
+sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
+sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
+sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
+sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o
+sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o
+sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o
+sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
+sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
+sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o
+sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
+sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
+sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
+sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o
+sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o
+sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o
+
include $(TOPDIR)/Rules.make
pcmcia_core.o: $(pcmcia_core-objs)
$(LD) $(LD_RFLAG) -r -o $@ $(pcmcia_core-objs)
+sa1100_cs.o: $(sa1100_cs-objs-y)
+ $(LD) -r -o $@ $(sa1100_cs-objs-y)
+
yenta_socket.o: $(yenta_socket-objs)
$(LD) $(LD_RFLAG) -r -o $@ $(yenta_socket-objs)
*base, align);
align = 0;
}
+ if ((s->cap.features & SS_CAP_STATIC_MAP) && s->cap.io_offset) {
+ *base = s->cap.io_offset | (*base & 0x0fff);
+ return 0;
+ }
/* Check for an already-allocated window that must conflict with
what was asked for. It is a hack because it does not catch all
potential conflicts, just the most obvious ones. */
ioaddr_t num)
{
int i;
- release_region(base, num);
+ if(!(s->cap.features & SS_CAP_STATIC_MAP))
+ release_region(base, num);
for (i = 0; i < MAX_IO_WIN; i++) {
if ((s->io[i].BasePort <= base) &&
(s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
s->state &= ~SOCKET_WIN_REQ(win->index);
/* Release system memory */
- release_mem_region(win->base, win->size);
+ if(!(s->cap.features & SS_CAP_STATIC_MAP))
+ release_mem_region(win->base, win->size);
win->handle->state &= ~CLIENT_WIN_REQ(win->index);
win->magic = 0;
--- /dev/null
+/*======================================================================
+
+ Device driver for the PCMCIA control functionality of StrongARM
+ SA-1100 microprocessors.
+
+ The contents of this file are subject to the Mozilla Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ The initial developer of the original code is John G. Dorsey
+ <john+@cs.cmu.edu>. Portions created by John G. Dorsey are
+ Copyright (C) 1999 John G. Dorsey. All Rights Reserved.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the GNU Public License version 2 (the "GPL"), in which
+ case the provisions of the GPL are applicable instead of the
+ above. If you wish to allow the use of your version of this file
+ only under the terms of the GPL and not to allow others to use
+ your version of this file under the MPL, indicate your decision
+ by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL. If you do not delete
+ the provisions above, a recipient may use your version of this
+ file under either the MPL or the GPL.
+
+======================================================================*/
+
+#if !defined(_PCMCIA_SA1100_H)
+# define _PCMCIA_SA1100_H
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+#include <asm/arch/pcmcia.h>
+
+
+/* MECR: Expansion Memory Configuration Register
+ * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
+ *
+ * MECR layout is:
+ *
+ * FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0>
+ *
+ * (This layout is actually true only for the SA-1110; the FASTn bits are
+ * reserved on the SA-1100.)
+ */
+
+#define MECR_SOCKET_0_SHIFT (0)
+#define MECR_SOCKET_1_SHIFT (16)
+
+#define MECR_BS_MASK (0x1f)
+#define MECR_FAST_MODE_MASK (0x01)
+
+#define MECR_BSIO_SHIFT (0)
+#define MECR_BSA_SHIFT (5)
+#define MECR_BSM_SHIFT (10)
+#define MECR_FAST_SHIFT (15)
+
+#define MECR_SET(mecr, sock, shift, mask, bs) \
+((mecr)=((mecr)&~(((mask)<<(shift))<<\
+ ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\
+ (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))
+
+#define MECR_GET(mecr, sock, shift, mask) \
+((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\
+ (shift))&(mask))
+
+#define MECR_BSIO_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSIO_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK)
+
+#define MECR_BSA_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSA_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK)
+
+#define MECR_BSM_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSM_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK)
+
+#define MECR_FAST_SET(mecr, sock, fast) \
+MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast))
+
+#define MECR_FAST_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK)
+
+
+/* This function implements the BS value calculation for setting the MECR
+ * using integer arithmetic:
+ */
+static inline unsigned int sa1100_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns,
+ unsigned int cpu_clock_khz){
+ unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000;
+ return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1);
+}
+
+/* This function returns the (approxmiate) command assertion period, in
+ * nanoseconds, for a given CPU clock frequency and MECR BS value:
+ */
+static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
+ unsigned int pcmcia_mecr_bs){
+ return (((10000000 * 2) / cpu_clock_khz) * (3 * (pcmcia_mecr_bs + 1))) / 10;
+}
+
+
+/* SA-1100 PCMCIA Memory and I/O timing
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * The SA-1110 Developer's Manual, section 10.2.5, says the following:
+ *
+ * "To calculate the recommended BS_xx value for each address space:
+ * divide the command width time (the greater of twIOWR and twIORD,
+ * or the greater of twWE and twOE) by processor cycle time; divide
+ * by 2; divide again by 3 (number of BCLK's per command assertion);
+ * round up to the next whole number; and subtract 1."
+ *
+ * The PC Card Standard, Release 7, section 4.13.4, says that twIORD
+ * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has
+ * a minimum value of 165ns, as well. Section 4.7.2 (describing
+ * common and attribute memory write timing) says that twWE has a
+ * minimum value of 150ns for a 250ns cycle time (for 5V operation;
+ * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V
+ * operation, also section 4.7.4). Section 4.7.3 says that taOE
+ * has a maximum value of 150ns for a 300ns cycle time (for 5V
+ * operation), or 300ns for a 600ns cycle time (for 3.3V operation).
+ *
+ * When configuring memory maps, Card Services appears to adopt the policy
+ * that a memory access time of "0" means "use the default." The default
+ * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute
+ * and memory command width time is 150ns; the PCMCIA 3.3V attribute and
+ * memory command width time is 300ns.
+ */
+#define SA1100_PCMCIA_IO_ACCESS (165)
+#define SA1100_PCMCIA_5V_MEM_ACCESS (150)
+#define SA1100_PCMCIA_3V_MEM_ACCESS (300)
+
+
+/* The socket driver actually works nicely in interrupt-driven form,
+ * so the (relatively infrequent) polling is "just to be sure."
+ */
+#define SA1100_PCMCIA_POLL_PERIOD (2*HZ)
+
+
+/* This structure encapsulates per-socket state which we might need to
+ * use when responding to a Card Services query of some kind.
+ */
+struct sa1100_pcmcia_socket {
+ socket_state_t cs_state;
+ struct pcmcia_state k_state;
+ unsigned int irq;
+ void (*handler)(void *, unsigned int);
+ void *handler_info;
+ pccard_io_map io_map[MAX_IO_WIN];
+ pccard_mem_map mem_map[MAX_WIN];
+ ioaddr_t virt_io, phys_attr, phys_mem;
+ unsigned short speed_io, speed_attr, speed_mem;
+};
+
+
+/* I/O pins replacing memory pins
+ * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
+ *
+ * These signals change meaning when going from memory-only to
+ * memory-or-I/O interface:
+ */
+#define iostschg bvd1
+#define iospkr bvd2
+
+
+/*
+ * Declaration for all implementation specific low_level operations.
+ */
+extern struct pcmcia_low_level assabet_pcmcia_ops;
+extern struct pcmcia_low_level neponset_pcmcia_ops;
+extern struct pcmcia_low_level h3600_pcmcia_ops;
+extern struct pcmcia_low_level cerf_pcmcia_ops;
+extern struct pcmcia_low_level gcplus_pcmcia_ops;
+extern struct pcmcia_low_level xp860_pcmcia_ops;
+extern struct pcmcia_low_level yopy_pcmcia_ops;
+extern struct pcmcia_low_level pangolin_pcmcia_ops;
+extern struct pcmcia_low_level freebird_pcmcia_ops;
+extern struct pcmcia_low_level pfs168_pcmcia_ops;
+extern struct pcmcia_low_level jornada720_pcmcia_ops;
+extern struct pcmcia_low_level flexanet_pcmcia_ops;
+extern struct pcmcia_low_level simpad_pcmcia_ops;
+extern struct pcmcia_low_level graphicsmaster_pcmcia_ops;
+extern struct pcmcia_low_level adsbitsy_pcmcia_ops;
+extern struct pcmcia_low_level stork_pcmcia_ops;
+
+#endif /* !defined(_PCMCIA_SA1100_H) */
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_adsbitsy.c
+ *
+ * PCMCIA implementation routines for ADS Bitsy
+ *
+ * 9/18/01 Woojung
+ * Fixed wrong PCMCIA voltage setting
+ *
+ * 7/5/01 Woojung Huh <whuh@applieddata.net>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
+{
+ int return_val=0;
+
+ /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+
+ /* Disable Power 3.3V/5V for PCMCIA/CF */
+ PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
+
+ INTPOL1 |= (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
+
+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
+ "GC Master PCMCIA (0) CD", NULL);
+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
+ "GC Master CF (1) CD", NULL);
+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "GC Master PCMCIA (0) BVD1", NULL);
+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "GC Master CF (1) BVD1", NULL);
+
+ MECR = 0x09430943;
+
+ return (return_val<0) ? -1 : 2;
+}
+
+static int adsbitsy_pcmcia_shutdown(void)
+{
+
+ free_irq(S0_CD_VALID, NULL);
+ free_irq(S1_CD_VALID, NULL);
+ free_irq(S0_BVD1_STSCHG, NULL);
+ free_irq(S1_BVD1_STSCHG, NULL);
+
+ INTPOL1 &= ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
+
+ return 0;
+}
+
+static int adsbitsy_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+ unsigned long status;
+ int return_val=1;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ status=PCSR;
+
+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
+
+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
+
+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
+
+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
+
+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+
+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
+
+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
+
+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
+
+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
+
+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
+
+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
+
+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
+
+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
+
+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
+
+ return return_val;
+}
+
+static int adsbitsy_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+
+ switch(info->sock){
+ case 0:
+ info->irq=S0_READY_NINT;
+ break;
+
+ case 1:
+ info->irq=S1_READY_NINT;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *configure)
+{
+ unsigned long pccr=PCCR, gpio=PA_DWR;
+
+ switch(configure->sock){
+ case 0:
+
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S0_FLT);
+ gpio |= GPIO_GPIO0 | GPIO_GPIO1;
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
+ gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
+ gpio &= ~GPIO_GPIO0;
+ break;
+
+ case 50:
+ pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
+ gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
+ gpio |= GPIO_GPIO0;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
+
+ break;
+
+ case 1:
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S1_FLT);
+ gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
+ gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
+ gpio |= GPIO_GPIO2;
+ break;
+
+ case 50:
+ pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
+ gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
+ gpio |= GPIO_GPIO3;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ if(configure->vpp!=configure->vcc && configure->vpp!=0){
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
+
+ break;
+
+ default:
+ return -1;
+ }
+
+ PCCR = pccr;
+ PA_DWR = gpio;
+
+ return 0;
+}
+
+struct pcmcia_low_level adsbitsy_pcmcia_ops = {
+ adsbitsy_pcmcia_init,
+ adsbitsy_pcmcia_shutdown,
+ adsbitsy_pcmcia_socket_state,
+ adsbitsy_pcmcia_get_irq_info,
+ adsbitsy_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_assabet.c
+ *
+ * PCMCIA implementation routines for Assabet
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+
+static int assabet_pcmcia_init(struct pcmcia_init *init){
+ int irq, res;
+
+ /* Enable CF bus: */
+ BCR_clear(BCR_CF_BUS_OFF);
+
+ /* All those are inputs */
+ GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IRQ);
+
+ /* Set transition detect */
+ set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1, GPIO_BOTH_EDGES );
+ set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+
+ /* Register interrupts */
+ irq = IRQ_GPIO_CF_CD;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
+ if( res < 0 ) goto irq_err;
+ irq = IRQ_GPIO_CF_BVD2;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL );
+ if( res < 0 ) goto irq_err;
+ irq = IRQ_GPIO_CF_BVD1;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
+ if( res < 0 ) goto irq_err;
+
+ /* There's only one slot, but it's "Slot 1": */
+ return 2;
+
+irq_err:
+ printk( KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__, irq );
+ return -1;
+}
+
+static int assabet_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( IRQ_GPIO_CF_CD, NULL );
+ free_irq( IRQ_GPIO_CF_BVD2, NULL );
+ free_irq( IRQ_GPIO_CF_BVD1, NULL );
+
+ /* Disable CF bus: */
+ BCR_set(BCR_CF_BUS_OFF);
+
+ return 0;
+}
+
+static int assabet_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long levels;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels=GPLR;
+
+ state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
+
+ state_array->state[1].ready=(levels & GPIO_CF_IRQ)?1:0;
+
+ state_array->state[1].bvd1=(levels & GPIO_CF_BVD1)?1:0;
+
+ state_array->state[1].bvd2=(levels & GPIO_CF_BVD2)?1:0;
+
+ state_array->state[1].wrprot=0; /* Not available on Assabet. */
+
+ state_array->state[1].vs_3v=1; /* Can only apply 3.3V on Assabet. */
+
+ state_array->state[1].vs_Xv=0;
+
+ return 1;
+}
+
+static int assabet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ if(info->sock>1) return -1;
+
+ if(info->sock==1)
+ info->irq=IRQ_GPIO_CF_IRQ;
+
+ return 0;
+}
+
+static int assabet_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long value, flags;
+
+ if(configure->sock>1) return -1;
+
+ if(configure->sock==0) return 0;
+
+ save_flags_cli(flags);
+
+ value = BCR_value;
+
+ switch(configure->vcc){
+ case 0:
+ value &= ~BCR_CF_PWR;
+ break;
+
+ case 50:
+ printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
+ __FUNCTION__);
+
+ case 33: /* Can only apply 3.3V to the CF slot. */
+ value |= BCR_CF_PWR;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+
+ value = (configure->reset) ? (value | BCR_CF_RST) : (value & ~BCR_CF_RST);
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+ BCR = BCR_value = value;
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+struct pcmcia_low_level assabet_pcmcia_ops = {
+ assabet_pcmcia_init,
+ assabet_pcmcia_shutdown,
+ assabet_pcmcia_socket_state,
+ assabet_pcmcia_get_irq_info,
+ assabet_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_cerf.c
+ *
+ * PCMCIA implementation routines for CerfBoard
+ * Based off the Assabet.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+
+static int cerf_pcmcia_init(struct pcmcia_init *init){
+ int irq, res;
+
+ /* Enable CF bus: */
+// BCR_clear(BCR_CF_BUS_OFF);
+
+ /* All those are inputs */
+ GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IRQ);
+
+ /* Set transition detect */
+ set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1, GPIO_BOTH_EDGES );
+ set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+
+ /* Register interrupts */
+ irq = IRQ_GPIO_CF_CD;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
+ if( res < 0 ) goto irq_err;
+ irq = IRQ_GPIO_CF_BVD2;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL );
+ if( res < 0 ) goto irq_err;
+ irq = IRQ_GPIO_CF_BVD1;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
+ if( res < 0 ) goto irq_err;
+
+ /* There's only one slot, but it's "Slot 1": */
+ return 2;
+
+irq_err:
+ printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
+ return -1;
+}
+
+static int cerf_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( IRQ_GPIO_CF_CD, NULL );
+ free_irq( IRQ_GPIO_CF_BVD2, NULL );
+ free_irq( IRQ_GPIO_CF_BVD1, NULL );
+
+ /* Disable CF bus: */
+// BCR_set(BCR_CF_BUS_OFF);
+
+ return 0;
+}
+
+static int cerf_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long levels;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels=GPLR;
+
+ state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
+
+ state_array->state[1].ready=(levels & GPIO_CF_IRQ)?1:0;
+
+ state_array->state[1].bvd1=(levels & GPIO_CF_BVD1)?1:0;
+
+ state_array->state[1].bvd2=(levels & GPIO_CF_BVD2)?1:0;
+
+ state_array->state[1].wrprot=0; /* Not available on Assabet. */
+
+ state_array->state[1].vs_3v=1; /* Can only apply 3.3V on Assabet. */
+
+ state_array->state[1].vs_Xv=0;
+
+ return 1;
+}
+
+static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ if(info->sock>1) return -1;
+
+ if(info->sock==1)
+ info->irq=IRQ_GPIO_CF_IRQ;
+
+ return 0;
+}
+
+static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long value, flags;
+
+ if(configure->sock>1) return -1;
+
+ if(configure->sock==0) return 0;
+
+ save_flags_cli(flags);
+
+// value = BCR_value;
+
+ switch(configure->vcc){
+ case 0:
+// value &= ~BCR_CF_PWR;
+ break;
+
+ case 50:
+ printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
+ __FUNCTION__);
+
+ case 33: /* Can only apply 3.3V to the CF slot. */
+// value |= BCR_CF_PWR;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+
+// value = (configure->reset) ? (value | BCR_CF_RST) : (value & ~BCR_CF_RST);
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+// BCR = BCR_value = value;
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+struct pcmcia_low_level cerf_pcmcia_ops = {
+ cerf_pcmcia_init,
+ cerf_pcmcia_shutdown,
+ cerf_pcmcia_socket_state,
+ cerf_pcmcia_get_irq_info,
+ cerf_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_flexanet.c
+ *
+ * PCMCIA implementation routines for Flexanet.
+ * by Jordi Colomer, 09/05/2001
+ *
+ * Yet to be defined.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+
+/*
+ * Socket initialization.
+ *
+ * Called by sa1100_pcmcia_driver_init on startup.
+ * Must return the number of slots.
+ *
+ */
+static int flexanet_pcmcia_init(struct pcmcia_init *init){
+
+ return 0;
+}
+
+
+/*
+ * Socket shutdown
+ *
+ */
+static int flexanet_pcmcia_shutdown(void)
+{
+ return 0;
+}
+
+
+/*
+ * Get the state of the sockets.
+ *
+ * Sockets in Flexanet are 3.3V only, without BVD2.
+ *
+ */
+static int flexanet_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ return -1;
+}
+
+
+/*
+ * Return the IRQ information for a given socket number (the IRQ number)
+ *
+ */
+static int flexanet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ return -1;
+}
+
+
+/*
+ *
+ */
+static int flexanet_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ return -1;
+}
+
+
+/*
+ * The set of socket operations
+ *
+ */
+struct pcmcia_low_level flexanet_pcmcia_ops = {
+ flexanet_pcmcia_init,
+ flexanet_pcmcia_shutdown,
+ flexanet_pcmcia_socket_state,
+ flexanet_pcmcia_get_irq_info,
+ flexanet_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_freebird.c
+ *
+ * Created by Eric Peng <ericpeng@coventive.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+
+static int freebird_pcmcia_init(struct pcmcia_init *init){
+ int irq, res;
+
+ /* Enable Linkup CF card */
+ LINKUP_PRC = 0xc0;
+ mdelay(100);
+ LINKUP_PRC = 0xc1;
+ mdelay(100);
+ LINKUP_PRC = 0xd1;
+ mdelay(100);
+ LINKUP_PRC = 0xd1;
+ mdelay(100);
+ LINKUP_PRC = 0xc0;
+
+ /* All those are inputs */
+ ////GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IRQ);
+ GPDR &= ~(GPIO_FREEBIRD_CF_CD | GPIO_FREEBIRD_CF_IRQ | GPIO_FREEBIRD_CF_BVD);
+
+ /* Set transition detect */
+ //set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1, GPIO_BOTH_EDGES );
+ //set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+ set_GPIO_IRQ_edge(GPIO_FREEBIRD_CF_CD|GPIO_FREEBIRD_CF_BVD,GPIO_BOTH_EDGES);
+ set_GPIO_IRQ_edge(GPIO_FREEBIRD_CF_IRQ, GPIO_FALLING_EDGE);
+
+ /* Register interrupts */
+ irq = IRQ_GPIO_FREEBIRD_CF_CD;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
+ if( res < 0 ) goto irq_err;
+ irq = IRQ_GPIO_FREEBIRD_CF_BVD;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
+ if( res < 0 ) goto irq_err;
+
+ /* There's only one slot, but it's "Slot 1": */
+ return 2;
+
+irq_err:
+ printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
+ return -1;
+}
+
+static int freebird_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( IRQ_GPIO_FREEBIRD_CF_CD, NULL );
+ free_irq( IRQ_GPIO_FREEBIRD_CF_BVD, NULL );
+
+ /* Disable CF card */
+ LINKUP_PRC = 0x40; /* SSP=1 SOE=0 */
+ mdelay(100);
+
+ return 0;
+}
+
+static int freebird_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long levels;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels = LINKUP_PRS;
+//printk("LINKUP_PRS=%x \n",levels);
+
+ state_array->state[0].detect=
+ ((levels & (LINKUP_CD1 | LINKUP_CD2))==0)?1:0;
+
+ state_array->state[0].ready=(levels & LINKUP_RDY)?1:0;
+
+ state_array->state[0].bvd1=(levels & LINKUP_BVD1)?1:0;
+
+ state_array->state[0].bvd2=(levels & LINKUP_BVD2)?1:0;
+
+ state_array->state[0].wrprot=0; /* Not available on Assabet. */
+
+ state_array->state[0].vs_3v=1; /* Can only apply 3.3V on Assabet. */
+
+ state_array->state[0].vs_Xv=0;
+
+ return 1;
+}
+
+static int freebird_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ if(info->sock>1) return -1;
+
+ if(info->sock==0)
+ info->irq=IRQ_GPIO_FREEBIRD_CF_IRQ;
+
+ return 0;
+}
+
+static int freebird_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long value, flags;
+
+ if(configure->sock>1) return -1;
+
+ if(configure->sock==1) return 0;
+
+ save_flags_cli(flags);
+
+ value = 0xc0; /* SSP=1 SOE=1 CFE=1 */
+
+ switch(configure->vcc){
+ case 0:
+
+ break;
+
+ case 50:
+ printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
+ __FUNCTION__);
+
+ case 33: /* Can only apply 3.3V to the CF slot. */
+ value |= LINKUP_S1;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+
+ if (configure->reset)
+ value = (configure->reset) ? (value | LINKUP_RESET) : (value & ~LINKUP_RESET);
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+ LINKUP_PRC = value;
+//printk("LINKUP_PRC=%x\n",value);
+ restore_flags(flags);
+
+ return 0;
+}
+
+struct pcmcia_low_level freebird_pcmcia_ops = {
+ freebird_pcmcia_init,
+ freebird_pcmcia_shutdown,
+ freebird_pcmcia_socket_state,
+ freebird_pcmcia_get_irq_info,
+ freebird_pcmcia_configure_socket
+};
+
--- /dev/null
+/*======================================================================
+
+ Device driver for the PCMCIA control functionality of StrongARM
+ SA-1100 microprocessors.
+
+ The contents of this file are subject to the Mozilla Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ The initial developer of the original code is John G. Dorsey
+ <john+@cs.cmu.edu>. Portions created by John G. Dorsey are
+ Copyright (C) 1999 John G. Dorsey. All Rights Reserved.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the GNU Public License version 2 (the "GPL"), in which
+ case the provisions of the GPL are applicable instead of the
+ above. If you wish to allow the use of your version of this file
+ only under the terms of the GPL and not to allow others to use
+ your version of this file under the MPL, indicate your decision
+ by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL. If you do not delete
+ the provisions above, a recipient may use your version of this
+ file under either the MPL or the GPL.
+
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/tqueue.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+#include <linux/proc_fs.h>
+#include <linux/version.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bus_ops.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "sa1100.h"
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug;
+#endif
+
+MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-1100 Socket Controller");
+
+/* This structure maintains housekeeping state for each socket, such
+ * as the last known values of the card detect pins, or the Card Services
+ * callback value associated with the socket:
+ */
+static struct sa1100_pcmcia_socket
+sa1100_pcmcia_socket[SA1100_PCMCIA_MAX_SOCK];
+
+static int sa1100_pcmcia_socket_count;
+
+
+/* Returned by the low-level PCMCIA interface: */
+static struct pcmcia_low_level *pcmcia_low_level;
+
+/* Event poll timer structure */
+static struct timer_list poll_timer;
+
+
+/* Prototypes for routines which are used internally: */
+
+static int sa1100_pcmcia_driver_init(void);
+static void sa1100_pcmcia_driver_shutdown(void);
+static void sa1100_pcmcia_task_handler(void *data);
+static void sa1100_pcmcia_poll_event(unsigned long data);
+static void sa1100_pcmcia_interrupt(int irq, void *dev,
+ struct pt_regs *regs);
+static struct tq_struct sa1100_pcmcia_task;
+
+#ifdef CONFIG_PROC_FS
+static int sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
+ int count, int *eof, void *data);
+#endif
+
+
+/* Prototypes for operations which are exported to the
+ * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core:
+ */
+
+static int sa1100_pcmcia_init(unsigned int sock);
+static int sa1100_pcmcia_suspend(unsigned int sock);
+static int sa1100_pcmcia_register_callback(unsigned int sock,
+ void (*handler)(void *,
+ unsigned int),
+ void *info);
+static int sa1100_pcmcia_inquire_socket(unsigned int sock,
+ socket_cap_t *cap);
+static int sa1100_pcmcia_get_status(unsigned int sock, u_int *value);
+static int sa1100_pcmcia_get_socket(unsigned int sock,
+ socket_state_t *state);
+static int sa1100_pcmcia_set_socket(unsigned int sock,
+ socket_state_t *state);
+static int sa1100_pcmcia_get_io_map(unsigned int sock,
+ struct pccard_io_map *io);
+static int sa1100_pcmcia_set_io_map(unsigned int sock,
+ struct pccard_io_map *io);
+static int sa1100_pcmcia_get_mem_map(unsigned int sock,
+ struct pccard_mem_map *mem);
+static int sa1100_pcmcia_set_mem_map(unsigned int sock,
+ struct pccard_mem_map *mem);
+#ifdef CONFIG_PROC_FS
+static void sa1100_pcmcia_proc_setup(unsigned int sock,
+ struct proc_dir_entry *base);
+#endif
+
+static struct pccard_operations sa1100_pcmcia_operations = {
+ sa1100_pcmcia_init,
+ sa1100_pcmcia_suspend,
+ sa1100_pcmcia_register_callback,
+ sa1100_pcmcia_inquire_socket,
+ sa1100_pcmcia_get_status,
+ sa1100_pcmcia_get_socket,
+ sa1100_pcmcia_set_socket,
+ sa1100_pcmcia_get_io_map,
+ sa1100_pcmcia_set_io_map,
+ sa1100_pcmcia_get_mem_map,
+ sa1100_pcmcia_set_mem_map,
+#ifdef CONFIG_PROC_FS
+ sa1100_pcmcia_proc_setup
+#endif
+};
+
+#ifdef CONFIG_CPU_FREQ
+/* forward declaration */
+static struct notifier_block sa1100_pcmcia_notifier_block;
+#endif
+
+
+/* sa1100_pcmcia_driver_init()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * This routine performs a basic sanity check to ensure that this
+ * kernel has been built with the appropriate board-specific low-level
+ * PCMCIA support, performs low-level PCMCIA initialization, registers
+ * this socket driver with Card Services, and then spawns the daemon
+ * thread which is the real workhorse of the socket driver.
+ *
+ * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
+ * on the low-level kernel interface.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int __init sa1100_pcmcia_driver_init(void){
+ servinfo_t info;
+ struct pcmcia_init pcmcia_init;
+ struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
+ struct pcmcia_state_array state_array;
+ unsigned int i, clock;
+ unsigned long mecr;
+
+ printk(KERN_INFO "SA-1100 PCMCIA (CS release %s)\n", CS_RELEASE);
+
+ CardServices(GetCardServicesInfo, &info);
+
+ if(info.Revision!=CS_RELEASE_CODE){
+ printk(KERN_ERR "Card Services release codes do not match\n");
+ return -1;
+ }
+
+ if(machine_is_assabet()){
+#ifdef CONFIG_SA1100_ASSABET
+ if(machine_has_neponset()){
+#ifdef CONFIG_ASSABET_NEPONSET
+ pcmcia_low_level=&neponset_pcmcia_ops;
+#else
+ printk(KERN_ERR "Card Services disabled: missing Neponset support\n");
+ return -1;
+#endif
+ }else{
+ pcmcia_low_level=&assabet_pcmcia_ops;
+ }
+#endif
+ } else if (machine_is_freebird()) {
+#ifdef CONFIG_SA1100_FREEBIRD
+ pcmcia_low_level = &freebird_pcmcia_ops;
+#endif
+ } else if (machine_is_h3600()) {
+#ifdef CONFIG_SA1100_H3600
+ pcmcia_low_level = &h3600_pcmcia_ops;
+#endif
+ } else if (machine_is_cerf()) {
+#ifdef CONFIG_SA1100_CERF
+ pcmcia_low_level = &cerf_pcmcia_ops;
+#endif
+ } else if (machine_is_graphicsclient()) {
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+ pcmcia_low_level = &gcplus_pcmcia_ops;
+#endif
+ } else if (machine_is_xp860()) {
+#ifdef CONFIG_SA1100_XP860
+ pcmcia_low_level = &xp860_pcmcia_ops;
+#endif
+ } else if (machine_is_yopy()) {
+#ifdef CONFIG_SA1100_YOPY
+ pcmcia_low_level = &yopy_pcmcia_ops;
+#endif
+ } else if (machine_is_pangolin()) {
+#ifdef CONFIG_SA1100_PANGOLIN
+ pcmcia_low_level = &pangolin_pcmcia_ops;
+#endif
+ } else if (machine_is_jornada720()) {
+#ifdef CONFIG_SA1100_JORNADA720
+ pcmcia_low_level = &jornada720_pcmcia_ops;
+#endif
+ } else if(machine_is_pfs168()){
+#ifdef CONFIG_SA1100_PFS168
+ pcmcia_low_level=&pfs168_pcmcia_ops;
+#endif
+ } else if(machine_is_flexanet()){
+#ifdef CONFIG_SA1100_FLEXANET
+ pcmcia_low_level=&flexanet_pcmcia_ops;
+#endif
+ } else if(machine_is_simpad()){
+#ifdef CONFIG_SA1100_SIMPAD
+ pcmcia_low_level=&simpad_pcmcia_ops;
+#endif
+ } else if(machine_is_graphicsmaster()) {
+#ifdef CONFIG_SA1100_GRAPHICSMASTER
+ pcmcia_low_level=&graphicsmaster_pcmcia_ops;
+#endif
+ } else if(machine_is_adsbitsy()) {
+#ifdef CONFIG_SA1100_ADSBITSY
+ pcmcia_low_level=&adsbitsy_pcmcia_ops;
+#endif
+ } else if(machine_is_stork()) {
+#ifdef CONFIG_SA1100_STORK
+ pcmcia_low_level=&stork_pcmcia_ops;
+#endif
+ }
+
+ if (!pcmcia_low_level) {
+ printk(KERN_ERR "This hardware is not supported by the SA1100 Card Service driver\n");
+ return -ENODEV;
+ }
+
+ pcmcia_init.handler=sa1100_pcmcia_interrupt;
+
+ if((sa1100_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){
+ printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n");
+ return -EIO;
+ }
+
+ state_array.size=sa1100_pcmcia_socket_count;
+ state_array.state=state;
+
+ if(pcmcia_low_level->socket_state(&state_array)<0){
+ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
+ return -EIO;
+ }
+
+ /* We initialize the MECR to default values here, because we are
+ * not guaranteed to see a SetIOMap operation at runtime.
+ */
+ mecr=0;
+
+ clock = get_cclk_frequency() * 100;
+
+ for(i=0; i<sa1100_pcmcia_socket_count; ++i){
+ sa1100_pcmcia_socket[i].k_state=state[i];
+
+ /* This is an interim fix. Apparently, SetSocket is no longer
+ * called to initialize each socket (prior to the first detect
+ * event). For now, we'll just manually set up the mask.
+ */
+ sa1100_pcmcia_socket[i].cs_state.csc_mask=SS_DETECT;
+
+ sa1100_pcmcia_socket[i].virt_io=(i==0)?PCMCIA_IO_0_BASE:PCMCIA_IO_1_BASE;
+ sa1100_pcmcia_socket[i].phys_attr=_PCMCIAAttr(i);
+ sa1100_pcmcia_socket[i].phys_mem=_PCMCIAMem(i);
+
+ MECR_FAST_SET(mecr, i, 0);
+ MECR_BSIO_SET(mecr, i,
+ sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_IO_ACCESS, clock));
+ MECR_BSA_SET(mecr, i,
+ sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_5V_MEM_ACCESS, clock));
+ MECR_BSM_SET(mecr, i,
+ sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_5V_MEM_ACCESS, clock));
+
+ sa1100_pcmcia_socket[i].speed_io=SA1100_PCMCIA_IO_ACCESS;
+ sa1100_pcmcia_socket[i].speed_attr=SA1100_PCMCIA_5V_MEM_ACCESS;
+ sa1100_pcmcia_socket[i].speed_mem=SA1100_PCMCIA_5V_MEM_ACCESS;
+ }
+
+ MECR=mecr;
+
+#ifdef CONFIG_CPU_FREQ
+ if(cpufreq_register_notifier(&sa1100_pcmcia_notifier_block) < 0){
+ printk(KERN_ERR "Unable to register CPU frequency change notifier\n");
+ return -ENXIO;
+ }
+#endif
+
+ /* Only advertise as many sockets as we can detect: */
+ if(register_ss_entry(sa1100_pcmcia_socket_count,
+ &sa1100_pcmcia_operations)<0){
+ printk(KERN_ERR "Unable to register socket service routine\n");
+ return -ENXIO;
+ }
+
+ /* Start the event poll timer. It will reschedule by itself afterwards. */
+ sa1100_pcmcia_poll_event(0);
+
+ DEBUG(1, "sa1100: initialization complete\n");
+
+ return 0;
+
+} /* sa1100_pcmcia_driver_init() */
+
+module_init(sa1100_pcmcia_driver_init);
+
+
+/* sa1100_pcmcia_driver_shutdown()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Invokes the low-level kernel service to free IRQs associated with this
+ * socket controller and reset GPIO edge detection.
+ */
+static void __exit sa1100_pcmcia_driver_shutdown(void){
+
+ del_timer_sync(&poll_timer);
+ unregister_ss_entry(&sa1100_pcmcia_operations);
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block);
+#endif
+ pcmcia_low_level->shutdown();
+ flush_scheduled_tasks();
+
+ DEBUG(1, "sa1100: shutdown complete\n");
+}
+
+module_exit(sa1100_pcmcia_driver_shutdown);
+
+
+/* sa1100_pcmcia_init()
+ * ^^^^^^^^^^^^^^^^^^^^
+ * We perform all of the interesting initialization tasks in
+ * sa1100_pcmcia_driver_init().
+ *
+ * Returns: 0
+ */
+static int sa1100_pcmcia_init(unsigned int sock){
+
+ DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock);
+
+ return 0;
+}
+
+
+/* sa1100_pcmcia_suspend()
+ * ^^^^^^^^^^^^^^^^^^^^^^^
+ * We don't currently perform any actions on a suspend.
+ *
+ * Returns: 0
+ */
+static int sa1100_pcmcia_suspend(unsigned int sock){
+
+ DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, sock);
+
+ return 0;
+}
+
+
+/* sa1100_pcmcia_events()
+ * ^^^^^^^^^^^^^^^^^^^^^^
+ * Helper routine to generate a Card Services event mask based on
+ * state information obtained from the kernel low-level PCMCIA layer
+ * in a recent (and previous) sampling. Updates `prev_state'.
+ *
+ * Returns: an event mask for the given socket state.
+ */
+static inline unsigned sa1100_pcmcia_events(struct pcmcia_state *state,
+ struct pcmcia_state *prev_state,
+ unsigned int mask,
+ unsigned int flags){
+ unsigned int events=0;
+
+ if(state->detect!=prev_state->detect){
+
+ DEBUG(2, "%s(): card detect value %u\n", __FUNCTION__, state->detect);
+
+ events|=mask&SS_DETECT;
+ }
+
+ if(state->ready!=prev_state->ready){
+
+ DEBUG(2, "%s(): card ready value %u\n", __FUNCTION__, state->ready);
+
+ events|=mask&((flags&SS_IOCARD)?0:SS_READY);
+ }
+
+ if(state->bvd1!=prev_state->bvd1){
+
+ DEBUG(2, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1);
+
+ events|=mask&(flags&SS_IOCARD)?SS_STSCHG:SS_BATDEAD;
+ }
+
+ if(state->bvd2!=prev_state->bvd2){
+
+ DEBUG(2, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2);
+
+ events|=mask&(flags&SS_IOCARD)?0:SS_BATWARN;
+ }
+
+ DEBUG(2, "events: %s%s%s%s%s%s\n",
+ (events==0)?"<NONE>":"",
+ (events&SS_DETECT)?"DETECT ":"",
+ (events&SS_READY)?"READY ":"",
+ (events&SS_BATDEAD)?"BATDEAD ":"",
+ (events&SS_BATWARN)?"BATWARN ":"",
+ (events&SS_STSCHG)?"STSCHG ":"");
+
+ *prev_state=*state;
+
+ return events;
+
+} /* sa1100_pcmcia_events() */
+
+
+/* sa1100_pcmcia_task_handler()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Processes serviceable socket events using the "eventd" thread context.
+ *
+ * Event processing (specifically, the invocation of the Card Services event
+ * callback) occurs in this thread rather than in the actual interrupt
+ * handler due to the use of scheduling operations in the PCMCIA core.
+ */
+static void sa1100_pcmcia_task_handler(void *data) {
+ struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
+ struct pcmcia_state_array state_array;
+ int i, events, all_events, irq_status;
+
+ DEBUG(2, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
+
+ state_array.size=sa1100_pcmcia_socket_count;
+ state_array.state=state;
+
+ do {
+
+ DEBUG(3, "%s(): interrogating low-level PCMCIA service\n", __FUNCTION__);
+
+ if((irq_status=pcmcia_low_level->socket_state(&state_array))<0)
+ printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n");
+
+ all_events=0;
+
+ if(irq_status>0){
+
+ for(i=0; i<state_array.size; ++i, all_events|=events)
+ if((events=
+ sa1100_pcmcia_events(&state[i],
+ &sa1100_pcmcia_socket[i].k_state,
+ sa1100_pcmcia_socket[i].cs_state.csc_mask,
+ sa1100_pcmcia_socket[i].cs_state.flags)))
+ if(sa1100_pcmcia_socket[i].handler!=NULL)
+ sa1100_pcmcia_socket[i].handler(sa1100_pcmcia_socket[i].handler_info,
+ events);
+ }
+
+ } while(all_events);
+} /* sa1100_pcmcia_task_handler() */
+
+static struct tq_struct sa1100_pcmcia_task = {
+ routine: sa1100_pcmcia_task_handler
+};
+
+
+/* sa1100_pcmcia_poll_event()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Let's poll for events in addition to IRQs since IRQ only is unreliable...
+ */
+static void sa1100_pcmcia_poll_event(unsigned long dummy)
+{
+ DEBUG(3, "%s(): polling for events\n", __FUNCTION__);
+ poll_timer.function = sa1100_pcmcia_poll_event;
+ poll_timer.expires = jiffies + SA1100_PCMCIA_POLL_PERIOD;
+ add_timer(&poll_timer);
+ schedule_task(&sa1100_pcmcia_task);
+}
+
+
+/* sa1100_pcmcia_interrupt()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Service routine for socket driver interrupts (requested by the
+ * low-level PCMCIA init() operation via sa1100_pcmcia_thread()).
+ * The actual interrupt-servicing work is performed by
+ * sa1100_pcmcia_thread(), largely because the Card Services event-
+ * handling code performs scheduling operations which cannot be
+ * executed from within an interrupt context.
+ */
+static void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs){
+ DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
+ schedule_task(&sa1100_pcmcia_task);
+}
+
+
+/* sa1100_pcmcia_register_callback()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the register_callback() operation for the in-kernel
+ * PCMCIA service (formerly SS_RegisterCallback in Card Services). If
+ * the function pointer `handler' is not NULL, remember the callback
+ * location in the state for `sock', and increment the usage counter
+ * for the driver module. (The callback is invoked from the interrupt
+ * service routine, sa1100_pcmcia_interrupt(), to notify Card Services
+ * of interesting events.) Otherwise, clear the callback pointer in the
+ * socket state and decrement the module usage count.
+ *
+ * Returns: 0
+ */
+static int sa1100_pcmcia_register_callback(unsigned int sock,
+ void (*handler)(void *,
+ unsigned int),
+ void *info){
+ if(handler==NULL){
+ sa1100_pcmcia_socket[sock].handler=NULL;
+ MOD_DEC_USE_COUNT;
+ } else {
+ MOD_INC_USE_COUNT;
+ sa1100_pcmcia_socket[sock].handler=handler;
+ sa1100_pcmcia_socket[sock].handler_info=info;
+ }
+
+ return 0;
+}
+
+
+/* sa1100_pcmcia_inquire_socket()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the inquire_socket() operation for the in-kernel PCMCIA
+ * service (formerly SS_InquireSocket in Card Services). Of note is
+ * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of
+ * `cap' to "trick" Card Services into tolerating large "I/O memory"
+ * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory
+ * resource database check. (Mapped memory is set up within the socket
+ * driver itself.)
+ *
+ * In conjunction with the STATIC_MAP capability is a new field,
+ * `io_offset', recommended by David Hinds. Rather than go through
+ * the SetIOMap interface (which is not quite suited for communicating
+ * window locations up from the socket driver), we just pass up
+ * an offset which is applied to client-requested base I/O addresses
+ * in alloc_io_space().
+ *
+ * Returns: 0 on success, -1 if no pin has been configured for `sock'
+ */
+static int sa1100_pcmcia_inquire_socket(unsigned int sock,
+ socket_cap_t *cap){
+ struct pcmcia_irq_info irq_info;
+
+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ if(sock>=sa1100_pcmcia_socket_count){
+ printk(KERN_ERR "sa1100: socket %u not configured\n", sock);
+ return -1;
+ }
+
+ /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
+ * force_low argument to validate_mem() in rsrc_mgr.c -- since in
+ * general, the mapped * addresses of the PCMCIA memory regions
+ * will not be within 0xffff, setting force_low would be
+ * undesirable.
+ *
+ * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
+ * resource database; we instead pass up physical address ranges
+ * and allow other parts of Card Services to deal with remapping.
+ *
+ * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
+ * not 32-bit CardBus devices.
+ */
+ cap->features=(SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD);
+
+ irq_info.sock=sock;
+ irq_info.irq=-1;
+
+ if(pcmcia_low_level->get_irq_info(&irq_info)<0){
+ printk(KERN_ERR "Error obtaining IRQ info from kernel for socket %u\n",
+ sock);
+ return -1;
+ }
+
+ cap->irq_mask=0;
+ cap->map_size=PAGE_SIZE;
+ cap->pci_irq=irq_info.irq;
+ cap->io_offset=sa1100_pcmcia_socket[sock].virt_io;
+
+ return 0;
+
+} /* sa1100_pcmcia_inquire_socket() */
+
+
+/* sa1100_pcmcia_get_status()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_status() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetStatus in Card Services). Essentially just
+ * fills in bits in `status' according to internal driver state or
+ * the value of the voltage detect chipselect register.
+ *
+ * As a debugging note, during card startup, the PCMCIA core issues
+ * three set_socket() commands in a row the first with RESET deasserted,
+ * the second with RESET asserted, and the last with RESET deasserted
+ * again. Following the third set_socket(), a get_status() command will
+ * be issued. The kernel is looking for the SS_READY flag (see
+ * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
+ *
+ * Returns: 0
+ */
+static int sa1100_pcmcia_get_status(unsigned int sock,
+ unsigned int *status){
+ struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
+ struct pcmcia_state_array state_array;
+
+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ state_array.size=sa1100_pcmcia_socket_count;
+ state_array.state=state;
+
+ if((pcmcia_low_level->socket_state(&state_array))<0){
+ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
+ return -1;
+ }
+
+ sa1100_pcmcia_socket[sock].k_state=state[sock];
+
+ *status=state[sock].detect?SS_DETECT:0;
+
+ *status|=state[sock].ready?SS_READY:0;
+
+ /* The power status of individual sockets is not available
+ * explicitly from the hardware, so we just remember the state
+ * and regurgitate it upon request:
+ */
+ *status|=sa1100_pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0;
+
+ if(sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)
+ *status|=state[sock].bvd1?SS_STSCHG:0;
+ else {
+ if(state[sock].bvd1==0)
+ *status|=SS_BATDEAD;
+ else if(state[sock].bvd2==0)
+ *status|=SS_BATWARN;
+ }
+
+ *status|=state[sock].vs_3v?SS_3VCARD:0;
+
+ *status|=state[sock].vs_Xv?SS_XVCARD:0;
+
+ DEBUG(3, "\tstatus: %s%s%s%s%s%s%s%s\n",
+ (*status&SS_DETECT)?"DETECT ":"",
+ (*status&SS_READY)?"READY ":"",
+ (*status&SS_BATDEAD)?"BATDEAD ":"",
+ (*status&SS_BATWARN)?"BATWARN ":"",
+ (*status&SS_POWERON)?"POWERON ":"",
+ (*status&SS_STSCHG)?"STSCHG ":"",
+ (*status&SS_3VCARD)?"3VCARD ":"",
+ (*status&SS_XVCARD)?"XVCARD ":"");
+
+ return 0;
+
+} /* sa1100_pcmcia_get_status() */
+
+
+/* sa1100_pcmcia_get_socket()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_socket() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetSocket in Card Services). Not a very
+ * exciting routine.
+ *
+ * Returns: 0
+ */
+static int sa1100_pcmcia_get_socket(unsigned int sock,
+ socket_state_t *state){
+
+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ /* This information was given to us in an earlier call to set_socket(),
+ * so we're just regurgitating it here:
+ */
+ *state=sa1100_pcmcia_socket[sock].cs_state;
+
+ return 0;
+}
+
+
+/* sa1100_pcmcia_set_socket()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the set_socket() operation for the in-kernel PCMCIA
+ * service (formerly SS_SetSocket in Card Services). We more or
+ * less punt all of this work and let the kernel handle the details
+ * of power configuration, reset, &c. We also record the value of
+ * `state' in order to regurgitate it to the PCMCIA core later.
+ *
+ * Returns: 0
+ */
+static int sa1100_pcmcia_set_socket(unsigned int sock,
+ socket_state_t *state){
+ struct pcmcia_configure configure;
+
+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ DEBUG(3, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
+ "\tVcc %d Vpp %d irq %d\n",
+ (state->csc_mask==0)?"<NONE>":"",
+ (state->csc_mask&SS_DETECT)?"DETECT ":"",
+ (state->csc_mask&SS_READY)?"READY ":"",
+ (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
+ (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
+ (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
+ (state->flags==0)?"<NONE>":"",
+ (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
+ (state->flags&SS_IOCARD)?"IOCARD ":"",
+ (state->flags&SS_RESET)?"RESET ":"",
+ (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
+ (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+ state->Vcc, state->Vpp, state->io_irq);
+
+ configure.sock=sock;
+ configure.vcc=state->Vcc;
+ configure.vpp=state->Vpp;
+ configure.output=(state->flags&SS_OUTPUT_ENA)?1:0;
+ configure.speaker=(state->flags&SS_SPKR_ENA)?1:0;
+ configure.reset=(state->flags&SS_RESET)?1:0;
+
+ if(pcmcia_low_level->configure_socket(&configure)<0){
+ printk(KERN_ERR "Unable to configure socket %u\n", sock);
+ return -1;
+ }
+
+ sa1100_pcmcia_socket[sock].cs_state=*state;
+
+ return 0;
+
+} /* sa1100_pcmcia_set_socket() */
+
+
+/* sa1100_pcmcia_get_io_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_io_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetIOMap in Card Services). Just returns an
+ * I/O map descriptor which was assigned earlier by a set_io_map().
+ *
+ * Returns: 0 on success, -1 if the map index was out of range
+ */
+static int sa1100_pcmcia_get_io_map(unsigned int sock,
+ struct pccard_io_map *map){
+
+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ if(map->map>=MAX_IO_WIN){
+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+ map->map);
+ return -1;
+ }
+
+ *map=sa1100_pcmcia_socket[sock].io_map[map->map];
+
+ return 0;
+}
+
+
+/* sa1100_pcmcia_set_io_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the set_io_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_SetIOMap in Card Services). We configure
+ * the map speed as requested, but override the address ranges
+ * supplied by Card Services.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int sa1100_pcmcia_set_io_map(unsigned int sock,
+ struct pccard_io_map *map){
+ unsigned int clock, speed;
+ unsigned long mecr, start;
+
+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ DEBUG(4, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n"
+ "\tflags: %s%s%s%s%s%s%s%s\n",
+ map->map, map->speed, map->start, map->stop,
+ (map->flags==0)?"<NONE>":"",
+ (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
+ (map->flags&MAP_16BIT)?"16BIT ":"",
+ (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
+ (map->flags&MAP_0WS)?"0WS ":"",
+ (map->flags&MAP_WRPROT)?"WRPROT ":"",
+ (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
+ (map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+
+ if(map->map>=MAX_IO_WIN){
+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+ map->map);
+ return -1;
+ }
+
+ if(map->flags&MAP_ACTIVE){
+
+ speed=(map->speed>0)?map->speed:SA1100_PCMCIA_IO_ACCESS;
+
+ clock = get_cclk_frequency() * 100;
+
+ mecr=MECR;
+
+ MECR_BSIO_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
+
+ sa1100_pcmcia_socket[sock].speed_io=speed;
+
+ DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
+ __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
+ MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
+ sock, MECR_BSIO_GET(mecr, sock));
+
+ MECR=mecr;
+
+ }
+
+ start=map->start;
+
+ if(map->stop==1)
+ map->stop=PAGE_SIZE-1;
+
+ map->start=sa1100_pcmcia_socket[sock].virt_io;
+ map->stop=map->start+(map->stop-start);
+
+ sa1100_pcmcia_socket[sock].io_map[map->map]=*map;
+
+ return 0;
+
+} /* sa1100_pcmcia_set_io_map() */
+
+
+/* sa1100_pcmcia_get_mem_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the get_mem_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_GetMemMap in Card Services). Just returns a
+ * memory map descriptor which was assigned earlier by a
+ * set_mem_map() request.
+ *
+ * Returns: 0 on success, -1 if the map index was out of range
+ */
+static int sa1100_pcmcia_get_mem_map(unsigned int sock,
+ struct pccard_mem_map *map){
+
+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ if(map->map>=MAX_WIN){
+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+ map->map);
+ return -1;
+ }
+
+ *map=sa1100_pcmcia_socket[sock].mem_map[map->map];
+
+ return 0;
+}
+
+
+/* sa1100_pcmcia_set_mem_map()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the set_mem_map() operation for the in-kernel PCMCIA
+ * service (formerly SS_SetMemMap in Card Services). We configure
+ * the map speed as requested, but override the address ranges
+ * supplied by Card Services.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int sa1100_pcmcia_set_mem_map(unsigned int sock,
+ struct pccard_mem_map *map){
+ unsigned int clock, speed;
+ unsigned long mecr, start;
+
+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ DEBUG(4, "\tmap %u speed %u\n\tsys_start %#lx\n"
+ "\tsys_stop %#lx\n\tcard_start %#x\n"
+ "\tflags: %s%s%s%s%s%s%s%s\n",
+ map->map, map->speed, map->sys_start, map->sys_stop,
+ map->card_start, (map->flags==0)?"<NONE>":"",
+ (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
+ (map->flags&MAP_16BIT)?"16BIT ":"",
+ (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
+ (map->flags&MAP_0WS)?"0WS ":"",
+ (map->flags&MAP_WRPROT)?"WRPROT ":"",
+ (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
+ (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+
+ if(map->map>=MAX_WIN){
+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+ map->map);
+ return -1;
+ }
+
+ if(map->flags&MAP_ACTIVE){
+
+ /* When clients issue RequestMap, the access speed is not always
+ * properly configured:
+ */
+ if(map->speed > 0)
+ speed = map->speed;
+ else
+ switch(sa1100_pcmcia_socket[sock].cs_state.Vcc){
+ case 33:
+ speed = SA1100_PCMCIA_3V_MEM_ACCESS;
+ break;
+ default:
+ speed = SA1100_PCMCIA_5V_MEM_ACCESS;
+ }
+
+ clock = get_cclk_frequency() * 100;
+
+ mecr=MECR;
+
+ if(map->flags&MAP_ATTRIB){
+
+ MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
+ sa1100_pcmcia_socket[sock].speed_attr=speed;
+
+ } else {
+
+ MECR_BSM_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
+ sa1100_pcmcia_socket[sock].speed_mem=speed;
+
+ }
+
+ DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
+ __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
+ MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
+ sock, MECR_BSIO_GET(mecr, sock));
+
+ MECR=mecr;
+
+ }
+
+ start=map->sys_start;
+
+ if(map->sys_stop==0)
+ map->sys_stop=PAGE_SIZE-1;
+
+ map->sys_start=(map->flags & MAP_ATTRIB)?\
+ sa1100_pcmcia_socket[sock].phys_attr:\
+ sa1100_pcmcia_socket[sock].phys_mem;
+
+ map->sys_stop=map->sys_start+(map->sys_stop-start);
+
+ sa1100_pcmcia_socket[sock].mem_map[map->map]=*map;
+
+ return 0;
+
+} /* sa1100_pcmcia_set_mem_map() */
+
+
+#if defined(CONFIG_PROC_FS)
+
+/* sa1100_pcmcia_proc_setup()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the proc_setup() operation for the in-kernel PCMCIA
+ * service (formerly SS_ProcSetup in Card Services).
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static void sa1100_pcmcia_proc_setup(unsigned int sock,
+ struct proc_dir_entry *base){
+ struct proc_dir_entry *entry;
+
+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ if((entry=create_proc_entry("status", 0, base))==NULL){
+ printk(KERN_ERR "Unable to install \"status\" procfs entry\n");
+ return;
+ }
+
+ entry->read_proc=sa1100_pcmcia_proc_status;
+ entry->data=(void *)sock;
+}
+
+
+/* sa1100_pcmcia_proc_status()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the /proc/bus/pccard/??/status file.
+ *
+ * Returns: the number of characters added to the buffer
+ */
+static int sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
+ int count, int *eof, void *data){
+ char *p=buf;
+ unsigned int sock=(unsigned int)data;
+ unsigned int clock = get_cclk_frequency() * 100;
+ unsigned long mecr = MECR;
+
+ p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n",
+ sa1100_pcmcia_socket[sock].k_state.detect?"detect ":"",
+ sa1100_pcmcia_socket[sock].k_state.ready?"ready ":"",
+ sa1100_pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"",
+ sa1100_pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"",
+ sa1100_pcmcia_socket[sock].k_state.wrprot?"wrprot ":"",
+ sa1100_pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"",
+ sa1100_pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":"");
+
+ p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n",
+ sa1100_pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"",
+ sa1100_pcmcia_socket[sock].k_state.ready?"SS_READY ":"",
+ sa1100_pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"",
+ sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
+ "SS_IOCARD ":"",
+ (sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD &&
+ sa1100_pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"",
+ ((sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
+ (sa1100_pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"",
+ ((sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
+ (sa1100_pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"",
+ sa1100_pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"",
+ sa1100_pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":"");
+
+ p+=sprintf(p, "mask : %s%s%s%s%s\n",
+ sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\
+ "SS_DETECT ":"",
+ sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\
+ "SS_READY ":"",
+ sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\
+ "SS_BATDEAD ":"",
+ sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\
+ "SS_BATWARN ":"",
+ sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\
+ "SS_STSCHG ":"");
+
+ p+=sprintf(p, "cs_flags : %s%s%s%s%s\n",
+ sa1100_pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\
+ "SS_PWR_AUTO ":"",
+ sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
+ "SS_IOCARD ":"",
+ sa1100_pcmcia_socket[sock].cs_state.flags&SS_RESET?\
+ "SS_RESET ":"",
+ sa1100_pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\
+ "SS_SPKR_ENA ":"",
+ sa1100_pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\
+ "SS_OUTPUT_ENA ":"");
+
+ p+=sprintf(p, "Vcc : %d\n", sa1100_pcmcia_socket[sock].cs_state.Vcc);
+
+ p+=sprintf(p, "Vpp : %d\n", sa1100_pcmcia_socket[sock].cs_state.Vpp);
+
+ p+=sprintf(p, "irq : %d\n", sa1100_pcmcia_socket[sock].cs_state.io_irq);
+
+ p+=sprintf(p, "I/O : %u (%u)\n", sa1100_pcmcia_socket[sock].speed_io,
+ sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, sock)));
+
+ p+=sprintf(p, "attribute: %u (%u)\n", sa1100_pcmcia_socket[sock].speed_attr,
+ sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, sock)));
+
+ p+=sprintf(p, "common : %u (%u)\n", sa1100_pcmcia_socket[sock].speed_mem,
+ sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, sock)));
+
+ return p-buf;
+}
+
+#endif /* defined(CONFIG_PROC_FS) */
+
+
+#ifdef CONFIG_CPU_FREQ
+
+/* sa1100_pcmcia_update_mecr()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * When sa1100_pcmcia_notifier() decides that a MECR adjustment (due
+ * to a core clock frequency change) is needed, this routine establishes
+ * new BS_xx values consistent with the clock speed `clock'.
+ */
+static void sa1100_pcmcia_update_mecr(unsigned int clock){
+ unsigned int sock;
+ unsigned long mecr = MECR;
+
+ for(sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock){
+
+ MECR_BSIO_SET(mecr, sock,
+ sa1100_pcmcia_mecr_bs(sa1100_pcmcia_socket[sock].speed_io,
+ clock));
+ MECR_BSA_SET(mecr, sock,
+ sa1100_pcmcia_mecr_bs(sa1100_pcmcia_socket[sock].speed_attr,
+ clock));
+ MECR_BSM_SET(mecr, sock,
+ sa1100_pcmcia_mecr_bs(sa1100_pcmcia_socket[sock].speed_mem,
+ clock));
+ }
+
+ MECR = mecr;
+
+}
+
+/* sa1100_pcmcia_notifier()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^
+ * When changing the processor core clock frequency, it is necessary
+ * to adjust the MECR timings accordingly. We've recorded the timings
+ * requested by Card Services, so this is just a matter of finding
+ * out what our current speed is, and then recomputing the new MECR
+ * values.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int sa1100_pcmcia_notifier(struct notifier_block *nb,
+ unsigned long val, void *data){
+ struct cpufreq_info *ci = data;
+
+ switch(val){
+ case CPUFREQ_MINMAX:
+
+ break;
+
+ case CPUFREQ_PRECHANGE:
+
+ if(ci->new_freq > ci->old_freq){
+ DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n",
+ __FUNCTION__,
+ ci->new_freq / 1000, (ci->new_freq / 100) % 10,
+ ci->old_freq / 1000, (ci->old_freq / 100) % 10);
+ sa1100_pcmcia_update_mecr(ci->new_freq);
+ }
+
+ break;
+
+ case CPUFREQ_POSTCHANGE:
+
+ if(ci->new_freq < ci->old_freq){
+ DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n",
+ __FUNCTION__,
+ ci->new_freq / 1000, (ci->new_freq / 100) % 10,
+ ci->old_freq / 1000, (ci->old_freq / 100) % 10);
+ sa1100_pcmcia_update_mecr(ci->new_freq);
+ }
+
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unknown CPU frequency event %lx\n", __FUNCTION__,
+ val);
+ return -1;
+
+ }
+
+ return 0;
+
+}
+
+static struct notifier_block sa1100_pcmcia_notifier_block = {
+ notifier_call: sa1100_pcmcia_notifier
+};
+
+#endif
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_graphicsclient.c
+ *
+ * PCMCIA implementation routines for Graphics Client Plus
+ *
+ * 9/12/01 Woojung
+ * Turn power OFF at startup
+ * 1/31/2001 Woojung Huh
+ * Fix for GC Plus PCMCIA Reset Problem
+ * 2/27/2001 Woojung Huh [whuh@applieddata.net]
+ * Fix
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+#define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
+#define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
+
+static volatile unsigned long *PCMCIA_Status =
+ ((volatile unsigned long *) ADS_p2v(_ADS_CS_STATUS));
+
+static volatile unsigned long *PCMCIA_Power =
+ ((volatile unsigned long *) ADS_p2v(_ADS_CS_PR));
+
+static int gcplus_pcmcia_init(struct pcmcia_init *init)
+{
+ int irq, res;
+
+ // Reset PCMCIA
+ // Reset Timing for CPLD(U2) version 8001E or later
+ *PCMCIA_Power &= ~ ADS_CS_PR_A_RESET;
+ udelay(12); // 12 uSec
+
+ *PCMCIA_Power |= ADS_CS_PR_A_RESET;
+ mdelay(30); // 30 mSec
+
+ // Turn off 5V
+ *PCMCIA_Power &= ~0x03;
+
+ /* Register interrupts */
+ irq = S0_CD_IRQ;
+ res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
+ if (res < 0) {
+ printk(KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq);
+ return -1;
+ }
+
+ return 1; // 1 PCMCIA Slot
+}
+
+static int gcplus_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( S0_CD_IRQ, NULL);
+
+ /* Shutdown PCMCIA power */
+ mdelay(2); // 2msec
+ *PCMCIA_Power &= ~0x03;
+
+ return 0;
+}
+
+static int gcplus_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long levels;
+
+ if(state_array->size<1) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels=*PCMCIA_Status;
+
+ state_array->state[0].detect=(levels & ADS_CS_ST_A_CD)?1:0;
+ state_array->state[0].ready=(levels & ADS_CS_ST_A_READY)?1:0;
+ state_array->state[0].bvd1= 0;
+ state_array->state[0].bvd2= 0;
+ state_array->state[0].wrprot=0;
+ state_array->state[0].vs_3v=0;
+ state_array->state[0].vs_Xv=0;
+
+ return 1;
+}
+
+static int gcplus_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+ if (info->sock > 1)
+ return -1;
+
+ if (info->sock == 0)
+ info->irq = S0_STS_IRQ;
+
+ return 0;
+}
+
+static int gcplus_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long flags;
+
+ if(configure->sock>1) return -1;
+
+ save_flags_cli(flags);
+
+ switch (configure->vcc) {
+ case 0:
+ *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
+ break;
+
+ case 50:
+ *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
+ *PCMCIA_Power |= ADS_CS_PR_A_5V_POWER;
+ break;
+
+ case 33:
+ *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
+ *PCMCIA_Power |= ADS_CS_PR_A_3V_POWER;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+ // Reset PCMCIA
+ *PCMCIA_Power &= ~ ADS_CS_PR_A_RESET;
+ udelay(12);
+
+ *PCMCIA_Power |= ADS_CS_PR_A_RESET;
+ mdelay(30);
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+struct pcmcia_low_level gcplus_pcmcia_ops = {
+ gcplus_pcmcia_init,
+ gcplus_pcmcia_shutdown,
+ gcplus_pcmcia_socket_state,
+ gcplus_pcmcia_get_irq_info,
+ gcplus_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_graphicsmaster.c
+ *
+ * PCMCIA implementation routines for GraphicsMaster
+ *
+ * 9/18/01 Woojung
+ * Fixed wrong PCMCIA voltage setting
+ * 7/5/01 Woojung Huh <whuh@applieddata.net>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
+{
+ int return_val=0;
+
+ /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+
+ /* Disable Power 3.3V/5V for PCMCIA/CF */
+ PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
+
+ INTPOL1 |= (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
+
+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
+ "GC Master PCMCIA (0) CD", NULL);
+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
+ "GC Master CF (1) CD", NULL);
+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "GC Master PCMCIA (0) BVD1", NULL);
+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "GC Master CF (1) BVD1", NULL);
+
+ MECR = 0x09430943;
+
+ return (return_val<0) ? -1 : 2;
+}
+
+static int graphicsmaster_pcmcia_shutdown(void)
+{
+
+ free_irq(S0_CD_VALID, NULL);
+ free_irq(S1_CD_VALID, NULL);
+ free_irq(S0_BVD1_STSCHG, NULL);
+ free_irq(S1_BVD1_STSCHG, NULL);
+
+ INTPOL1 &= ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
+
+ return 0;
+}
+
+static int graphicsmaster_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+ unsigned long status;
+ int return_val=1;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ status=PCSR;
+
+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
+
+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
+
+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
+
+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
+
+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+
+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
+
+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
+
+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
+
+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
+
+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
+
+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
+
+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
+
+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
+
+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
+
+ return return_val;
+}
+
+static int graphicsmaster_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+
+ switch(info->sock){
+ case 0:
+ info->irq=S0_READY_NINT;
+ break;
+
+ case 1:
+ info->irq=S1_READY_NINT;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int graphicsmaster_pcmcia_configure_socket(const struct pcmcia_configure *configure)
+{
+ unsigned long pccr=PCCR, gpio=PA_DWR;
+
+ switch(configure->sock){
+ case 0:
+
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S0_FLT);
+ gpio |= GPIO_GPIO0 | GPIO_GPIO1;
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
+ gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
+ gpio &= ~GPIO_GPIO0;
+ break;
+
+ case 50:
+ pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
+ gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
+ gpio |= GPIO_GPIO0;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
+
+ break;
+
+ case 1:
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S1_FLT);
+ gpio |= GPIO_GPIO2 | GPIO_GPIO3;
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
+ gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
+ gpio &= ~GPIO_GPIO2;
+ break;
+
+ case 50:
+ pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
+ gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
+ gpio |= GPIO_GPIO2;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ if(configure->vpp!=configure->vcc && configure->vpp!=0){
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
+
+ break;
+
+ default:
+ return -1;
+ }
+
+ PCCR = pccr;
+ PA_DWR = gpio;
+
+ return 0;
+}
+
+struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
+ graphicsmaster_pcmcia_init,
+ graphicsmaster_pcmcia_shutdown,
+ graphicsmaster_pcmcia_socket_state,
+ graphicsmaster_pcmcia_get_irq_info,
+ graphicsmaster_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_h3600.c
+ *
+ * PCMCIA implementation routines for H3600
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+
+static int h3600_pcmcia_init(struct pcmcia_init *init){
+ int irq, res;
+
+ /* Enable CF bus: */
+ set_h3600_egpio(EGPIO_H3600_OPT_NVRAM_ON);
+ clr_h3600_egpio(EGPIO_H3600_OPT_RESET);
+
+ /* All those are inputs */
+ GPDR &= ~(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1 | GPIO_H3600_PCMCIA_IRQ0| GPIO_H3600_PCMCIA_IRQ1);
+
+ /* Set transition detect */
+ set_GPIO_IRQ_edge( GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1, GPIO_BOTH_EDGES );
+ set_GPIO_IRQ_edge( GPIO_H3600_PCMCIA_IRQ0| GPIO_H3600_PCMCIA_IRQ1, GPIO_FALLING_EDGE );
+
+ /* Register interrupts */
+ irq = IRQ_GPIO_H3600_PCMCIA_CD0;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
+ if( res < 0 ) goto irq_err;
+ irq = IRQ_GPIO_H3600_PCMCIA_CD1;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD1", NULL );
+ if( res < 0 ) goto irq_err;
+
+ return 2;
+
+irq_err:
+ printk( KERN_ERR __FUNCTION__ ": Request for IRQ %u failed\n", irq );
+ return -1;
+}
+
+static int h3600_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( IRQ_GPIO_H3600_PCMCIA_CD0, NULL );
+ free_irq( IRQ_GPIO_H3600_PCMCIA_CD1, NULL );
+
+ /* Disable CF bus: */
+ clr_h3600_egpio(EGPIO_H3600_OPT_NVRAM_ON|EGPIO_H3600_OPT_ON);
+ set_h3600_egpio(EGPIO_H3600_OPT_RESET);
+
+ return 0;
+}
+
+static int h3600_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long levels;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels=GPLR;
+
+ state_array->state[0].detect=((levels & GPIO_H3600_PCMCIA_CD0)==0)?1:0;
+ state_array->state[0].ready=(levels & GPIO_H3600_PCMCIA_IRQ0)?1:0;
+ state_array->state[0].bvd1= 0;
+ state_array->state[0].bvd2= 0;
+ state_array->state[0].wrprot=0; /* Not available on H3600. */
+ state_array->state[0].vs_3v=0;
+ state_array->state[0].vs_Xv=0;
+
+ state_array->state[1].detect=((levels & GPIO_H3600_PCMCIA_CD1)==0)?1:0;
+ state_array->state[1].ready=(levels & GPIO_H3600_PCMCIA_IRQ1)?1:0;
+ state_array->state[1].bvd1=0;
+ state_array->state[1].bvd2=0;
+ state_array->state[1].wrprot=0; /* Not available on H3600. */
+ state_array->state[1].vs_3v=0;
+ state_array->state[1].vs_Xv=0;
+
+ return 1;
+}
+
+static int h3600_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ switch (info->sock) {
+ case 0:
+ info->irq=IRQ_GPIO_H3600_PCMCIA_IRQ0;
+ break;
+ case 1:
+ info->irq=IRQ_GPIO_H3600_PCMCIA_IRQ1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int h3600_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long flags;
+
+ if(configure->sock>1) return -1;
+
+ save_flags_cli(flags);
+
+ switch (configure->vcc) {
+ case 0:
+ clr_h3600_egpio(EGPIO_H3600_OPT_ON);
+ break;
+
+ case 33:
+ case 50:
+ set_h3600_egpio(EGPIO_H3600_OPT_ON);
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+
+ if (configure->reset)
+ set_h3600_egpio(EGPIO_H3600_CARD_RESET);
+ else
+ clr_h3600_egpio(EGPIO_H3600_CARD_RESET);
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+struct pcmcia_low_level h3600_pcmcia_ops = {
+ h3600_pcmcia_init,
+ h3600_pcmcia_shutdown,
+ h3600_pcmcia_socket_state,
+ h3600_pcmcia_get_irq_info,
+ h3600_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_jornada720.c
+ *
+ * Jornada720 PCMCIA specific routines
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+#define SOCKET0_POWER GPIO_GPIO0
+#define SOCKET0_3V GPIO_GPIO2
+#define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3)
+#define SOCKET1_3V GPIO_GPIO3
+
+static int jornada720_pcmcia_init(struct pcmcia_init *init)
+{
+ int return_val=0;
+
+ GRER |= 0x00000002;
+ /* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */
+ PA_DDR = 0;
+ PA_DWR = 0;
+ PA_SDR = 0;
+ PA_SSR = 0;
+
+ PB_DDR = 0;
+ PB_DWR = 0x01;
+ PB_SDR = 0;
+ PB_SSR = 0;
+
+ PC_DDR = 0x88;
+ PC_DWR = 0x20;
+ PC_SDR = 0;
+ PC_SSR = 0;
+
+ INTPOL1 |=
+ (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
+
+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
+ "Jornada720 PCMCIA (0) CD", NULL);
+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
+ "Jornada720 CF (1) CD", NULL);
+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "Jornada720 PCMCIA (0) BVD1", NULL);
+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "Jornada720 CF (1) BVD1", NULL);
+
+ return (return_val<0) ? -1 : 2;
+}
+
+static int jornada720_pcmcia_shutdown(void)
+{
+ free_irq(S0_CD_VALID, NULL);
+ free_irq(S1_CD_VALID, NULL);
+ free_irq(S0_BVD1_STSCHG, NULL);
+ free_irq(S1_BVD1_STSCHG, NULL);
+
+ INTPOL1 &=
+ ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
+
+ return 0;
+}
+
+static int jornada720_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array)
+{
+ unsigned long status;
+ int return_val=1;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+ status=PCSR;
+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
+ return return_val;
+}
+
+static int jornada720_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+ switch(info->sock){
+ case 0:
+ info->irq=S0_READY_NINT;
+ break;
+
+ case 1:
+ info->irq=S1_READY_NINT;
+ break;
+
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int jornada720_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long pccr=PCCR, gpio=PA_DWR;
+
+printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
+ configure->sock, configure->vcc, configure->vpp);
+ switch(configure->sock){
+ case 0:
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S0_FLT);
+ gpio&=~(SOCKET0_POWER | SOCKET0_3V);
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
+ gpio |= SOCKET0_POWER | SOCKET0_3V;
+ break;
+
+ case 50:
+ pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
+ gpio = (gpio & ~SOCKET0_3V) | SOCKET0_POWER;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+ switch(configure->vpp){
+ case 0:
+ break;
+ case 50:
+ printk(KERN_ERR "%s(): 5.0 Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ break;
+ case 120:
+ printk(KERN_ERR "%s(): 12 Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ break;
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+ pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
+ break;
+
+ case 1:
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S1_FLT);
+ gpio &= ~(SOCKET1_POWER);
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
+ gpio |= SOCKET1_POWER;
+ break;
+
+ case 50:
+ pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
+ gpio = (gpio & ~(SOCKET1_POWER)) | SOCKET1_POWER;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+ if(configure->vpp!=configure->vcc && configure->vpp!=0){
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+ pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
+ break;
+ default:
+ return -1;
+ }
+ PCCR = pccr;
+ PA_DWR = gpio;
+ return 0;
+}
+
+struct pcmcia_low_level jornada720_pcmcia_ops = {
+ jornada720_pcmcia_init,
+ jornada720_pcmcia_shutdown,
+ jornada720_pcmcia_socket_state,
+ jornada720_pcmcia_get_irq_info,
+ jornada720_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_neponset.c
+ *
+ * Neponset PCMCIA specific routines
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int neponset_pcmcia_init(struct pcmcia_init *init){
+ int return_val=0;
+
+ /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+
+ /* MAX1600 to standby mode: */
+ PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+ NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
+
+ INTPOL1 |=
+ (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
+
+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
+ "Neponset PCMCIA (0) CD", NULL);
+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
+ "Neponset CF (1) CD", NULL);
+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "Neponset PCMCIA (0) BVD1", NULL);
+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "Neponset CF (1) BVD1", NULL);
+
+ return (return_val<0) ? -1 : 2;
+}
+
+static int neponset_pcmcia_shutdown(void){
+
+ free_irq(S0_CD_VALID, NULL);
+ free_irq(S1_CD_VALID, NULL);
+ free_irq(S0_BVD1_STSCHG, NULL);
+ free_irq(S1_BVD1_STSCHG, NULL);
+
+ INTPOL1 &=
+ ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
+
+ return 0;
+}
+
+static int neponset_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long status;
+ int return_val=1;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ status=PCSR;
+
+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
+
+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
+
+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
+
+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
+
+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+
+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
+
+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
+
+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
+
+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
+
+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
+
+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
+
+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
+
+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
+
+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
+
+ return return_val;
+}
+
+static int neponset_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ switch(info->sock){
+ case 0:
+ info->irq=S0_READY_NINT;
+ break;
+
+ case 1:
+ info->irq=S1_READY_NINT;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int neponset_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure){
+ unsigned long pccr=PCCR, ncr=NCR_0, gpio=PA_DWR;
+
+ /* Neponset uses the Maxim MAX1600, with the following connections:
+ *
+ * MAX1600 Neponset
+ *
+ * A0VCC SA-1111 GPIO A<1>
+ * A1VCC SA-1111 GPIO A<0>
+ * A0VPP CPLD NCR A0VPP
+ * A1VPP CPLD NCR A1VPP
+ * B0VCC SA-1111 GPIO A<2>
+ * B1VCC SA-1111 GPIO A<3>
+ * B0VPP ground (slot B is CF)
+ * B1VPP ground (slot B is CF)
+ *
+ * VX VCC (5V)
+ * VY VCC3_3 (3.3V)
+ * 12INA 12V
+ * 12INB ground (slot B is CF)
+ *
+ * The MAX1600 CODE pin is tied to ground, placing the device in
+ * "Standard Intel code" mode. Refer to the Maxim data sheet for
+ * the corresponding truth table.
+ */
+
+ switch(configure->sock){
+ case 0:
+
+ switch(configure->vcc){
+ case 0:
+ pccr=(pccr & ~PCCR_S0_FLT);
+ gpio&=~(GPIO_GPIO0 | GPIO_GPIO1);
+ break;
+
+ case 33:
+ pccr=(pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
+ gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO1;
+ break;
+
+ case 50:
+ pccr=(pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
+ gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO0;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ switch(configure->vpp){
+ case 0:
+ ncr&=~(NCR_A0VPP | NCR_A1VPP);
+ break;
+
+ case 120:
+ ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A1VPP;
+ break;
+
+ default:
+ if(configure->vpp == configure->vcc)
+ ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A0VPP;
+ else {
+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
+
+ break;
+
+ case 1:
+ switch(configure->vcc){
+ case 0:
+ pccr=(pccr & ~PCCR_S1_FLT);
+ gpio&=~(GPIO_GPIO2 | GPIO_GPIO3);
+ break;
+
+ case 33:
+ pccr=(pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
+ gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO2;
+ break;
+
+ case 50:
+ pccr=(pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
+ gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO3;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ if(configure->vpp!=configure->vcc && configure->vpp!=0){
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
+
+ break;
+
+ default:
+ return -1;
+ }
+
+ PCCR = pccr;
+ NCR_0 = ncr;
+ PA_DWR = gpio;
+
+ return 0;
+}
+
+struct pcmcia_low_level neponset_pcmcia_ops = {
+ neponset_pcmcia_init,
+ neponset_pcmcia_shutdown,
+ neponset_pcmcia_socket_state,
+ neponset_pcmcia_get_irq_info,
+ neponset_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_pangolin.c
+ *
+ * PCMCIA implementation routines for Pangolin
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int pangolin_pcmcia_init(struct pcmcia_init *init){
+ int irq, res;
+
+ /* set GPIO_PCMCIA_CD & GPIO_PCMCIA_IRQ as inputs */
+ GPDR &= ~(GPIO_PCMCIA_CD|GPIO_PCMCIA_IRQ);
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ /* set GPIO pins GPIO_PCMCIA_BUS_ON & GPIO_PCMCIA_RESET as output */
+ GPDR |= (GPIO_PCMCIA_BUS_ON|GPIO_PCMCIA_RESET);
+ /* Enable PCMCIA bus: */
+ GPCR = GPIO_PCMCIA_BUS_ON;
+#else
+ /* set GPIO pin GPIO_PCMCIA_RESET as output */
+ GPDR |= GPIO_PCMCIA_RESET;
+#endif
+ /* Set transition detect */
+ set_GPIO_IRQ_edge( GPIO_PCMCIA_CD, GPIO_BOTH_EDGES );
+ set_GPIO_IRQ_edge( GPIO_PCMCIA_IRQ, GPIO_FALLING_EDGE );
+
+ /* Register interrupts */
+ irq = IRQ_PCMCIA_CD;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD", NULL );
+ if( res < 0 ) goto irq_err;
+
+ /* There's only one slot, but it's "Slot 1": */
+ return 2;
+
+irq_err:
+ printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
+ return -1;
+}
+
+static int pangolin_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( IRQ_PCMCIA_CD, NULL );
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ /* Disable PCMCIA bus: */
+ GPSR = GPIO_PCMCIA_BUS_ON;
+#endif
+ return 0;
+}
+
+static int pangolin_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long levels;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels=GPLR;
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ state_array->state[1].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
+ state_array->state[1].ready=(levels & GPIO_PCMCIA_IRQ)?1:0;
+ state_array->state[1].bvd1=1; /* Not available on Pangolin. */
+ state_array->state[1].bvd2=1; /* Not available on Pangolin. */
+ state_array->state[1].wrprot=0; /* Not available on Pangolin. */
+ state_array->state[1].vs_3v=1; /* Can only apply 3.3V on Pangolin. */
+ state_array->state[1].vs_Xv=0;
+#else
+ state_array->state[0].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
+ state_array->state[0].ready=(levels & GPIO_PCMCIA_IRQ)?1:0;
+ state_array->state[0].bvd1=1; /* Not available on Pangolin. */
+ state_array->state[0].bvd2=1; /* Not available on Pangolin. */
+ state_array->state[0].wrprot=0; /* Not available on Pangolin. */
+ state_array->state[0].vs_3v=0; /* voltage level is determined by jumper setting */
+ state_array->state[0].vs_Xv=0;
+#endif
+ return 1;
+}
+
+static int pangolin_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ if(info->sock>1) return -1;
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ if(info->sock==1)
+ info->irq=IRQ_PCMCIA_IRQ;
+#else
+ if(info->sock==0)
+ info->irq=IRQ_PCMCIA_IRQ;
+#endif
+ return 0;
+}
+
+static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long value, flags;
+
+ if(configure->sock>1) return -1;
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ if(configure->sock==0) return 0;
+#endif
+ save_flags_cli(flags);
+
+ /* Murphy: BUS_ON different from POWER ? */
+
+ switch(configure->vcc){
+ case 0:
+ break;
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ case 50:
+ printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
+ __FUNCTION__);
+ case 33: /* Can only apply 3.3V to the CF slot. */
+ break;
+#else
+ case 50:
+ printk(KERN_WARNING "%s(): CS asked for 5V, determinded by jumper setting...\n", __FUNCTION__);
+ break;
+ case 33:
+ printk(KERN_WARNING "%s(): CS asked for 3.3V, determined by jumper setting...\n", __FUNCTION__);
+ break;
+#endif
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+#ifdef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ /* reset & unreset request */
+ if(configure->sock==0) {
+ if(configure->reset) {
+ GPSR |= GPIO_PCMCIA_RESET;
+ } else {
+ GPCR |= GPIO_PCMCIA_RESET;
+ }
+ }
+#endif
+ /* Silently ignore Vpp, output enable, speaker enable. */
+ restore_flags(flags);
+ return 0;
+}
+
+struct pcmcia_low_level pangolin_pcmcia_ops = {
+ pangolin_pcmcia_init,
+ pangolin_pcmcia_shutdown,
+ pangolin_pcmcia_socket_state,
+ pangolin_pcmcia_get_irq_info,
+ pangolin_pcmcia_configure_socket
+};
+
--- /dev/null
+#warning "REVISIT_PFS168: Need to verify and test GPIO power encodings."
+/*
+ * drivers/pcmcia/sa1100_pfs168.c
+ *
+ * PFS168 PCMCIA specific routines
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int pfs168_pcmcia_init(struct pcmcia_init *init){
+ int return_val=0;
+
+ /* TPS2211 to standby mode: */
+ PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+
+ /* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller: */
+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+
+ INTPOL1 |=
+ (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
+
+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
+ "PFS168 PCMCIA (0) CD", NULL);
+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
+ "PFS168 CF (1) CD", NULL);
+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "PFS168 PCMCIA (0) BVD1", NULL);
+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "PFS168 CF (1) BVD1", NULL);
+
+ return (return_val<0) ? -1 : 2;
+}
+
+static int pfs168_pcmcia_shutdown(void){
+
+ free_irq(S0_CD_VALID, NULL);
+ free_irq(S1_CD_VALID, NULL);
+ free_irq(S0_BVD1_STSCHG, NULL);
+ free_irq(S1_BVD1_STSCHG, NULL);
+
+ INTPOL1 &=
+ ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
+
+ return 0;
+}
+
+static int pfs168_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long status;
+ int return_val=1;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ status=PCSR;
+
+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
+
+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
+
+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
+
+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
+
+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+
+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
+
+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
+
+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
+
+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
+
+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
+
+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
+
+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
+
+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
+
+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
+
+ return return_val;
+}
+
+static int pfs168_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ switch(info->sock){
+ case 0:
+ info->irq=S0_READY_NINT;
+ break;
+
+ case 1:
+ info->irq=S1_READY_NINT;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int pfs168_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure){
+ unsigned long pccr=PCCR, gpio=PA_DWR;
+
+ /* PFS168 uses the Texas Instruments TPS2211 for PCMCIA (socket 0) voltage control only,
+ * with the following connections:
+ *
+ * TPS2211 PFS168
+ *
+ * -VCCD0 SA-1111 GPIO A<0>
+ * -VCCD0 SA-1111 GPIO A<1>
+ * VPPD0 SA-1111 GPIO A<2>
+ * VPPD0 SA-1111 GPIO A<2>
+ *
+ */
+
+ switch(configure->sock){
+ case 0:
+
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S0_FLT);
+ gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
+ gpio = (gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO0;
+ break;
+
+ case 50:
+ pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
+ gpio = (gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO1;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ switch(configure->vpp){
+ case 0:
+ gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
+ break;
+
+ case 120:
+ printk(KERN_ERR "%s(): PFS-168 does not support Vpp %uV\n", __FUNCTION__,
+ configure->vpp/10);
+ return -1;
+ break;
+
+ default:
+ if(configure->vpp == configure->vcc)
+ gpio = (gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO3;
+ else {
+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+ }
+
+ pccr = (configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
+
+ PA_DWR = gpio;
+
+ break;
+
+ case 1:
+ switch(configure->vcc){
+ case 0:
+ pccr = (pccr & ~PCCR_S1_FLT);
+ break;
+
+ case 33:
+ pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
+ break;
+
+ case 50:
+ printk(KERN_ERR "%s(): PFS-168 CompactFlash socket does not support Vcc %uV\n", __FUNCTION__,
+ configure->vcc/10);
+ return -1;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ if(configure->vpp!=configure->vcc && configure->vpp!=0){
+ printk(KERN_ERR "%s(): CompactFlash socket does not support Vpp %uV\n", __FUNCTION__,
+ configure->vpp/10);
+ return -1;
+ }
+
+ pccr = (configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
+
+ break;
+
+ default:
+ return -1;
+ }
+
+ PCCR = pccr;
+
+ return 0;
+}
+
+struct pcmcia_low_level pfs168_pcmcia_ops = {
+ pfs168_pcmcia_init,
+ pfs168_pcmcia_shutdown,
+ pfs168_pcmcia_socket_state,
+ pfs168_pcmcia_get_irq_info,
+ pfs168_pcmcia_configure_socket
+};
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_pangolin.c
+ *
+ * PCMCIA implementation routines for simpad
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int simpad_pcmcia_init(struct pcmcia_init *init){
+ int irq, res;
+
+ /* set GPIO_CF_CD & GPIO_CF_IRQ as inputs */
+ GPDR &= ~(GPIO_CF_CD|GPIO_CF_IRQ);
+ //init_simpad_cs3();
+ printk("\nCS3:%x\n",cs3_shadow);
+ PCMCIA_setbit(PCMCIA_RESET);
+ PCMCIA_clearbit(PCMCIA_BUFF_DIS);
+
+ /* Set transition detect */
+ set_GPIO_IRQ_edge( GPIO_CF_CD, GPIO_BOTH_EDGES );
+ set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+
+ /* Register interrupts */
+ irq = IRQ_GPIO_CF_CD;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
+ if( res < 0 ) goto irq_err;
+
+ /* There's only one slot, but it's "Slot 1": */
+ return 2;
+
+irq_err:
+ printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
+ return -1;
+}
+
+static int simpad_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( IRQ_GPIO_CF_CD, NULL );
+
+ /* Disable CF bus: */
+
+ PCMCIA_setbit(PCMCIA_BUFF_DIS);
+ PCMCIA_clearbit(PCMCIA_RESET);
+ return 0;
+}
+
+static int simpad_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array)
+{
+ unsigned long levels;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels=GPLR;
+
+ state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
+
+ state_array->state[1].ready=(levels & GPIO_CF_IRQ)?1:0;
+
+ state_array->state[1].bvd1=1; /* Not available on Simpad. */
+
+ state_array->state[1].bvd2=1; /* Not available on Simpad. */
+
+ state_array->state[1].wrprot=0; /* Not available on Simpad. */
+
+ state_array->state[1].vs_3v=1; /* Can only apply 3.3V on Simpad. */
+
+ state_array->state[1].vs_Xv=0;
+
+ return 1;
+}
+
+static int simpad_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ if(info->sock>1) return -1;
+
+ if(info->sock==1)
+ info->irq=IRQ_GPIO_CF_IRQ;
+
+ return 0;
+}
+
+static int simpad_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure)
+{
+ unsigned long value, flags;
+
+ if(configure->sock>1) return -1;
+
+ if(configure->sock==0) return 0;
+
+ save_flags_cli(flags);
+
+ /* Murphy: BUS_ON different from POWER ? */
+
+ switch(configure->vcc){
+ case 0:
+ PCMCIA_setbit(PCMCIA_BUFF_DIS);
+ break;
+
+ case 33:
+ case 50:
+ PCMCIA_setbit(PCMCIA_BUFF_DIS);
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+struct pcmcia_low_level simpad_pcmcia_ops = {
+ simpad_pcmcia_init,
+ simpad_pcmcia_shutdown,
+ simpad_pcmcia_socket_state,
+ simpad_pcmcia_get_irq_info,
+ simpad_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_stork.c
+ *
+ Copyright 2001 (C) Ken Gordon
+
+ This is derived from pre-existing drivers/pcmcia/sa1100_?????.c
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ *
+ * PCMCIA implementation routines for stork
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+static int debug = 0;
+
+static struct pcmcia_init sa1100_stork_pcmcia_init;
+
+static int stork_pcmcia_init(struct pcmcia_init *init)
+{
+ int irq, res;
+ printk("in stork_pcmcia_init\n");
+
+ sa1100_stork_pcmcia_init = *init;
+
+ /* Enable CF bus: */
+ storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
+
+ /* All those are inputs */
+ GPDR &= ~(GPIO_STORK_PCMCIA_A_CARD_DETECT | GPIO_STORK_PCMCIA_B_CARD_DETECT | GPIO_STORK_PCMCIA_A_RDY| GPIO_STORK_PCMCIA_B_RDY);
+
+ /* Set transition detect */
+ set_GPIO_IRQ_edge( GPIO_STORK_PCMCIA_A_CARD_DETECT | GPIO_STORK_PCMCIA_B_CARD_DETECT, GPIO_BOTH_EDGES );
+ set_GPIO_IRQ_edge( GPIO_STORK_PCMCIA_A_RDY| GPIO_STORK_PCMCIA_B_RDY, GPIO_FALLING_EDGE );
+
+ /* Register interrupts */
+ irq = IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
+ if( res < 0 ) goto irq_err;
+ irq = IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT;
+ res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD1", NULL );
+ if( res < 0 ) goto irq_err;
+
+ return 2;
+
+ irq_err:
+ printk( KERN_ERR __FUNCTION__ ": Request for IRQ %u failed\n", irq );
+ return -1;
+}
+
+static int stork_pcmcia_shutdown(void)
+{
+ printk(__FUNCTION__ "\n");
+ /* disable IRQs */
+ free_irq( IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, NULL );
+ free_irq( IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, NULL );
+
+ /* Disable CF bus: */
+ storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
+ storkClearLatchA(STORK_PCMCIA_A_POWER_ON);
+ storkClearLatchA(STORK_PCMCIA_B_POWER_ON);
+ return 0;
+}
+
+static int stork_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+ unsigned long levels;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ levels=GPLR;
+
+ if (debug > 1)
+ printk(__FUNCTION__ " GPLR=%x IRQ[1:0]=%x\n", GPLR, (GPLR & (GPIO_STORK_PCMCIA_A_RDY|GPIO_STORK_PCMCIA_B_RDY)));
+ state_array->state[0].detect=((levels & GPIO_STORK_PCMCIA_A_CARD_DETECT)==0)?1:0;
+ state_array->state[0].ready=(levels & GPIO_STORK_PCMCIA_A_RDY)?1:0;
+ state_array->state[0].bvd1= 1;
+ state_array->state[0].bvd2= 1;
+ state_array->state[0].wrprot=0;
+ state_array->state[0].vs_3v=1;
+ state_array->state[0].vs_Xv=0;
+
+ state_array->state[1].detect=((levels & GPIO_STORK_PCMCIA_B_CARD_DETECT)==0)?1:0;
+ state_array->state[1].ready=(levels & GPIO_STORK_PCMCIA_B_RDY)?1:0;
+ state_array->state[1].bvd1=1;
+ state_array->state[1].bvd2=1;
+ state_array->state[1].wrprot=0;
+ state_array->state[1].vs_3v=1;
+ state_array->state[1].vs_Xv=0;
+
+ return 1;
+}
+
+static int stork_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+
+ switch (info->sock) {
+ case 0:
+ info->irq=IRQ_GPIO_STORK_PCMCIA_A_RDY;
+ break;
+ case 1:
+ info->irq=IRQ_GPIO_STORK_PCMCIA_B_RDY;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int stork_pcmcia_configure_socket(const struct pcmcia_configure *configure)
+{
+ int card = configure->sock;
+ unsigned long flags;
+
+ int DETECT, RDY, POWER, RESET;
+
+ if (card > 1) return -1;
+
+ printk(__FUNCTION__ ": socket=%d vcc=%d vpp=%d reset=%d\n",
+ card, configure->vcc, configure->vpp, configure->reset);
+
+ save_flags_cli(flags);
+
+ if (card == 0) {
+ DETECT = GPIO_STORK_PCMCIA_A_CARD_DETECT;
+ RDY = GPIO_STORK_PCMCIA_A_RDY;
+ POWER = STORK_PCMCIA_A_POWER_ON;
+ RESET = STORK_PCMCIA_A_RESET;
+ } else {
+ DETECT = GPIO_STORK_PCMCIA_B_CARD_DETECT;
+ RDY = GPIO_STORK_PCMCIA_B_RDY;
+ POWER = STORK_PCMCIA_B_POWER_ON;
+ RESET = STORK_PCMCIA_B_RESET;
+ }
+
+/*
+ if (storkTestGPIO(DETECT)) {
+ printk("no card detected - but resetting anyway\r\n");
+ }
+*/
+ switch (configure->vcc) {
+ case 0:
+ storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
+ storkClearLatchA(POWER);
+ break;
+
+ case 50:
+ case 33:
+ storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
+ storkSetLatchA(POWER);
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ restore_flags(flags);
+ return -1;
+ }
+
+ if (configure->reset)
+ storkSetLatchB(RESET);
+ else
+ storkClearLatchB(RESET);
+
+ restore_flags(flags);
+
+ /* silently ignore vpp and speaker enables. */
+
+ printk(__FUNCTION__ ": finished\n");
+
+ return 0;
+}
+
+struct pcmcia_low_level stork_pcmcia_ops = {
+ stork_pcmcia_init,
+ stork_pcmcia_shutdown,
+ stork_pcmcia_socket_state,
+ stork_pcmcia_get_irq_info,
+ stork_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_xp860.c
+ *
+ * XP860 PCMCIA specific routines
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+#define NCR_A0VPP (1<<16)
+#define NCR_A1VPP (1<<17)
+
+static int xp860_pcmcia_init(struct pcmcia_init *init){
+ int return_val=0;
+
+ /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+
+ /* MAX1600 to standby mode: */
+ PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+ GPDR |= (NCR_A0VPP | NCR_A1VPP);
+ GPCR &= ~(NCR_A0VPP | NCR_A1VPP);
+
+ INTPOL1 |=
+ (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
+ (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
+
+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
+ "XP860 PCMCIA (0) CD", NULL);
+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
+ "XP860 CF (1) CD", NULL);
+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "XP860 PCMCIA (0) BVD1", NULL);
+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
+ "XP860 CF (1) BVD1", NULL);
+
+ return (return_val<0) ? -1 : 2;
+}
+
+static int xp860_pcmcia_shutdown(void){
+
+ free_irq(S0_CD_VALID, NULL);
+ free_irq(S1_CD_VALID, NULL);
+ free_irq(S0_BVD1_STSCHG, NULL);
+ free_irq(S1_BVD1_STSCHG, NULL);
+
+ INTPOL1 &=
+ ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
+ (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
+ (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
+
+ return 0;
+}
+
+static int xp860_pcmcia_socket_state(struct pcmcia_state_array
+ *state_array){
+ unsigned long status;
+ int return_val=1;
+
+ if(state_array->size<2) return -1;
+
+ memset(state_array->state, 0,
+ (state_array->size)*sizeof(struct pcmcia_state));
+
+ status=PCSR;
+
+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
+
+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
+
+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
+
+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
+
+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+
+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
+
+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
+
+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
+
+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
+
+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
+
+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
+
+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
+
+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
+
+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
+
+ return return_val;
+}
+
+static int xp860_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+
+ switch(info->sock){
+ case 0:
+ info->irq=S0_READY_NINT;
+ break;
+
+ case 1:
+ info->irq=S1_READY_NINT;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int xp860_pcmcia_configure_socket(const struct pcmcia_configure
+ *configure){
+ unsigned long pccr=PCCR, ncr=GPLR, gpio=PA_DWR;
+
+
+ /* Neponset uses the Maxim MAX1600, with the following connections:
+ *
+ * MAX1600 Neponset
+ *
+ * A0VCC SA-1111 GPIO A<1>
+ * A1VCC SA-1111 GPIO A<0>
+ * A0VPP CPLD NCR A0VPP
+ * A1VPP CPLD NCR A1VPP
+ * B0VCC SA-1111 GPIO A<2>
+ * B1VCC SA-1111 GPIO A<3>
+ * B0VPP ground (slot B is CF)
+ * B1VPP ground (slot B is CF)
+ *
+ * VX VCC (5V)
+ * VY VCC3_3 (3.3V)
+ * 12INA 12V
+ * 12INB ground (slot B is CF)
+ *
+ * The MAX1600 CODE pin is tied to ground, placing the device in
+ * "Standard Intel code" mode. Refer to the Maxim data sheet for
+ * the corresponding truth table.
+ */
+
+ switch(configure->sock){
+ case 0:
+
+ switch(configure->vcc){
+ case 0:
+ gpio&=~(GPIO_GPIO0 | GPIO_GPIO1);
+ break;
+
+ case 33:
+ pccr=(pccr & ~PCCR_S0_PSE);
+ gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO1;
+ break;
+
+ case 50:
+ pccr=(pccr | PCCR_S0_PSE);
+ gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO0;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ switch(configure->vpp){
+ case 0:
+ ncr&=~(NCR_A0VPP | NCR_A1VPP);
+ break;
+
+ case 120:
+ ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A1VPP;
+ break;
+
+ default:
+ if(configure->vpp == configure->vcc)
+ ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A0VPP;
+ else {
+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
+ pccr=(configure->output)?(pccr | PCCR_S0_FLT):(pccr & ~PCCR_S0_FLT);
+
+ break;
+
+ case 1:
+ switch(configure->vcc){
+ case 0:
+ gpio&=~(GPIO_GPIO2 | GPIO_GPIO3);
+ break;
+
+ case 33:
+ pccr=(pccr & ~PCCR_S1_PSE);
+ gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO2;
+ break;
+
+ case 50:
+ pccr=(pccr | PCCR_S1_PSE);
+ gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO3;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ if(configure->vpp!=configure->vcc && configure->vpp!=0){
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
+ configure->vpp);
+ return -1;
+ }
+
+ pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
+ pccr=(configure->output)?(pccr | PCCR_S1_FLT):(pccr & ~PCCR_S1_FLT);
+
+ break;
+
+ default:
+ return -1;
+ }
+
+ PCCR = pccr;
+ ncr &= NCR_A0VPP|NCR_A1VPP;
+ GPSR = ncr;
+ GPCR = (~ncr)&(NCR_A0VPP|NCR_A1VPP);
+ PA_DWR = gpio;
+
+ return 0;
+}
+
+struct pcmcia_low_level xp860_pcmcia_ops = {
+ xp860_pcmcia_init,
+ xp860_pcmcia_shutdown,
+ xp860_pcmcia_socket_state,
+ xp860_pcmcia_get_irq_info,
+ xp860_pcmcia_configure_socket
+};
+
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_yopy.c
+ *
+ * PCMCIA implementation routines for Yopy
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/pcmcia.h>
+
+
+static inline void pcmcia_power(int on) {
+ /* high for power up */
+ yopy_gpio_set(GPIO_CF_POWER, on);
+}
+
+static inline void pcmcia_reset(int reset)
+{
+ /* high for reset */
+ yopy_gpio_set(GPIO_CF_RESET, reset);
+}
+
+static int yopy_pcmcia_init(struct pcmcia_init *init)
+{
+ int irq, res;
+
+ pcmcia_power(0);
+ pcmcia_reset(1);
+
+ /* All those are inputs */
+ GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IREQ);
+ GAFR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IREQ);
+
+ /* Set transition detect */
+ set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1,
+ GPIO_BOTH_EDGES );
+ set_GPIO_IRQ_edge( GPIO_CF_IREQ, GPIO_FALLING_EDGE );
+
+ /* Register interrupts */
+ irq = IRQ_CF_CD;
+ res = request_irq(irq, init->handler, SA_INTERRUPT, "CF_CD", NULL);
+ if (res < 0) goto irq_err;
+ irq = IRQ_CF_BVD2;
+ res = request_irq(irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL);
+ if (res < 0) goto irq_err;
+ irq = IRQ_CF_BVD1;
+ res = request_irq(irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL);
+ if (res < 0) goto irq_err;
+
+ return 1;
+irq_err:
+ printk(KERN_ERR "%s: Request for IRQ %d failed\n", __FUNCTION__, irq);
+ return -1;
+}
+
+static int yopy_pcmcia_shutdown(void)
+{
+ /* disable IRQs */
+ free_irq( IRQ_CF_CD, NULL );
+ free_irq( IRQ_CF_BVD2, NULL );
+ free_irq( IRQ_CF_BVD1, NULL );
+
+ /* Disable CF */
+ pcmcia_reset(1);
+ pcmcia_power(0);
+
+ return 0;
+}
+
+static int yopy_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+ unsigned long levels;
+
+ if (state_array->size != 1)
+ return -1;
+
+ memset(state_array->state, 0,
+ state_array->size * sizeof(struct pcmcia_state));
+
+ levels = GPLR;
+
+ state_array->state[0].detect = (levels & GPIO_CF_CD) ? 0 : 1;
+ state_array->state[0].ready = (levels & GPIO_CF_READY) ? 1 : 0;
+ state_array->state[0].bvd1 = (levels & GPIO_CF_BVD1) ? 1 : 0;
+ state_array->state[0].bvd2 = (levels & GPIO_CF_BVD2) ? 1 : 0;
+ state_array->state[0].wrprot = 0; /* Not available on Yopy. */
+ state_array->state[0].vs_3v = 0; /* FIXME Can only apply 3.3V on Yopy. */
+ state_array->state[0].vs_Xv = 0;
+
+ return 1;
+}
+
+static int yopy_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+ if (info->sock != 0)
+ return -1;
+
+ info->irq = IRQ_CF_IREQ;
+
+ return 0;
+}
+
+static int yopy_pcmcia_configure_socket(const struct pcmcia_configure *configure)
+{
+ if (configure->sock != 0)
+ return -1;
+
+ switch (configure->vcc) {
+ case 0: /* power off */;
+ pcmcia_power(0);
+ break;
+ case 50:
+ printk(KERN_WARNING __FUNCTION__"(): CS asked for 5V, applying 3.3V..\n");
+ case 33:
+ pcmcia_power(1);
+ break;
+ default:
+ printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n",
+ configure->vcc);
+ return -1;
+ }
+
+ pcmcia_reset(configure->reset);
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+ return 0;
+}
+
+struct pcmcia_low_level yopy_pcmcia_ops = {
+ yopy_pcmcia_init,
+ yopy_pcmcia_shutdown,
+ yopy_pcmcia_socket_state,
+ yopy_pcmcia_get_irq_info,
+ yopy_pcmcia_configure_socket
+};
MODULE_PARM_DESC(isapnp_reserve_io, "ISA Plug & Play - reserve I/O region(s) - port,size");
MODULE_PARM(isapnp_reserve_mem, "1-16i");
MODULE_PARM_DESC(isapnp_reserve_mem, "ISA Plug & Play - reserve memory region(s) - address,size");
+MODULE_LICENSE("GPL");
#define _PIDXR 0x279
#define _PNPWRP 0xa79
}
isapnp_for_each_dev(dev) {
if (dev->active) {
- if (dev->irq_resource[0].start == irq ||
- dev->irq_resource[1].start == irq)
+ if ((dev->irq_resource[0].flags && dev->irq_resource[0].start == irq) ||
+ (dev->irq_resource[1].flags && dev->irq_resource[1].start == irq))
return 1;
}
}
}
isapnp_for_each_dev(dev) {
if (dev->active) {
- if (dev->dma_resource[0].start == dma || dev->dma_resource[1].start == dma)
+ if ((dev->dma_resource[0].flags && dev->dma_resource[0].start == dma) ||
+ (dev->dma_resource[1].flags && dev->dma_resource[1].start == dma))
return 1;
}
}
static int isapnp_valid_dma(struct isapnp_cfgtmp *cfg, int idx)
{
+ /* DMA priority: this table is good for i386 */
+ static unsigned short xtab[16] = {
+ 1, 3, 5, 6, 7, 0, 2, 4
+ };
int err, i;
unsigned long *value1, *value2;
struct isapnp_dma *dma;
value1 = &cfg->result.dma_resource[idx].start;
value2 = &cfg->result.dma_resource[idx].end;
if (cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO) {
- for (i = 0; i < 8 && !(dma->map & (1<<i)); i++);
+ for (i = 0; i < 8 && !(dma->map & (1<<xtab[i])); i++);
if (i >= 8)
return -ENOENT;
cfg->result.dma_resource[idx].flags &= ~IORESOURCE_AUTO;
- if (!isapnp_check_dma(cfg, *value1 = *value2 = i, idx))
+ if (!isapnp_check_dma(cfg, *value1 = *value2 = xtab[i], idx))
return 0;
}
do {
- for (i = *value1 + 1; i < 8 && !(dma->map & (1<<i)); i++);
+ for (i = 0; i < 8 && xtab[i] != *value1; i++);
+ for (i++; i < 8 && !(dma->map & (1<<xtab[i])); i++);
if (i >= 8) {
if (dma->res && dma->res->alt) {
if ((err = isapnp_alternative_switch(cfg, dma->res, dma->res->alt))<0)
}
return -ENOENT;
} else {
- *value1 = *value2 = i;
+ *value1 = *value2 = xtab[i];
}
} while (isapnp_check_dma(cfg, *value1, idx));
return 0;
BUG ();
}
if (device->lowmem_cqr==NULL) {
- DASD_MESSAGE (KERN_WARNING, device,
- "Low memory! Using emergency request %p",
- device->lowmem_ccws);
+ DASD_DRIVER_DEBUG_EVENT (2, dasd_alloc_request,
+ "(%04x) Low memory! Using emergency request %p.",
+ device->devinfo.devno,
+ device->lowmem_ccws);
+
device->lowmem_cqr=device->lowmem_ccws;
rv = device->lowmem_ccws;
memset (rv, 0, PAGE_SIZE);
rv->data = (void *) ((long) rv + PAGE_SIZE - datasize);
rv->cpaddr = (ccw1_t *) ((long) rv + sizeof (ccw_req_t));
} else {
- DASD_MESSAGE (KERN_WARNING, device,
- "Refusing emergency mem for request "
- "NULL, already in use at %p.",
- device->lowmem_ccws);
+ DASD_DRIVER_DEBUG_EVENT (2, dasd_alloc_request,
+ "(%04x) Refusing emergency mem for request "
+ "NULL, already in use at %p.",
+ device->devinfo.devno,
+ device->lowmem_ccws);
}
return rv;
}
CQR_STATUS_QUEUED);
+#ifdef DASD_PROFILE
/* save profile information for non erp cqr */
if (cqr->refers == NULL) {
unsigned int counter = 0;
dasd_global_profile.dasd_io_nr_req[counter]++;
device->profile.dasd_io_nr_req[counter]++;
}
+#endif
}
/*
chanq_max_size > 0 || (req->nr_sectors >= chanq_min_size)) {
ccw_req_t *cqr = NULL;
if (is_read_only(device->kdev) && req->cmd == WRITE) {
- DASD_MESSAGE (KERN_WARNING, device,
- "rejecting write request %p\n",
- req);
+
+ DASD_DRIVER_DEBUG_EVENT (3, dasd_int_handler,
+ "(%04x) Rejecting write request %p\n",
+ device->devinfo.devno,
+ req);
+
dasd_end_request (req, 0);
dasd_dequeue_request (queue,req);
} else {
part[MINOR (req->rq_dev)].start_sect;
cqr = device->discipline->build_cp_from_req (device, req);
if (cqr == NULL) {
- DASD_MESSAGE (KERN_WARNING, device,
- "CCW creation failed on request %p\n",
- req);
+
+ DASD_DRIVER_DEBUG_EVENT (3, dasd_int_handler,
+ "(%04x) CCW creation failed "
+ "on request %p\n",
+ device->devinfo.devno,
+ req);
/* revert relocation of request */
req->sector -=
device->major_info->gendisk.
}
erp->cpaddr->cmd_code = CCW_CMD_TIC;
- erp->cpaddr->cda = (__u32) (void *) cqr->cpaddr;
+ erp->cpaddr->cda = (__u32) (addr_t) cqr->cpaddr;
erp->function = dasd_default_erp_action;
erp->refers = cqr;
erp->device = cqr->device;
}
for (i = (1 << DASD_PARTN_BITS) - 1; i >= 0; i--) {
int major = device->major_info->gendisk.major;
- int minor = start + i;
- kdev_t devi = MKDEV (major, minor);
- struct super_block *sb = get_super (devi);
- //sync_dev (devi);
- if (sb)
- invalidate_inodes (sb);
- invalidate_buffers (devi);
+ invalidate_device(MKDEV (major, start+i), 1);
}
dasd_destroy_partitions(device);
dasd_setup_partitions(device);
#endif
switch (no) {
case DASDAPIVER: {
- int ver = DASD_API_VERSION;
- rc = copy_to_user ((int *) data, &ver, sizeof (int));
- if (rc)
- rc = -EFAULT;
- break;
+ int ver = DASD_API_VERSION;
+ rc = put_user(ver, (int *) data);
+ break;
}
case BLKGETSIZE:{ /* Return device size */
long blocks = major_info->gendisk.sizes
[MINOR (inp->i_rdev)] << 1;
- rc =
- copy_to_user ((long *) data, &blocks,
- sizeof (long));
- if (rc)
- rc = -EFAULT;
+ rc = put_user(blocks, (long *) data);
+ break;
+ }
+ case BLKGETSIZE64:{
+ u64 blocks = major_info->gendisk.sizes
+ [MINOR (inp->i_rdev)];
+ rc = put_user(blocks << 10, (u64 *) data);
break;
}
case BLKRRPART:{
int rc = 0;
unsigned long flags;
- printk (KERN_ERR PRINTK_HEADER
- "called dasd_state_accept_to_init for device %02x\n",
- device->devinfo.devno);
-
if ( device->discipline->init_analysis ) {
device->init_cqr=device->discipline->init_analysis (device);
if ( device->init_cqr != NULL ) {
rc = -EMEDIUMTYPE;
}
if ( device->init_cqr ) {
+ /* This pointer is no longer needed, BUT dont't free the */
+ /* memory, because this is done in bh for finished request!!!! */
atomic_dec(&dasd_init_pending);
- device->init_cqr = NULL; /* This one is no longer needed */
+ device->init_cqr = NULL;
}
device->level = DASD_STATE_READY;
return rc;
dasd_deactivate_queue (dasd_device_t *device)
{
int i;
- int major = MAJOR(device->kdev);
int minor = MINOR(device->kdev);
for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
vfree (buffer);
return -EFAULT;
}
- buffer[user_len] = 0;
+
+ /* replace LF with '\0' */
+ if (buffer[user_len -1] == '\n') {
+ buffer[user_len -1] = '\0';
+ } else {
+ buffer[user_len] = '\0';
+ }
+
printk (KERN_INFO PRINTK_HEADER "/proc/dasd/devices: '%s'\n", buffer);
if (strncmp (buffer, "set ", 4) && strncmp (buffer, "add ", 4)) {
printk (KERN_WARNING PRINTK_HEADER
range.to == -EINVAL ) {
printk (KERN_WARNING PRINTK_HEADER
- "/proc/dasd/devices: parse error in '%s'",
+ "/proc/dasd/devices: range parse error in '%s'\n",
buffer);
} else {
off = (long) temp - (long) buffer;
dasd_disable_ranges (&range, NULL, 0, 1);
} else {
printk (KERN_WARNING PRINTK_HEADER
- "/proc/dasd/devices: parse error in '%s'", buffer);
+ "/proc/dasd/devices: parse error in '%s'\n",
+ buffer);
}
}
}
* DASD_3990_HANDLE_ENV_DATA
*
* DESCRIPTION
- * Handles 24 byte 'Enviromental data present'.
+ * Handles 24 byte 'Environmental data present'.
* Does a analysis of the sense data (message Format)
* and prints the error messages.
*
O_TARGET := s390-char.o
list-multi := tub3270.o tape390.o
+export-objs := hwc_rw.o
tub3270-objs := tuball.o tubfs.o tubtty.o \
tubttyaid.o tubttybld.o tubttyscl.o \
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/version.h>
#include <asm/semaphore.h>
#include <asm/ebcdic.h>
tapestate_set (ti, TS_DONE);
ti->rc = 0;
ti->wanna_wakeup=1;
- wake_up_interruptible (&ti->wq);
+ wake_up (&ti->wq);
}
void
ti->wanna_wakeup=1;
switch (tapestate_get(ti)) {
case TS_REW_RELEASE_INIT:
+ case TS_RFO_INIT:
+ case TS_RBA_INIT:
tapestate_set(ti,TS_FAILED);
wake_up (&ti->wq);
break;
return rc;
}
s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
- wait_event_interruptible (ti->wq,ti->wanna_wakeup);
+ wait_event (ti->wq,ti->wanna_wakeup);
ti->cqr = NULL;
ti->discipline->free_read_block (cqr, ti);
- if (signal_pending (current)) {
- tapestate_set (ti, TS_IDLE);
- return -ERESTARTSYS;
- }
s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
if (tapestate_get (ti) == TS_FAILED) {
tapestate_set (ti, TS_IDLE);
NULL /* next */
};
-bcb_t tub3270_con_bcb; /* Buffer that receives con writes */
-spinlock_t tub3270_con_bcblock; /* Lock for the buffer */
+static bcb_t tub3270_con_bcb; /* Buffer that receives con writes */
+static spinlock_t tub3270_con_bcblock; /* Lock for the buffer */
int tub3270_con_irq = -1; /* set nonneg by _activate() */
tub_t *tub3270_con_tubp; /* set nonzero by _activate() */
struct tty_driver tty3270_con_driver; /* for /dev/console at 4, 64 */
if (tty)
len += sprintf(buf+len,
- " write_wait=%.8x read_wait=%.8x\n",
- (int)&tty->write_wait, (int)&tty->read_wait);
+ " write_wait=%p read_wait=%p\n",
+ &tty->write_wait, &tty->read_wait);
if (tty && ((mp = tty->termios)))
len += sprintf(buf+len," iflag=%.8x oflag=%.8x "
/*
- * $Id: ctcmain.c,v 1.49 2001/08/31 14:50:05 felfert Exp $
+ * $Id: ctcmain.c,v 1.51 2001/09/24 10:38:02 mschwide Exp $
*
* CTC / ESCON network driver
*
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.49 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.51 $
*
*/
\f
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#ifdef MODULE
MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
+MODULE_LICENSE("GPL");
#ifndef CTC_CHANDEV
MODULE_PARM(ctc, "s");
MODULE_PARM_DESC(ctc,
net_device *netdev;
ctc_profile prof;
+
+ unsigned char *trans_skb_data;
} channel;
#define CHANNEL_FLAGS_READ 0
*/
static void print_banner(void) {
static int printed = 0;
- char vbuf[] = "$Revision: 1.49 $";
+ char vbuf[] = "$Revision: 1.51 $";
char *version = vbuf;
if (printed)
return -ENOMEM;
}
ch->ccw[1].count = 0;
+ ch->trans_skb_data = ch->trans_skb->data;
ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
}
return 0;
spin_unlock(&ch->collect_lock);
return;
}
- ch->trans_skb->tail = ch->trans_skb->data;
+ ch->trans_skb->tail = ch->trans_skb->data = ch->trans_skb_data;
ch->trans_skb->len = 0;
if (ch->prof.maxmulti < (ch->collect_len + 2))
ch->prof.maxmulti = ch->collect_len + 2;
int len = ch->max_bufsize - ch->devstat->rescnt;
struct sk_buff *skb = ch->trans_skb;
__u16 block_len = *((__u16*)skb->data);
- char *saved_data = skb->data;
int check_len;
int rc;
ctc_unpack_skb(ch, skb);
}
again:
- skb->data = skb->tail = saved_data;
+ skb->data = skb->tail = ch->trans_skb_data;
skb->len = 0;
if (ctc_checkalloc_buffer(ch, 1))
return;
channel *ch = (channel *)arg;
net_device *dev = ch->netdev;
+ fsm_deltimer(&ch->timer);
printk(KERN_DEBUG "%s: %s channel restart\n", dev->name,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
-
fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
oldstate = fsm_getstate(fi);
fsm_newstate(fi, CH_STATE_STARTWAIT);
#ifdef DEBUG
printk(KERN_DEBUG "ccw[4].cda = %08x\n", ch->ccw[4].cda);
#endif
- rc = do_IO(ch->irq, &ch->ccw[3],
- (intparm_t)ch, 0xff, 0);
+ rc = do_IO(ch->irq, &ch->ccw[3], (intparm_t)ch, 0xff, 0);
if (event == CH_EVENT_TIMER)
s390irq_spin_unlock_irqrestore(ch->irq,
saveflags);
if (rc != 0) {
fsm_deltimer(&ch->timer);
ccw_check_return_code(ch, rc);
- skb_dequeue_tail(&ch->io_queue);
+ if (ccw_idx == 3)
+ skb_dequeue_tail(&ch->io_queue);
/**
* Remove our header. It gets added
* again on retransmit.
#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/init.h>
#include <linux/tqueue.h>
#include <linux/interrupt.h>
#undef DEBUG
-#ifndef min
-#define min(a,b) (((a)<(b))?(a):(b))
-#endif
-
/* FLAGS:
* All flags are defined in the field IPFLAGS1 of each function
* and can be found in CP Programming Services.
parm = (iparml_db *)grab_param();
- parm->ipbfadr1 = (__u32) buffer;
+ parm->ipbfadr1 = (__u32) (addr_t) buffer;
parm->ipbfln1f = (__u32) ((ulong) buflen);
parm->ipmsgid = msgid;
parm->ippathid = pathid;
if (residual_buffer)
*residual_buffer = parm->ipbfadr1;
} else {
- moved = min (buflen, 8);
+ moved = min_t (unsigned long, buflen, 8);
memcpy ((char *) buffer,
(char *) &parm->ipbfadr1, moved);
while ((moved < 8) && (moved < buflen)) {
dyn_len =
- min ((buffer + i)->length, need_to_move);
+ min_t (unsigned int,
+ (buffer + i)->length, need_to_move);
memcpy ((char *)((ulong)((buffer + i)->address)),
((char *) &parm->ipbfadr1) + moved,
/*
- * $Id: netiucv.c,v 1.11 2001/07/16 17:00:02 felfert Exp $
+ * $Id: netiucv.c,v 1.12 2001/09/24 10:38:02 mschwide Exp $
*
* IUCV network driver
*
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV network driver $Revision: 1.11 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.12 $
*
*/
\f
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/interrupt.h>
static void
netiucv_banner(void)
{
- char vbuf[] = "$Revision: 1.11 $";
+ char vbuf[] = "$Revision: 1.12 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
return 0;
}
-module_init(netiucv_init);
#ifdef MODULE
+module_init(netiucv_init);
module_exit(netiucv_exit);
+MODULE_LICENSE("GPL");
#endif
module_init(amd7930_init);
module_exit(amd7930_exit);
+MODULE_LICENSE("GPL");
/*************************************************************/
/* Audio format conversion */
module_init(bpp_init);
module_exit(bpp_cleanup);
-MODULE_LICENSE("GPL");
* */
/* CHANGELOG
+ *
+ * Version 2.6
+ *
+ * Following test of the 64 bit parisc kernel by Richard Hirst,
+ * several problems have now been corrected. Also adds support for
+ * consistent memory allocation.
*
* Version 2.5
*
* Initial modularisation from the D700. See NCR_D700.c for the rest of
* the changelog.
* */
-#define NCR_700_VERSION "2.5"
+#define NCR_700_VERSION "2.6"
#include <linux/config.h>
#include <linux/version.h>
NCR_700_detect(Scsi_Host_Template *tpnt,
struct NCR_700_Host_Parameters *hostdata)
{
- dma_addr_t pScript, pSlots;
+ dma_addr_t pScript, pMemory, pSlots;
+ __u8 *memory;
__u32 *script;
struct Scsi_Host *host;
static int banner = 0;
int j;
- /* This separation of pScript and script is not strictly
- * necessay, but may be useful in architectures which can
- * allocate consistent memory on which virt_to_bus will not
- * work */
- script = kmalloc(sizeof(SCRIPT), GFP_KERNEL);
- pScript = virt_to_bus(script);
+#ifdef CONFIG_53C700_USE_CONSISTENT
+ memory = pci_alloc_consistent(hostdata->pci_dev, TOTAL_MEM_SIZE,
+ &pMemory);
+ hostdata->consistent = 1;
+ if(memory == NULL ) {
+ printk(KERN_WARNING "53c700: consistent memory allocation failed\n");
+#endif
+ memory = kmalloc(TOTAL_MEM_SIZE, GFP_KERNEL);
+ if(memory == NULL) {
+ printk(KERN_ERR "53c700: Failed to allocate memory for driver, detatching\n");
+ return NULL;
+ }
+ pMemory = pci_map_single(hostdata->pci_dev, memory,
+ TOTAL_MEM_SIZE, PCI_DMA_BIDIRECTIONAL);
+#ifdef CONFIG_53C700_USE_CONSISTENT
+ hostdata->consistent = 0;
+ }
+#endif
+ script = (__u32 *)memory;
+ pScript = pMemory;
+ hostdata->msgin = memory + MSGIN_OFFSET;
+ hostdata->msgout = memory + MSGOUT_OFFSET;
+ hostdata->status = memory + STATUS_OFFSET;
+ hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET);
+
+ pSlots = pMemory + SLOTS_OFFSET;
/* Fill in the missing routines from the host template */
tpnt->queuecommand = NCR_700_queuecommand;
if((host = scsi_register(tpnt, 4)) == NULL)
return NULL;
- if(script == NULL) {
- printk(KERN_ERR "53c700: Failed to allocate script, detatching\n");
- scsi_unregister(host);
- return NULL;
- }
-
- /* This separation of slots and pSlots may facilitate later
- * migration to consistent memory on architectures which
- * support it */
- hostdata->slots = kmalloc(sizeof(struct NCR_700_command_slot)
- * NCR_700_COMMAND_SLOTS_PER_HOST,
- GFP_KERNEL);
- pSlots = virt_to_bus(hostdata->slots);
-
- hostdata->msgin = kmalloc(MSG_ARRAY_SIZE, GFP_KERNEL);
- hostdata->msgout = kmalloc(MSG_ARRAY_SIZE, GFP_KERNEL);
- hostdata->status = kmalloc(MSG_ARRAY_SIZE, GFP_KERNEL);
- if(hostdata->slots == NULL || hostdata->msgin == NULL
- || hostdata->msgout == NULL || hostdata->status==NULL) {
- printk(KERN_ERR "53c700: Failed to allocate command slots or message buffers, detatching\n");
- scsi_unregister(host);
- return NULL;
- }
memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot)
* NCR_700_COMMAND_SLOTS_PER_HOST);
for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) {
for(j = 0; j < PATCHES; j++) {
script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]);
}
- /* now patch up fixed addresses.
- * NOTE: virt_to_bus may be wrong if consistent memory is used
- * for these in the future */
+ /* now patch up fixed addresses. */
script_patch_32(script, MessageLocation,
- virt_to_bus(&hostdata->msgout[0]));
+ pScript + MSGOUT_OFFSET);
script_patch_32(script, StatusAddress,
- virt_to_bus(&hostdata->status[0]));
+ pScript + STATUS_OFFSET);
script_patch_32(script, ReceiveMsgAddress,
- virt_to_bus(&hostdata->msgin[0]));
+ pScript + MSGIN_OFFSET);
hostdata->script = script;
hostdata->pScript = pScript;
- dma_cache_wback((unsigned long)script, sizeof(SCRIPT));
+ NCR_700_dma_cache_wback((unsigned long)script, sizeof(SCRIPT));
hostdata->state = NCR_700_HOST_FREE;
spin_lock_init(&hostdata->lock);
hostdata->cmd = NULL;
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)host->hostdata[0];
- /* NOTE: these may be NULL if we weren't fully initialised before
- * the scsi_unregister was called */
- kfree(hostdata->script);
- kfree(hostdata->slots);
- kfree(hostdata->msgin);
- kfree(hostdata->msgout);
- kfree(hostdata->status);
+#ifdef CONFIG_53C700_USE_CONSISTENT
+ if(hostdata->consistent) {
+ pci_free_consistent(hostdata->pci_dev, TOTAL_MEM_SIZE,
+ hostdata->script, hostdata->pScript);
+ } else {
+#endif
+ pci_unmap_single(hostdata->pci_dev, hostdata->pScript,
+ TOTAL_MEM_SIZE, PCI_DMA_BIDIRECTIONAL);
+ kfree(hostdata->script);
+#ifdef CONFIG_53C700_USE_CONSISTENT
+ }
+#endif
return 1;
}
}
return (offset & 0x0f) | (XFERP & 0x07)<<4;
}
-
+
+STATIC inline void
+NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp,
+ struct NCR_700_command_slot *slot)
+{
+ if(SCp->sc_data_direction != SCSI_DATA_NONE &&
+ SCp->sc_data_direction != SCSI_DATA_UNKNOWN) {
+ int pci_direction = scsi_to_pci_dma_dir(SCp->sc_data_direction);
+ if(SCp->use_sg) {
+ pci_unmap_sg(hostdata->pci_dev, SCp->buffer,
+ SCp->use_sg, pci_direction);
+ } else {
+ pci_unmap_single(hostdata->pci_dev,
+ slot->dma_handle,
+ SCp->request_bufflen,
+ pci_direction);
+ }
+ }
+}
STATIC inline void
NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
if(SCp != NULL) {
struct NCR_700_command_slot *slot =
(struct NCR_700_command_slot *)SCp->host_scribble;
-
+
+ NCR_700_unmap(hostdata, SCp, slot);
+ pci_unmap_single(hostdata->pci_dev, slot->pCmd,
+ sizeof(SCp->cmnd), PCI_DMA_TODEVICE);
if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) {
#ifdef NCR_700_DEBUG
printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n",
SCp, SCp->cmnd[7], result);
print_sense("53c700", SCp);
+
#endif
+ SCp->use_sg = SCp->cmnd[8];
if(result == 0)
result = SCp->cmnd[7];
}
- if(SCp->sc_data_direction != SCSI_DATA_NONE &&
- SCp->sc_data_direction != SCSI_DATA_UNKNOWN) {
- int pci_direction = scsi_to_pci_dma_dir(SCp->sc_data_direction);
- if(SCp->use_sg) {
- pci_unmap_sg(hostdata->pci_dev, SCp->buffer,
- SCp->use_sg, pci_direction);
- } else {
- pci_unmap_single(hostdata->pci_dev,
- slot->dma_handle,
- SCp->request_bufflen,
- pci_direction);
- }
- }
-
free_slot(slot, hostdata);
SCp->host_scribble = NULL;
printk(KERN_WARNING "scsi%d Unexpected SDTR msg\n",
host->host_no);
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_wback((unsigned long)hostdata->msgout, 1);
+ NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1);
script_patch_16(hostdata->script, MessageCount, 1);
/* SendMsgOut returns, so set up the return
* address */
printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n",
host->host_no, pun, lun);
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_wback((unsigned long)hostdata->msgout, 1);
+ NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1);
script_patch_16(hostdata->script, MessageCount, 1);
resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_wback((unsigned long)hostdata->msgout, 1);
+ NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1);
script_patch_16(hostdata->script, MessageCount, 1);
/* SendMsgOut returns, so set up the return
* address */
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_wback((unsigned long)hostdata->msgout, 1);
+ NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, 1);
script_patch_16(hostdata->script, MessageCount, 1);
/* SendMsgOut returns, so set up the return
* address */
}
NCR_700_writel(temp, host, TEMP_REG);
/* set us up to receive another message */
- dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);
+ NCR_700_dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);
return resume_offset;
}
printk(" cmd %p has status %d, requesting sense\n",
SCp, hostdata->status[0]);
#endif
- /* we can destroy the command here because the
- * contingent allegiance condition will cause a
- * retry which will re-copy the command from the
- * saved data_cmnd */
+ /* we can destroy the command here
+ * because the contingent allegiance
+ * condition will cause a retry which
+ * will re-copy the command from the
+ * saved data_cmnd. We also unmap any
+ * data associated with the command
+ * here */
+ NCR_700_unmap(hostdata, SCp, slot);
+
SCp->cmnd[0] = REQUEST_SENSE;
SCp->cmnd[1] = (SCp->lun & 0x7) << 5;
SCp->cmnd[2] = 0;
SCp->cmnd[4] = sizeof(SCp->sense_buffer);
SCp->cmnd[5] = 0;
SCp->cmd_len = 6;
- /* Here's a quiet hack: the REQUEST_SENSE command is
- * six bytes, so store a flag indicating that this
- * was an internal sense request and the original
- * status at the end of the command */
+ /* Here's a quiet hack: the
+ * REQUEST_SENSE command is six bytes,
+ * so store a flag indicating that
+ * this was an internal sense request
+ * and the original status at the end
+ * of the command */
SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC;
SCp->cmnd[7] = hostdata->status[0];
+ SCp->cmnd[8] = SCp->use_sg;
+ SCp->use_sg = 0;
SCp->sc_data_direction = SCSI_DATA_READ;
- dma_cache_wback((unsigned long)SCp->cmnd, SCp->cmd_len);
+ pci_dma_sync_single(hostdata->pci_dev,
+ slot->pCmd,
+ SCp->cmd_len,
+ PCI_DMA_TODEVICE);
+ slot->dma_handle = pci_map_single(hostdata->pci_dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), PCI_DMA_FROMDEVICE);
slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer));
- slot->SG[0].pAddr = bS_to_host(virt_to_bus(SCp->sense_buffer));
+ slot->SG[0].pAddr = bS_to_host(slot->dma_handle);
slot->SG[1].ins = bS_to_host(SCRIPT_RETURN);
slot->SG[1].pAddr = 0;
slot->resume_offset = hostdata->pScript;
- dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG[0])*2);
- dma_cache_inv((unsigned long)SCp->sense_buffer, sizeof(SCp->sense_buffer));
+ NCR_700_dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG[0])*2);
+ NCR_700_dma_cache_inv((unsigned long)SCp->sense_buffer, sizeof(SCp->sense_buffer));
/* queue the command for reissue */
slot->state = NCR_700_SLOT_QUEUED;
/* re-patch for this command */
script_patch_32_abs(hostdata->script, CommandAddress,
- virt_to_bus(slot->cmnd->cmnd));
+ slot->pCmd);
script_patch_16(hostdata->script,
CommandCount, slot->cmnd->cmd_len);
script_patch_32_abs(hostdata->script, SGScriptStartAddress,
* should therefore always clear ACK */
NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device),
host, SXFER_REG);
- dma_cache_inv((unsigned long)hostdata->msgin,
+ NCR_700_dma_cache_inv((unsigned long)hostdata->msgin,
MSG_ARRAY_SIZE);
- dma_cache_wback((unsigned long)hostdata->msgout,
+ NCR_700_dma_cache_wback((unsigned long)hostdata->msgout,
MSG_ARRAY_SIZE);
/* I'm just being paranoid here, the command should
* already have been flushed from the cache */
- dma_cache_wback((unsigned long)slot->cmnd->cmnd,
+ NCR_700_dma_cache_wback((unsigned long)slot->cmnd->cmnd,
slot->cmnd->cmd_len);
hostdata->reselection_id = reselection_id;
/* just in case we have a stale simple tag message, clear it */
hostdata->msgin[1] = 0;
- dma_cache_wback_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);
+ NCR_700_dma_cache_wback_inv((unsigned long)hostdata->msgin,
+ MSG_ARRAY_SIZE);
if(hostdata->tag_negotiated & (1<<reselection_id)) {
resume_offset = hostdata->pScript + Ent_GetReselectionWithTag;
} else {
hostdata->cmd = NULL;
/* clear any stale simple tag message */
hostdata->msgin[1] = 0;
- dma_cache_wback_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);
+ NCR_700_dma_cache_wback_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);
if(id == 0xff) {
/* Selected as target, Ignore */
* set up so we cannot take a selection interrupt */
hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE,
- SCp->lun);
+ SCp->lun);
/* for INQUIRY or REQUEST_SENSE commands, we cannot be sure
* if the negotiated transfer parameters still hold, so
* always renegotiate them */
Device_ID, 1<<SCp->target);
script_patch_32_abs(hostdata->script, CommandAddress,
- virt_to_bus(SCp->cmnd));
+ slot->pCmd);
script_patch_16(hostdata->script, CommandCount, SCp->cmd_len);
/* finally plumb the beginning of the SG list into the script
* */
if(slot->resume_offset == 0)
slot->resume_offset = hostdata->pScript;
/* now perform all the writebacks and invalidates */
- dma_cache_wback((unsigned long)hostdata->msgout, count);
- dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);
- dma_cache_wback((unsigned long)SCp->cmnd, SCp->cmd_len);
- dma_cache_inv((unsigned long)hostdata->status, 1);
+ NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, count);
+ NCR_700_dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);
+ NCR_700_dma_cache_wback((unsigned long)SCp->cmnd, SCp->cmd_len);
+ NCR_700_dma_cache_inv((unsigned long)hostdata->status, 1);
/* set the synchronous period/offset */
NCR_700_writeb(NCR_700_get_SXFER(SCp->device),
DEBUG(("scsi%d: istat %02x sstat0 %02x dstat %02x dsp %04x[%08x] dsps 0x%x\n",
host->host_no, istat, sstat0, dstat,
- (dsp - (__u32)virt_to_bus(hostdata->script))/4,
+ (dsp - (__u32)(hostdata->pScript))/4,
dsp, dsps));
if(SCp != NULL) {
slot->SG[i].ins = bS_to_host(SCRIPT_NOP);
slot->SG[i].pAddr = 0;
}
- dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG));
+ NCR_700_dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG));
/* and pretend we disconnected after
* the command phase */
resume_offset = hostdata->pScript + Ent_MsgInDuringData;
#endif
if(old != NULL && old->tag == SCp->device->current_tag) {
- printk(KERN_WARNING "scsi%d (%d:%d) Tag clock back to current, queueing\n", SCp->host->host_no, SCp->target, SCp->lun);
+ /* On some badly starving drives, this can be
+ * a frequent occurance, so print the message
+ * only once */
+ if(NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_TAG_STARVATION_WARNED)) {
+ printk(KERN_WARNING "scsi%d (%d:%d) Target is suffering from tag starvation.\n", SCp->host->host_no, SCp->target, SCp->lun);
+ NCR_700_set_flag(SCp->device, NCR_700_DEV_TAG_STARVATION_WARNED);
+ }
return 1;
}
slot->tag = SCp->device->current_tag++;
hostdata->ITL_Hash_back[hash] = slot;
slot->ITL_back = NULL;
+ /* sanity check: some of the commands generated by the mid-layer
+ * have an eccentric idea of their sc_data_direction */
+ if(!SCp->use_sg && !SCp->request_bufflen
+ && SCp->sc_data_direction != SCSI_DATA_NONE) {
+#ifdef NCR_700_DEBUG
+ printk("53c700: Command");
+ print_command(SCp->cmnd);
+ printk("Has wrong data direction %d\n", SCp->sc_data_direction);
+#endif
+ SCp->sc_data_direction = SCSI_DATA_NONE;
+ }
+
switch (SCp->cmnd[0]) {
case REQUEST_SENSE:
/* clear the internal sense magic */
}
slot->SG[i].ins = bS_to_host(SCRIPT_RETURN);
slot->SG[i].pAddr = 0;
- dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG));
+ NCR_700_dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG));
DEBUG((" SETTING %08lx to %x\n",
- virt_to_bus(&slot->SG[i].ins),
+ (&slot->pSG[i].ins),
slot->SG[i].ins));
}
slot->resume_offset = 0;
+ slot->pCmd = pci_map_single(hostdata->pci_dev, SCp->cmnd,
+ sizeof(SCp->cmnd), PCI_DMA_TODEVICE);
NCR_700_start_command(SCp);
return 0;
}
#error "Config.in must define either CONFIG_53C700_IO_MAPPED or CONFIG_53C700_MEM_MAPPED to use this scsi core."
#endif
+/* macros for consistent memory allocation */
+
+#ifdef CONFIG_53C700_USE_CONSISTENT
+#define NCR_700_dma_cache_wback(mem, size) \
+ if(!hostdata->consistent) \
+ dma_cache_wback(mem, size)
+#define NCR_700_dma_cache_inv(mem, size) \
+ if(!hostdata->consistent) \
+ dma_cache_inv(mem, size)
+#define NCR_700_dma_cache_wback_inv(mem, size) \
+ if(!hostdata->consistent) \
+ dma_cache_wback_inv(mem, size)
+#else
+#define NCR_700_dma_cache_wback(mem, size) dma_cache_wback(mem,size)
+#define NCR_700_dma_cache_inv(mem, size) dma_cache_inv(mem,size)
+#define NCR_700_dma_cache_wback_inv(mem, size) dma_cache_wback_inv(mem,size)
+#endif
+
struct NCR_700_Host_Parameters;
#define NCR_700_DEV_NEGOTIATED_SYNC (1<<16)
#define NCR_700_DEV_BEGIN_SYNC_NEGOTIATION (1<<17)
#define NCR_700_DEV_BEGIN_TAG_QUEUEING (1<<18)
+#define NCR_700_DEV_TAG_STARVATION_WARNED (1<<19)
static inline void
NCR_700_set_SXFER(Scsi_Device *SDp, __u8 sxfer)
__u16 tag;
__u32 resume_offset;
Scsi_Cmnd *cmnd;
+ /* The pci_mapped address of the actual command in cmnd */
+ dma_addr_t pCmd;
__u32 temp;
/* if this command is a pci_single mapping, holds the dma address
* for later unmapping in the done routine */
int clock; /* board clock speed in MHz */
__u32 base; /* the base for the port (copied to host) */
struct pci_dev *pci_dev;
- __u8 dmode_extra; /* adjustable bus settings */
- __u8 differential:1; /* if we are differential */
+ __u32 dmode_extra; /* adjustable bus settings */
+ __u32 differential:1; /* if we are differential */
#ifdef CONFIG_53C700_LE_ON_BE
/* This option is for HP only. Set it if your chip is wired for
* little endian on this platform (which is big endian) */
- __u8 force_le_on_be:1;
+ __u32 force_le_on_be:1;
#endif
- __u8 chip710:1; /* set if really a 710 not 700 */
- __u8 burst_disable:1; /* set to 1 to disable 710 bursting */
+ __u32 chip710:1; /* set if really a 710 not 700 */
+ __u32 burst_disable:1; /* set to 1 to disable 710 bursting */
/* NOTHING BELOW HERE NEEDS ALTERING */
- __u8 fast:1; /* if we can alter the SCSI bus clock
+ __u32 fast:1; /* if we can alter the SCSI bus clock
speed (so can negiotiate sync) */
+#ifdef CONFIG_53C700_USE_CONSISTENT
+ __u32 consistent:1;
+#endif
int sync_clock; /* The speed of the SYNC core */
spinlock_t lock;
enum NCR_700_Host_State state; /* protected by state lock */
Scsi_Cmnd *cmd;
-
+ /* Note: pScript contains the single consistent block of
+ * memory. All the msgin, msgout and status are allocated in
+ * this memory too (at separate cache lines). TOTAL_MEM_SIZE
+ * represents the total size of this area */
+#define MSG_ARRAY_SIZE 8
+#define MSGOUT_OFFSET (L1_CACHE_ALIGN(sizeof(SCRIPT)))
__u8 *msgout;
-#define MSG_ARRAY_SIZE 16
- __u8 tag_negotiated;
- __u8 *status;
+#define MSGIN_OFFSET (MSGOUT_OFFSET + L1_CACHE_ALIGN(MSG_ARRAY_SIZE))
__u8 *msgin;
+#define STATUS_OFFSET (MSGIN_OFFSET + L1_CACHE_ALIGN(MSG_ARRAY_SIZE))
+ __u8 *status;
+#define SLOTS_OFFSET (STATUS_OFFSET + L1_CACHE_ALIGN(MSG_ARRAY_SIZE))
struct NCR_700_command_slot *slots;
+#define TOTAL_MEM_SIZE (SLOTS_OFFSET + L1_CACHE_ALIGN(sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST))
int saved_slot_position;
int command_slot_count; /* protected by state lock */
+ __u8 tag_negotiated;
__u8 rev;
__u8 reselection_id;
/* flags for the host */
fi
fi
if [ "$CONFIG_PARISC" = "y" ]; then
- dep_tristate 'HP LASI SCSI support for 53c700' CONFIG_SCSI_LASI700 $CONFIG_SCSI
+ dep_tristate 'HP LASI SCSI support for 53c700/710' CONFIG_SCSI_LASI700 $CONFIG_SCSI
if [ "$CONFIG_SCSI_LASI700" != "n" ]; then
define_bool CONFIG_53C700_MEM_MAPPED y
define_bool CONFIG_53C700_LE_ON_BE y
+ define_bool CONFIG_53C700_USE_CONSISTENT y
fi
fi
dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI $CONFIG_PCI
-This driver supports the 53c700 and 53c700-66 chips only. It is full
-featured and does sync (-66 only), disconnects and tag command
-queueing.
+General Description
+===================
+
+This driver supports the 53c700 and 53c700-66 chips. It also supports
+the 53c710 but only in 53c700 emulation mode. It is full featured and
+does sync (-66 and 710 only), disconnects and tag command queueing.
Since the 53c700 must be interfaced to a bus, you need to wrapper the
card detector around this driver. For an example, see the
-NCR_D700.[ch] files.
+NCR_D700.[ch] or lasi700.[ch] files.
The comments in the 53c700.[ch] files tell you which parts you need to
fill in to get the driver working.
-The driver is currently I/O mapped only, but it should be easy enough
-to memory map (just make the port reads #defines with MEM_MAPPED for
-memory mapping or nothing for I/O mapping, specify an extra rule for
-53c700-mem.o with the -DMEM_MAPPED flag and make your driver use it,
-that way the make rules will generate the correct version).
+
+Compile Time Flags
+==================
+
+The driver may be either io mapped or memory mapped. This is
+selectable by configuration flags:
+
+CONFIG_53C700_MEM_MAPPED
+
+define if the driver is memory mapped.
+
+CONFIG_53C700_IO_MAPPED
+
+define if the driver is to be io mapped.
+
+One or other of the above flags *must* be defined.
+
+Other flags are:
+
+CONFIG_53C700_LE_ON_BE
+
+define if the chipset must be supported in little endian mode on a big
+endian architecture (used for the 700 on parisc).
+
+CONFIG_53C700_USE_CONSISTENT
+
+allocate consistent memory (should only be used if your architecture
+has a mixture of consistent and inconsistent memory). Fully
+consistent or fully inconsistent architectures should not define this.
+
+
+Using the Chip Core Driver
+==========================
+
+In order to plumb the 53c700 chip core driver into a working SCSI
+driver, you need to know three things about the way the chip is wired
+into your system (or expansion card).
+
+1. The clock speed of the SCSI core
+2. The interrupt line used
+3. The memory (or io space) location of the 53c700 registers.
+
+Optionally, you may also need to know other things, like how to read
+the SCSI Id from the card bios or whether the chip is wired for
+differential operation.
+
+Usually you can find items 2. and 3. from general spec. documents or
+even by examining the configuration of a working driver under another
+operating system.
+
+The clock speed is usually buried deep in the technical literature.
+It is required because it is used to set up both the synchronous and
+asynchronous dividers for the chip. As a general rule of thumb,
+manufacturers set the clock speed at the lowest possible setting
+consistent with the best operation of the chip (although some choose
+to drive it off the CPU or bus clock rather than going to the expense
+of an extra clock chip). The best operation clock speeds are:
+
+53c700 - 25MHz
+53c700-66 - 50MHz
+53c710 - 40Mhz
+
+Writing Your Glue Driver
+========================
+
+This will be a standard SCSI driver (I don't know of a good document
+describing this, just copy from some other driver) with at least a
+detect and release entry.
+
+In the detect routine, you need to allocate a struct
+NCR_700_Host_Parameters sized memory area and clear it (so that the
+default values for everything are 0). Then you must fill in the
+parameters that matter to you (see below), plumb the NCR_700_intr
+routine into the interrupt line and call NCR_700_detect with the host
+template and the new parameters as arguments. You should also call
+the relevant request_*_region function and place the register base
+address into the `base' pointer of the host parameters.
+
+In the release routine, you must free the NCR_700_Host_Parameters that
+you allocated, call the corresponding release_*_region and free the
+interrupt.
+
+Handling Interrupts
+-------------------
+
+In general, you should just plumb the card's interrupt line in with
+
+request_irq(irq, NCR_700_intr, <irq flags>, <driver name>, host);
+
+where host is the return from the relevant NCR_700_detect() routine.
+
+You may also write your own interrupt handling routine which calls
+NCR_700_intr() directly. However, you should only really do this if
+you have a card with more than one chip on it and you can read a
+register to tell which set of chips wants the interrupt.
+
+Settable NCR_700_Host_Parameters
+--------------------------------
+
+The following are a list of the user settable parameters:
+
+clock: (MANDATORY)
+
+Set to the clock speed of the chip in MHz.
+
+base: (MANDATORY)
+
+set to the base of the io or mem region for the register set. On 64
+bit architectures this is only 32 bits wide, so the registers must be
+mapped into the low 32 bits of memory.
+
+pci_dev: (OPTIONAL)
+
+set to the PCI board device. Leave NULL for a non-pci board. This is
+used for the pci_alloc_consistent() and pci_map_*() functions.
+
+dmode_extra: (OPTIONAL, 53c710 only)
+
+extra flags for the DMODE register. These are used to control bus
+output pins on the 710. The settings should be a combination of
+DMODE_FC1 and DMODE_FC2. What these pins actually do is entirely up
+to the board designer. Usually it is safe to ignore this setting.
+
+differential: (OPTIONAL)
+
+set to 1 if the chip drives a differential bus.
+
+force_le_on_be: (OPTIONAL, only if CONFIG_53C700_LE_ON_BE is set)
+
+set to 1 if the chip is operating in little endian mode on a big
+endian architecture.
+
+chip710: (OPTIONAL)
+
+set to 1 if the chip is a 53c710.
+
+burst_disable: (OPTIONAL, 53c710 only)
+
+disable 8 byte bursting for DMA transfers.
#endif /* !defined(AHA152X_DEBUG) */
#ifdef __ISAPNP__
-
static struct isapnp_device_id id_table[] __devinitdata = {
{ ISAPNP_DEVICE_SINGLE('A','D','P',0x1505, 'A','D','P',0x1505), },
{ ISAPNP_DEVICE_SINGLE_END, }
};
MODULE_DEVICE_TABLE(isapnp, id_table);
-
#endif /* ISAPNP */
#endif /* MODULE */
}
printk("ok\n");
}
-#ifdef __ISAPNP__
- while (setup_count <= 2 &&
- (dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('A','D','P'),
- ISAPNP_FUNCTION(0x1505), dev))) {
- if (dev->prepare(dev) < 0)
- continue;
- if (dev->active)
- continue;
- if (!(dev->resource[0].flags & IORESOURCE_IO))
- continue;
- dev->resource[0].flags |= IORESOURCE_AUTO;
- if (dev->activate(dev) < 0)
- continue;
- setup[setup_count].io_port = dev->resource[0].start;
- setup[setup_count].irq = dev->irq_resource[0].start;
- pnpdev[num_pnpdevs++] = dev;
- printk (KERN_INFO
- "aha152x: found ISAPnP AVA-1505A at address 0x%03X, IRQ %d\n",
- setup[setup_count].io_port, setup[setup_count].irq);
- setup_count++;
- }
-#endif
#if defined(SETUP0)
if (setup_count < 2) {
}
#endif
+#ifdef __ISAPNP__
+ while ( setup_count<2 && (dev=isapnp_find_dev(NULL, ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), dev)) ) {
+ if (dev->prepare(dev) < 0)
+ continue;
+ if (dev->active)
+ continue;
+ if (!(dev->resource[0].flags & IORESOURCE_IO))
+ continue;
+ dev->resource[0].flags |= IORESOURCE_AUTO;
+ if (dev->activate(dev) < 0)
+ continue;
+ if ( setup_count==1 && dev->resource[0].start==setup[0].io_port) {
+ dev->deactivate(dev);
+ continue;
+ }
+ setup[setup_count].io_port = dev->resource[0].start;
+ setup[setup_count].irq = dev->irq_resource[0].start;
+ setup[setup_count].scsiid = 7;
+ setup[setup_count].reconnect = 1;
+ setup[setup_count].parity = 1;
+ setup[setup_count].synchronous = 1;
+ setup[setup_count].delay = DELAY_DEFAULT;
+ setup[setup_count].ext_trans = 0;
+#if defined(AHA152X_DEBUG)
+ setup[setup_count].debug = DEBUG_DEFAULT;
+#endif
+ pnpdev[num_pnpdevs++] = dev;
+ printk (KERN_INFO
+ "aha152x: found ISAPnP AVA-1505A at io=0x%03x, irq=%d\n",
+ setup[setup_count].io_port, setup[setup_count].irq);
+ setup_count++;
+ }
+#endif
+
+
#if defined(AUTOCONF)
if (setup_count < 2) {
#if !defined(SKIP_BIOSTEST)
*/
#include <linux/module.h>
-
-#if defined(PCMCIA)
-# undef MODULE
-#endif
-
#include <stdarg.h>
#include <asm/io.h>
#include <asm/irq.h>
#endif
#if defined __alpha__
-static void adpt_sparc_info(sysInfo_S* si)
+static void adpt_alpha_info(sysInfo_S* si)
{
// This is all the info we need for now
// We will add more info as our new
static Scsi_Host_Template driver_template = DPT_I2O;
#include "scsi_module.c"
EXPORT_NO_SYMBOLS;
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("GPL");
**************************************************************************/
#include <linux/config.h>
+#include <linux/types.h>
#define ULONG unsigned long
#define PVOID void *
#define UBYTE unsigned char
#define UWORD unsigned short
#define UDWORD unsigned long
-#ifdef ALPHA
-#define U32 unsigned int
-#else
-#define U32 unsigned long
-#endif
+#define U32 u32
#ifndef NULL
#define NULL 0 /* zero */
**************************************************************************/
#include <linux/config.h>
+#include <linux/types.h>
#define ULONG unsigned long
#define USHORT unsigned short
#define UBYTE unsigned char
#define UWORD unsigned short
#define UDWORD unsigned long
-#ifdef ALPHA
-#define U32 unsigned int
-#else
-#define U32 unsigned long
-#endif
+#define U32 u32
#ifndef NULL
#define NULL 0 /* zero */
#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
#endif
+#include <linux/types.h>
#include "sd.h"
#define ULONG unsigned long
#define USHORT unsigned short
#define UCHAR unsigned char
-#define BYTE unsigned char
+#define BYTE u8
#define WORD unsigned short
#define DWORD unsigned long
-#define UBYTE unsigned char
+#define UBYTE u8
#define UWORD unsigned short
#define UDWORD unsigned long
-#ifdef ALPHA
-#define U32 unsigned int
-#else
-#define U32 unsigned long
-#endif
+#define U32 u32
#ifndef NULL
#define NULL 0 /* zero */
#include <linux/version.h>
#endif
+#include <linux/types.h>
+
#include "sd.h"
extern int inia100_detect(Scsi_Host_Template *);
#define UBYTE unsigned char
#define UWORD unsigned short
#define UDWORD unsigned long
-#ifdef ALPHA
-#define U32 unsigned int
-#else
-#define U32 unsigned long
-#endif
+#define U32 u32
#ifndef NULL
#define NULL 0 /* zero */
***********************************************************************/
-/* $Id: nsp_cs.c,v 1.35 2001/07/05 16:58:24 elca Exp $ */
+/* $Id: nsp_cs.c,v 1.42 2001/09/10 10:30:58 elca Exp $ */
#ifdef NSP_KERNEL_2_2
#include <pcmcia/config.h>
MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module");
-MODULE_LICENSE("GPL");
-
MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
+MODULE_LICENSE("GPL");
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
MODULE_PARM_DESC(pc_debug, "set debug level");
-static char *version = "$Id: nsp_cs.c,v 1.35 2001/07/05 16:58:24 elca Exp $";
+static char *version = "$Id: nsp_cs.c,v 1.42 2001/09/10 10:30:58 elca Exp $";
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
#else
#define DEBUG(n, args...) /* */
struct bus_operations *bus;
} scsi_info_t;
-static void nsp_cs_release(u_long arg);
-static int nsp_cs_event(event_t event, int priority,
- event_callback_args_t *args);
-static dev_link_t *nsp_cs_attach(void);
-static void nsp_cs_detach(dev_link_t *);
-static int nsp_detect(Scsi_Host_Template * );
-static int nsp_release(struct Scsi_Host *shpnt);
-static const char * nsp_info(struct Scsi_Host *shpnt);
-static int nsp_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-static int nsp_abort(Scsi_Cmnd *);
-static int nsp_reset(Scsi_Cmnd *, unsigned int);
-
/*----------------------------------------------------------------*/
data->CurrentSC = NULL;
SCpnt->result = DID_BAD_TARGET << 16;
done(SCpnt);
- return FALSE;
+ return -1;
}
show_command(SCpnt);
data->CurrentSC = NULL;
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
- return FALSE;
+ return -1;
}
//DEBUG(0, __FUNCTION__ "() out\n");
- return TRUE;
+ return 0;
}
/*
return;
}
-#ifdef DBG_SHOWCOMMAND
+#ifdef PCMCIA_DEBUG
#include "nsp_debug.c"
#endif /* DBG_SHOWCOMMAND */
host->unique_id = data->BaseAddress;
host->n_io_port = data->NumAddress;
host->irq = data->IrqNumber;
- host->dma_channel = -1;
+ host->dma_channel = 0xff; /* not use dms */
sprintf(nspinfo,
/* Buffer size is 100 bytes */
/* 0 1 2 3 4 5 6 7 8 9 0*/
/* 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890*/
- "NinjaSCSI-3/32Bi Driver version 2.7, I/O 0x%04lx-0x%04lx IRQ %2d",
+ "NinjaSCSI-3/32Bi Driver $Revision: 1.42 $, I/O 0x%04lx-0x%04lx IRQ %2d",
host->io_port, host->io_port + host->n_io_port,
host->irq);
sht->name = nspinfo;
return 1; /* detect done. */
}
+/* nsp_cs requires own release handler because its uses dev_id (=data) */
static int nsp_release(struct Scsi_Host *shpnt)
{
nsp_hw_data *data = &nsp_data;
if (shpnt->irq) {
free_irq(shpnt->irq, data);
}
- if (shpnt->io_port) {
+ if (shpnt->io_port && shpnt->n_io_port) {
release_region(shpnt->io_port, shpnt->n_io_port);
}
return 0;
{
DEBUG(0, __FUNCTION__ " SCpnt=0x%p why=%d\n", SCpnt, why);
- return nsp_eh_bus_reset(SCpnt);
+ nsp_eh_bus_reset(SCpnt);
+
+ return SCSI_RESET_SUCCESS;
}
static int nsp_abort(Scsi_Cmnd *SCpnt)
nsp_eh_bus_reset(SCpnt);
- return SUCCESS;
+ return SCSI_ABORT_SUCCESS;
}
/*static int nsp_eh_strategy(struct Scsi_Host *Shost)
DEBUG(0, __FUNCTION__ " SCpnt=0x%p\n", SCpnt);
nsp_eh_bus_reset(SCpnt);
+
return SUCCESS;
}
DEBUG(0, __FUNCTION__ "\n");
nsphw_init(data);
- nsp_eh_bus_reset(SCpnt);
- return SUCCESS;
+ return nsp_eh_bus_reset(SCpnt);
}
Ver 0.1 : Initial version.
This software may be used and distributed according to the terms of
- the GNU Public License.
+ the GNU General Public License.
=========================================================*/
-/* $Id: nsp_cs.h,v 1.21 2001/07/04 14:45:31 elca Exp $ */
+/* $Id: nsp_cs.h,v 1.27 2001/09/10 10:31:13 elca Exp $ */
#ifndef __nsp_cs__
#define __nsp_cs__
/* for debugging */
-/*
-#define DBG
-#define DBG_PRINT
-#define DBG_SHOWCOMMAND
-#define PCMCIA_DEBUG 9
-*/
+/*#define PCMCIA_DEBUG 9*/
/*
#define static
} nsp_hw_data;
+static void nsp_cs_release(u_long arg);
+static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args);
+static dev_link_t *nsp_cs_attach(void);
+static void nsp_cs_detach(dev_link_t *);
+
static unsigned int nsphw_start_selection(Scsi_Cmnd *SCpnt, nsp_hw_data *data);
static void nsp_start_timer(Scsi_Cmnd *SCpnt, nsp_hw_data *data, int time);
+static int nsp_detect(Scsi_Host_Template * );
+static int nsp_release(struct Scsi_Host *shpnt);
+static const char * nsp_info(struct Scsi_Host *shpnt);
+static int nsp_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+
+static int nsp_abort(Scsi_Cmnd *);
+static int nsp_reset(Scsi_Cmnd *, unsigned int);
+
static int nsp_eh_abort(Scsi_Cmnd * SCpnt);
static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);
static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt);
static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt);
-static int nsp_fifo_count(Scsi_Cmnd *SCpnt);
+static int nsp_fifo_count(Scsi_Cmnd *SCpnt);
static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data);
-static int nsp_nexus(Scsi_Cmnd *SCpnt, nsp_hw_data *data);
+static int nsp_nexus(Scsi_Cmnd *SCpnt, nsp_hw_data *data);
#ifdef PCMCIA_DEBUG
-# ifdef DBG_SHOWCOMMAND
static void show_command(Scsi_Cmnd *ptr);
static void show_phase(Scsi_Cmnd *SCpnt);
static void show_busphase(unsigned char stat);
static void show_message(nsp_hw_data *data);
-# endif /* DBG_SHOWCOMMAND */
#else
# define show_command(ptr) /* */
# define show_phase(SCpnt) /* */
the GNU General Public License.
=========================================================================*/
-/* $Id: nsp_debug.c,v 1.6 2001/07/04 14:43:53 elca Exp $ */
+/* $Id: nsp_debug.c,v 1.8 2001/09/07 04:32:28 elca Exp $ */
/*
* Show the command data of a command
}
}
-void print_commandk (unsigned char *command)
+static void print_commandk (unsigned char *command)
{
int i,s;
printk(KERN_DEBUG);
By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
This software may be used and distributed according to the terms of
- the GNU Public License.
+ the GNU General Public License.
*/
-/* $Id: nsp_io.h,v 1.8 2001/01/30 05:16:02 elca Exp $ */
+/* $Id: nsp_io.h,v 1.9 2001/09/07 04:32:42 elca Exp $ */
#ifndef __NSP_IO_H__
#define __NSP_IO_H__
the GNU General Public License.
*/
-/* $Id: nsp_message.c,v 1.6 2001/07/05 10:56:37 elca Exp $ */
+/* $Id: nsp_message.c,v 1.7 2001/09/07 04:33:01 elca Exp $ */
static void nsp_message_in(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
{
max_scsi_luns : shpnt->max_lun);
sparse_lun = 0;
for (lun = 0, lun0_sl = SCSI_2; lun < max_dev_lun; ++lun) {
+ /* don't probe further for luns > 7 for targets <= SCSI_2 */
+ if ((lun0_sl < SCSI_3) && (lun > 7))
+ break;
+
if (!scan_scsis_single(channel, order_dev, lun, lun0_sl,
&max_dev_lun, &sparse_lun, &SDpnt, shpnt,
scsi_result)
SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0;
SRpnt->sr_sense_buffer[2] = 0;
- SRpnt->sr_data_direction = SCSI_DATA_READ;
+ SRpnt->sr_data_direction = SCSI_DATA_NONE;
scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer,
0/*512*/, SD_TIMEOUT, MAX_RETRIES);
}
#ifdef MODULE
+MODULE_LICENSE("GPL");
+
int init_module(void) {
static int initiated = 0;
* 18/05/2001 - .bss nitpicks, fix a bug in set_dac_channels where it
* was calling prog_dmabuf with s->lock held, call missing
* unlock_kernel in cm_midi_release
+ * 08/10/2001 - use set_current_state in some more places
*
* Carlos Eduardo Gorges <carlos@techlinux.com.br>
* Fri May 25 2001
if (s->dma_dac.mapped || !s->dma_dac.ready)
return 0;
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac.wait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
break;
if (nonblock) {
remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
return -EBUSY;
}
tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;
printk(KERN_DEBUG "cmpci: dma timed out??\n");
}
remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/soundcard.h>
#include <linux/pci.h>
#include <linux/init.h>
#define SND_DEV_DSP16 5
#ifdef M_DEBUG
-static int debug=0;
+static int debug;
#define DPMOD 1 /* per module load */
#define DPSTR 2 /* per 'stream' */
#define DPSYS 3 /* per syscall */
return r;
}
-static struct m3_card *devs = NULL;
+static struct m3_card *devs;
/*
* I'm not very good at laying out functions in a file :)
if (s->dma_dac.mapped || !s->dma_dac.ready)
return 0;
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac.wait, &wait);
for (;;) {
spin_lock_irqsave(&s->lock, flags);
break;
if (nonblock) {
remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
return -EBUSY;
}
tmo = (count * HZ) / s->ratedac;
DPRINTK(DPCRAP,"dma timed out?? %ld\n",jiffies);
}
remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
if(busywait) {
mdelay(delay1);
} else {
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((delay1 * HZ) / 1000);
}
if(busywait) {
mdelay(delay2);
} else {
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((delay2 * HZ) / 1000);
}
if(! try_read_vendor(card))
card->in_suspend++;
add_wait_queue(&card->suspend_queue, &wait);
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
remove_wait_queue(&card->suspend_queue, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
}
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/soundcard.h>
#include <linux/pci.h>
#include <linux/init.h>
/* Our own config: */
hw_cfg->io_base = dev->resource[4].start;
- hw_cfg->irq = 0;
- hw_cfg->dma = -1;
- hw_cfg->dma2 = -1;
+ hw_cfg->irq = dev->irq_resource[0].start;
+ hw_cfg->dma = dev->dma_resource[0].start;
+ hw_cfg->dma2 = dev->dma_resource[1].start;
/* The MSS config: */
mss_cfg->io_base = dev->resource[1].start;
* give pretty output from conf_printf. :)
*/
cfg[card].io_base = io;
- cfg[card].irq = 0;
- cfg[card].dma = -1;
- cfg[card].dma2 = -1;
+ cfg[card].irq = irq;
+ cfg[card].dma = dma;
+ cfg[card].dma2 = dma2;
/* The MSS config: */
cfg_mss[card].io_base = mss_io;
*
* 28-10-2000 Added pnplegacy support
* Daniel Church <dchurch@mbhs.edu>
+ *
+ * 01-10-2001 Added a new flavor of Creative SB AWE64 PnP (CTL00E9).
+ * Jerome Cornet <jcornet@free.fr>
*/
#include <linux/config.h>
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
0,0,0,0,
0,1,1,-1},
+ {"Sound Blaster AWE 64",
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9),
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
+ 0,0,0,0,
+ 0,1,1,-1},
{"ESS 1688",
ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968),
{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
+ { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E9),
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
+
{ ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), 0 },
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* History
+ * v0.14.9d
+ * October 8 2001 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * use set_current_state, properly release resources on failure in
+ * trident_probe, get rid of check_region
* v0.14.9c
* August 10 2001 Peter Wächtler <pwaechtler@loewe-komp.de>
* added support for Tvia (formerly Integraphics/IGST) CyberPro5050
#include <linux/pm.h>
-#define DRIVER_VERSION "0.14.9c"
+#define DRIVER_VERSION "0.14.9d"
/* magic numbers to protect our data structures */
#define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */
for (;;) {
/* It seems that we have to set the current state to TASK_INTERRUPTIBLE
every time to make the process really go to sleep */
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&state->card->lock, flags);
count = dmabuf->count;
if (nonblock) {
remove_wait_queue(&dmabuf->wait, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
return -EBUSY;
}
}
}
remove_wait_queue(&dmabuf->wait, &wait);
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
}
#ifdef CONFIG_PROC_FS
-struct proc_dir_entry *res = NULL;
+struct proc_dir_entry *res;
static int ali_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
{
struct trident_card *card = (struct trident_card *)data;
int i = 0;
u16 temp;
struct pci_dev *pci_dev_m1533 = NULL;
+ int rc = -ENODEV;
if (pci_enable_device(pci_dev))
- return -ENODEV;
+ goto out;
if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) {
printk(KERN_ERR "trident: architecture does not support"
" 30bit PCI busmaster DMA\n");
- return -ENODEV;
+ goto out;
}
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
else
iobase = pci_resource_start(pci_dev, 0);
- if (check_region(iobase, 256)) {
+ if (!request_region(iobase, 256, card_names[pci_id->driver_data])) {
printk(KERN_ERR "trident: can't allocate I/O space at 0x%4.4lx\n",
iobase);
- return -ENODEV;
+ goto out;
}
+ rc = -ENOMEM;
if ((card = kmalloc(sizeof(struct trident_card), GFP_KERNEL)) == NULL) {
printk(KERN_ERR "trident: out of memory\n");
- return -ENOMEM;
+ goto out_release_region;
}
memset(card, 0, sizeof(*card));
/* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
card->hwvolctl = 0;
pci_dev_m1533 = pci_find_device(PCI_VENDOR_ID_AL,PCI_DEVICE_ID_AL_M1533, pci_dev_m1533);
+ rc = -ENODEV;
if (pci_dev_m1533 == NULL)
- return -ENODEV;
+ goto out_proc_fs;
pci_read_config_byte(pci_dev_m1533, 0x63, &bits);
if (bits & (1<<5))
card->hwvolctl = 1;
card->address_interrupt = trident_address_interrupt;
}
- /* claim our iospace and irq */
- request_region(card->iobase, 256, card_names[pci_id->driver_data]);
+ /* claim our irq */
+ rc = -ENODEV;
if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ,
card_names[pci_id->driver_data], card)) {
printk(KERN_ERR "trident: unable to allocate irq %d\n", card->irq);
- release_region(card->iobase, 256);
- kfree(card);
- return -ENODEV;
+ goto out_proc_fs;
}
/* register /dev/dsp */
if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) {
printk(KERN_ERR "trident: couldn't register DSP device!\n");
- release_region(iobase, 256);
- free_irq(card->irq, card);
- kfree(card);
- return -ENODEV;
+ goto out_free_irq;
}
card->mixer_regs_ready = 0;
/* initialize AC97 codec and register /dev/mixer */
kfree (card->ac97_codec[i]);
}
}
- unregister_sound_dsp(card->dev_audio);
- release_region(iobase, 256);
- free_irq(card->irq, card);
- kfree(card);
- return -ENODEV;
+ goto out_unregister_sound_dsp;
}
card->mixer_regs_ready = 1;
outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
#endif
/* edited by HMSEO for GT sound*/
}
-
+ rc = 0;
pci_set_drvdata(pci_dev, card);
/* Enable Address Engine Interrupts */
trident_enable_loop_interrupts(card);
-
- return 0;
+out: return rc;
+out_unregister_sound_dsp:
+ unregister_sound_dsp(card->dev_audio);
+out_free_irq:
+ free_irq(card->irq, card);
+out_proc_fs:
+#ifdef CONFIG_PROC_FS
+ if (res) {
+ remove_proc_entry("ALi5451", NULL);
+ res = NULL;
+ }
+#endif
+ kfree(card);
+ devs = NULL;
+out_release_region:
+ release_region(iobase, 256);
+ goto out;
}
static void __exit trident_remove(struct pci_dev *pci_dev)
module_init(init_vidc);
module_exit(cleanup_vidc);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("VIDC20 audio driver");
+MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
#define TC_DEBUG
+MODULE_LICENSE("GPL");
slot_info tc_bus[MAX_SLOT];
static int max_tcslot;
static tcinfo *info;
static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io_size)
{
struct uhci *uhci;
- int retval = -EBUSY;
+ int retval;
char buf[8], *bufp = buf;
int i, port;
struct usb_bus *bus;
struct proc_dir_entry *ent;
#endif
- if (!request_region(io_addr, io_size, "usb-uhci")) {
- err("couldn't allocate I/O range %x - %x", io_addr,
- io_addr + io_size - 1);
- goto err_request_region;
+ retval = -ENODEV;
+ if (pci_enable_device(dev) < 0) {
+ err("couldn't enable PCI device");
+ goto err_enable_device;
}
if (!dev->irq) {
err("found UHCI device with no IRQ assigned. check BIOS settings!");
- retval = -EINVAL;
goto err_invalid_irq;
}
if (!pci_dma_supported(dev, 0xFFFFFFFF)) {
err("PCI subsystem doesn't support 32 bit addressing?");
- retval = -ENODEV;
goto err_pci_dma_supported;
}
- if (pci_enable_device(dev) < 0) {
- err("couldn't enable PCI device");
- goto err_enable_device;
+ retval = -EBUSY;
+ if (!request_region(io_addr, io_size, "usb-uhci")) {
+ err("couldn't allocate I/O range %x - %x", io_addr,
+ io_addr + io_size - 1);
+ goto err_request_region;
}
pci_set_master(dev);
err_alloc_uhci:
err_pci_set_dma_mask:
+ release_region(io_addr, io_size);
-err_enable_device:
+err_request_region:
err_pci_dma_supported:
- release_region(io_addr, io_size);
err_invalid_irq:
-err_request_region:
+err_enable_device:
return retval;
}
return 0;
}
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");
MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
*
* Copyright (C) 1998-2000 Russell King
*
+ * MIPS and 50xx clock support
+ * Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*#define CFB16_IS_CFB15*/
-static char *CyberRegs;
-
#include "cyber2000fb.h"
struct cfb_info {
struct fb_info fb;
struct display_switch *dispsw;
struct pci_dev *dev;
+ unsigned char *region;
+ unsigned char *regs;
signed int currcon;
int func_use_count;
u_long ref_ps;
u_char mclk_div;
};
+static char default_font_storage[40];
+static char *default_font = "Acorn8x8";
+MODULE_PARM(default_font, "s");
+MODULE_PARM_DESC(default_font, "Default font name");
+
+/*
+ * Our access methods.
+ */
+#define cyber2000fb_writel(val,reg,cfb) writel(val, (cfb)->regs + (reg))
+#define cyber2000fb_writew(val,reg,cfb) writew(val, (cfb)->regs + (reg))
+#define cyber2000fb_writeb(val,reg,cfb) writeb(val, (cfb)->regs + (reg))
+
+#define cyber2000fb_readb(reg,cfb) readb((cfb)->regs + (reg))
+
+static inline void
+cyber2000_crtcw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_writew((reg & 255) | val << 8, 0x3d4, cfb);
+}
+
+static inline void
+cyber2000_grphw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_writew((reg & 255) | val << 8, 0x3ce, cfb);
+}
+
+static inline unsigned int
+cyber2000_grphr(unsigned int reg, struct cfb_info *cfb)
+{
+ cyber2000fb_writeb(reg, 0x3ce, cfb);
+ return cyber2000fb_readb(0x3cf, cfb);
+}
+
+static inline void
+cyber2000_attrw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_readb(0x3da, cfb);
+ cyber2000fb_writeb(reg, 0x3c0, cfb);
+ cyber2000fb_readb(0x3c1, cfb);
+ cyber2000fb_writeb(val, 0x3c0, cfb);
+}
+
+static inline void
+cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_writew((reg & 255) | val << 8, 0x3c4, cfb);
+}
+
/* -------------------- Hardware specific routines ------------------------- */
/*
* Hardware Cyber2000 Acceleration
*/
-static void cyber2000_accel_wait(void)
+static void cyber2000_accel_wait(struct cfb_info *cfb)
{
int count = 100000;
- while (cyber2000_inb(CO_REG_CONTROL) & 0x80) {
+ while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & 0x80) {
if (!count--) {
debug_printf("accel_wait timed out\n");
- cyber2000_outb(0, CO_REG_CONTROL);
+ cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
return;
}
udelay(1);
cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
+ struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct fb_var_screeninfo *var = &p->fb_info->var;
u_long src, dst;
u_int fh, fw;
src = sx + sy * var->xres_virtual;
dst = dx + dy * var->xres_virtual;
- cyber2000_accel_wait();
- cyber2000_outb(0x00, CO_REG_CONTROL);
- cyber2000_outb(0x03, CO_REG_FORE_MIX);
- cyber2000_outw(width, CO_REG_WIDTH);
+ cyber2000_accel_wait(cfb);
+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
+ cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
+ cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
if (var->bits_per_pixel != 24) {
- cyber2000_outl(dst, CO_REG_DEST_PTR);
- cyber2000_outl(src, CO_REG_SRC_PTR);
+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writel(src, CO_REG_SRC_PTR, cfb);
} else {
- cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
- cyber2000_outb(dst, CO_REG_X_PHASE);
- cyber2000_outl(src * 3, CO_REG_SRC_PTR);
+ cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
+ cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
}
- cyber2000_outw(height, CO_REG_HEIGHT);
- cyber2000_outw(cmd, CO_REG_CMD_L);
- cyber2000_outw(0x2800, CO_REG_CMD_H);
+ cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
+ cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
+ cyber2000fb_writew(0x2800, CO_REG_CMD_H, cfb);
}
static void
cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
+ struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct fb_var_screeninfo *var = &p->fb_info->var;
u_long dst;
u_int fw, fh;
width = width * fw - 1;
height = height * fh - 1;
- cyber2000_accel_wait();
- cyber2000_outb(0x00, CO_REG_CONTROL);
- cyber2000_outb(0x03, CO_REG_FORE_MIX);
- cyber2000_outw(width, CO_REG_WIDTH);
- cyber2000_outw(height, CO_REG_HEIGHT);
+ cyber2000_accel_wait(cfb);
+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
+ cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
+ cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
+ cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
switch (var->bits_per_pixel) {
case 15:
case 16:
bgx = ((u16 *)p->dispsw_data)[bgx];
case 8:
- cyber2000_outl(dst, CO_REG_DEST_PTR);
+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
break;
case 24:
- cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
- cyber2000_outb(dst, CO_REG_X_PHASE);
+ cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
bgx = ((u32 *)p->dispsw_data)[bgx];
break;
}
- cyber2000_outl(bgx, CO_REG_FOREGROUND);
- cyber2000_outw(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L);
- cyber2000_outw(0x0800, CO_REG_CMD_H);
+ cyber2000fb_writel(bgx, CO_REG_FOREGROUND, cfb);
+ cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
+ cyber2000fb_writew(0x0800, CO_REG_CMD_H, cfb);
}
static void
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
- cyber2000_accel_wait();
+ cyber2000_accel_wait(cfb);
cfb->dispsw->putc(conp, p, c, yy, xx);
}
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
- cyber2000_accel_wait();
+ cyber2000_accel_wait(cfb);
cfb->dispsw->putcs(conp, p, s, count, yy, xx);
}
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
- cyber2000_accel_wait();
+ cyber2000_accel_wait(cfb);
cfb->dispsw->revc(p, xx, yy);
}
switch (cfb->fb.var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
- cyber2000_outb(regno, 0x3c8);
- cyber2000_outb(red, 0x3c9);
- cyber2000_outb(green, 0x3c9);
- cyber2000_outb(blue, 0x3c9);
+ cyber2000fb_writeb(regno, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
break;
#endif
#ifndef CFB16_IS_CFB15
if (regno < 64) {
/* write green */
- cyber2000_outb(regno << 2, 0x3c8);
- cyber2000_outb(cfb->palette[regno >> 1].red, 0x3c9);
- cyber2000_outb(green, 0x3c9);
- cyber2000_outb(cfb->palette[regno >> 1].blue, 0x3c9);
+ cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
}
if (regno < 32) {
/* write red,blue */
- cyber2000_outb(regno << 3, 0x3c8);
- cyber2000_outb(red, 0x3c9);
- cyber2000_outb(cfb->palette[regno << 1].green, 0x3c9);
- cyber2000_outb(blue, 0x3c9);
+ cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
}
if (regno < 16)
case 15:
if (regno < 32) {
- cyber2000_outb(regno << 3, 0x3c8);
- cyber2000_outb(red, 0x3c9);
- cyber2000_outb(green, 0x3c9);
- cyber2000_outb(blue, 0x3c9);
+ cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
}
if (regno < 16)
((u16 *)cfb->fb.pseudo_palette)[regno] =
#ifdef FBCON_HAS_CFB24
case 24:
- cyber2000_outb(regno, 0x3c8);
- cyber2000_outb(red, 0x3c9);
- cyber2000_outb(green, 0x3c9);
- cyber2000_outb(blue, 0x3c9);
+ cyber2000fb_writeb(regno, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
if (regno < 16)
((u32 *)cfb->fb.pseudo_palette)[regno] =
* Blank palette
*/
for (i = 0; i < NR_PALETTE; i++) {
- cyber2000_outb(i, 0x3c8);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
+ cyber2000fb_writeb(i, 0x3c8, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
}
- cyber2000_outb(0xef, 0x3c2);
- cyber2000_crtcw(0x11, 0x0b);
- cyber2000_attrw(0x11, 0x00);
+ cyber2000fb_writeb(0xef, 0x3c2, cfb);
+ cyber2000_crtcw(0x11, 0x0b, cfb);
+ cyber2000_attrw(0x11, 0x00, cfb);
- cyber2000_seqw(0x00, 0x01);
- cyber2000_seqw(0x01, 0x01);
- cyber2000_seqw(0x02, 0x0f);
- cyber2000_seqw(0x03, 0x00);
- cyber2000_seqw(0x04, 0x0e);
- cyber2000_seqw(0x00, 0x03);
+ cyber2000_seqw(0x00, 0x01, cfb);
+ cyber2000_seqw(0x01, 0x01, cfb);
+ cyber2000_seqw(0x02, 0x0f, cfb);
+ cyber2000_seqw(0x03, 0x00, cfb);
+ cyber2000_seqw(0x04, 0x0e, cfb);
+ cyber2000_seqw(0x00, 0x03, cfb);
for (i = 0; i < sizeof(crtc_idx); i++)
- cyber2000_crtcw(crtc_idx[i], hw->crtc[i]);
+ cyber2000_crtcw(crtc_idx[i], hw->crtc[i], cfb);
for (i = 0x0a; i < 0x10; i++)
- cyber2000_crtcw(i, 0);
-
- cyber2000_grphw(0x11, hw->crtc_ofl);
- cyber2000_grphw(0x00, 0x00);
- cyber2000_grphw(0x01, 0x00);
- cyber2000_grphw(0x02, 0x00);
- cyber2000_grphw(0x03, 0x00);
- cyber2000_grphw(0x04, 0x00);
- cyber2000_grphw(0x05, 0x60);
- cyber2000_grphw(0x06, 0x05);
- cyber2000_grphw(0x07, 0x0f);
- cyber2000_grphw(0x08, 0xff);
+ cyber2000_crtcw(i, 0, cfb);
+
+ cyber2000_grphw(0x11, hw->crtc_ofl, cfb);
+ cyber2000_grphw(0x00, 0x00, cfb);
+ cyber2000_grphw(0x01, 0x00, cfb);
+ cyber2000_grphw(0x02, 0x00, cfb);
+ cyber2000_grphw(0x03, 0x00, cfb);
+ cyber2000_grphw(0x04, 0x00, cfb);
+ cyber2000_grphw(0x05, 0x60, cfb);
+ cyber2000_grphw(0x06, 0x05, cfb);
+ cyber2000_grphw(0x07, 0x0f, cfb);
+ cyber2000_grphw(0x08, 0xff, cfb);
/* Attribute controller registers */
for (i = 0; i < 16; i++)
- cyber2000_attrw(i, i);
+ cyber2000_attrw(i, i, cfb);
- cyber2000_attrw(0x10, 0x01);
- cyber2000_attrw(0x11, 0x00);
- cyber2000_attrw(0x12, 0x0f);
- cyber2000_attrw(0x13, 0x00);
- cyber2000_attrw(0x14, 0x00);
+ cyber2000_attrw(0x10, 0x01, cfb);
+ cyber2000_attrw(0x11, 0x00, cfb);
+ cyber2000_attrw(0x12, 0x0f, cfb);
+ cyber2000_attrw(0x13, 0x00, cfb);
+ cyber2000_attrw(0x14, 0x00, cfb);
/* woody: set the interlaced bit... */
/* FIXME: what about doublescan? */
- cyber2000_outb(0x11, 0x3ce);
- i = cyber2000_inb(0x3cf);
+ cyber2000fb_writeb(0x11, 0x3ce, cfb);
+ i = cyber2000fb_readb(0x3cf, cfb);
if (hw->vmode == FB_VMODE_INTERLACED)
i |= 0x20;
else
i &= ~0x20;
- cyber2000_outb(i, 0x3cf);
+ cyber2000fb_writeb(i, 0x3cf, cfb);
/* PLL registers */
- cyber2000_grphw(DCLK_MULT, hw->clock_mult);
- cyber2000_grphw(DCLK_DIV, hw->clock_div);
- cyber2000_grphw(MCLK_MULT, cfb->mclk_mult);
- cyber2000_grphw(MCLK_DIV, cfb->mclk_div);
- cyber2000_grphw(0x90, 0x01);
- cyber2000_grphw(0xb9, 0x80);
- cyber2000_grphw(0xb9, 0x00);
-
- cyber2000_outb(0x56, 0x3ce);
- i = cyber2000_inb(0x3cf);
- cyber2000_outb(i | 4, 0x3cf);
- cyber2000_outb(hw->palette_ctrl, 0x3c6);
- cyber2000_outb(i, 0x3cf);
-
- cyber2000_outb(0x20, 0x3c0);
- cyber2000_outb(0xff, 0x3c6);
-
- cyber2000_grphw(0x14, hw->fetch);
+ cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
+ cyber2000_grphw(DCLK_DIV, hw->clock_div, cfb);
+ cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
+ cyber2000_grphw(MCLK_DIV, cfb->mclk_div, cfb);
+ cyber2000_grphw(0x90, 0x01, cfb);
+ cyber2000_grphw(0xb9, 0x80, cfb);
+ cyber2000_grphw(0xb9, 0x00, cfb);
+
+ cyber2000fb_writeb(0x56, 0x3ce, cfb);
+ i = cyber2000fb_readb(0x3cf, cfb);
+ cyber2000fb_writeb(i | 4, 0x3cf, cfb);
+ cyber2000fb_writeb(hw->palette_ctrl, 0x3c6, cfb);
+ cyber2000fb_writeb(i, 0x3cf, cfb);
+
+ cyber2000fb_writeb(0x20, 0x3c0, cfb);
+ cyber2000fb_writeb(0xff, 0x3c6, cfb);
+
+ cyber2000_grphw(0x14, hw->fetch, cfb);
cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
- ((hw->pitch >> 4) & 0x30));
- cyber2000_grphw(0x77, hw->visualid);
+ ((hw->pitch >> 4) & 0x30), cfb);
+ cyber2000_grphw(0x77, hw->visualid, cfb);
/* make sure we stay in linear mode */
- cyber2000_grphw(0x33, 0x0d);
+ cyber2000_grphw(0x33, 0x0d, cfb);
/*
* Set up accelerator registers
*/
- cyber2000_outw(hw->width, CO_REG_SRC_WIDTH);
- cyber2000_outw(hw->width, CO_REG_DEST_WIDTH);
- cyber2000_outb(hw->pixformat, CO_REG_PIX_FORMAT);
+ cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
+ cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
+ cyber2000fb_writeb(hw->pixformat, CO_REG_PIX_FORMAT, cfb);
}
static inline int
if (base >= 1 << 20)
return -EINVAL;
- cyber2000_grphw(0x10, base >> 16 | 0x10);
- cyber2000_crtcw(0x0c, base >> 8);
- cyber2000_crtcw(0x0d, base);
+ cyber2000_grphw(0x10, base >> 16 | 0x10, cfb);
+ cyber2000_crtcw(0x0c, base >> 8, cfb);
+ cyber2000_crtcw(0x0d, base, cfb);
return 0;
}
const u_long ref_ps = cfb->ref_ps;
u_int div2, t_div1, best_div1, best_mult;
int best_diff;
+ int vco;
/*
* Step 1:
hw->clock_mult = best_mult - 1;
hw->clock_div = div2 << 6 | (best_div1 - 1);
+ vco = ref_ps * best_div1 / best_mult;
+ if ((ref_ps == 40690) && (vco < 5556))
+ /* Set VFSEL when VCO > 180MHz (5.556 ps). */
+ hw->clock_div |= DCLK_DIV_VFSEL;
+
return 0;
}
switch (blank) {
case 4: /* powerdown - both sync lines down */
- cyber2000_grphw(0x16, 0x05);
+ cyber2000_grphw(0x16, 0x05, cfb);
break;
case 3: /* hsync off */
- cyber2000_grphw(0x16, 0x01);
+ cyber2000_grphw(0x16, 0x01, cfb);
break;
case 2: /* vsync off */
- cyber2000_grphw(0x16, 0x04);
+ cyber2000_grphw(0x16, 0x04, cfb);
break;
case 1: /* soft blank */
- cyber2000_grphw(0x16, 0x00);
+ cyber2000_grphw(0x16, 0x00, cfb);
for (i = 0; i < NR_PALETTE; i++) {
- cyber2000_outb(i, 0x3c8);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
+ cyber2000fb_writeb(i, 0x3c8, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
}
break;
default: /* unblank */
- cyber2000_grphw(0x16, 0x00);
+ cyber2000_grphw(0x16, 0x00, cfb);
for (i = 0; i < NR_PALETTE; i++) {
- cyber2000_outb(i, 0x3c8);
- cyber2000_outb(cfb->palette[i].red, 0x3c9);
- cyber2000_outb(cfb->palette[i].green, 0x3c9);
- cyber2000_outb(cfb->palette[i].blue, 0x3c9);
+ cyber2000fb_writeb(i, 0x3c8, cfb);
+ cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
}
break;
}
if (cfb->func_use_count == 1) {
int old;
- old = cyber2000_grphr(FUNC_CTL);
- cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL);
+ old = cyber2000_grphr(FUNC_CTL, cfb);
+ cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
}
}
if (cfb->func_use_count == 1) {
int old;
- old = cyber2000_grphr(FUNC_CTL);
- cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL);
+ old = cyber2000_grphr(FUNC_CTL, cfb);
+ cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
}
cfb->func_use_count -= 1;
{
if (int_cfb_info != NULL) {
info->dev = int_cfb_info->dev;
- info->regs = CyberRegs;
+ info->regs = int_cfb_info->regs;
info->fb = int_cfb_info->fb.screen_base;
info->fb_size = int_cfb_info->fb.fix.smem_len;
info->enable_extregs = cyber2000fb_enable_extregs;
* initialising this card for the first time.
* FIXME: what about hotplug?
*/
- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT);
- cfb->mclk_div = cyber2000_grphr(MCLK_DIV);
+ cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
+ cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
}
#endif
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
/*
- * x86 is simple, we just do regular outb's instead of
- * cyber2000_outb.
+ * x86 and MIPS are simple, we just do regular
+ * outb's instead of cyber2000fb_writeb.
*/
outb(0x18, 0x46e8);
outb(0x01, 0x102);
* initialising this card for the first time.
* FIXME: what about hotplug?
*/
- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT);
- cfb->mclk_div = cyber2000_grphr(MCLK_DIV);
+ cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
+ cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
}
#endif
#ifdef __arm__
- cyber2000_outb(0x18, 0x46e8);
- cyber2000_outb(0x01, 0x102);
- cyber2000_outb(0x08, 0x46e8);
- cyber2000_outb(0x33, 0x3ce);
- cyber2000_outb(0x01, 0x3cf);
+ cyber2000fb_writeb(0x18, 0x46e8, cfb);
+ cyber2000fb_writeb(0x01, 0x102, cfb);
+ cyber2000fb_writeb(0x08, 0x46e8, cfb);
+ cyber2000fb_writeb(0x33, 0x3ce, cfb);
+ cyber2000fb_writeb(0x01, 0x3cf, cfb);
/*
* MCLK on the NetWinder and the Shark is fixed at 75MHz
* Initialise the CyberPro
*/
for (i = 0; i < sizeof(igs_regs); i += 2)
- cyber2000_grphw(igs_regs[i], igs_regs[i+1]);
+ cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
if (at_boot) {
/*
* This should have been already initialised by the BIOS,
* but if it's garbage, claim default 1MB VRAM (woody)
*/
- cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1);
- cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2);
+ cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
+ cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
} else {
/*
* Reprogram the MEM_CTL1 and MEM_CTL2 registers
*/
- cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1);
- cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2);
+ cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
+ cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
}
/*
* (CyberPro 5000's may be programmed to use
* an additional set of PLLs.
*/
- cyber2000_outb(0xba, 0x3ce);
- cyber2000_outb(cyber2000_inb(0x3cf) & 0x80, 0x3cf);
+ cyber2000fb_writeb(0xba, 0x3ce, cfb);
+ cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
}
static struct cfb_info * __devinit
cfb->currcon = -1;
cfb->dev = dev;
- cfb->ref_ps = 69842;
+
+ if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
+ cfb->ref_ps = 40690; // 24.576 MHz
+ else
+ cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
+
cfb->divisors[0] = 1;
cfb->divisors[1] = 2;
cfb->divisors[2] = 4;
- if (id->driver_data == FB_ACCEL_IGS_CYBER2010)
- cfb->divisors[3] = 6;
- else
+ if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
cfb->divisors[3] = 8;
+ else
+ cfb->divisors[3] = 6;
strcpy(cfb->fb.fix.id, name);
cfb->fb.var.accel_flags = FB_ACCELF_TEXT;
strcpy(cfb->fb.modename, cfb->fb.fix.id);
- strcpy(cfb->fb.fontname, "Acorn8x8");
+ strcpy(cfb->fb.fontname, default_font);
cfb->fb.fbops = &cyber2000fb_ops;
cfb->fb.changevar = NULL;
}
/*
- * Map in the registers
- */
-static int __devinit
-cyberpro_map_mmio(struct cfb_info *cfb, struct pci_dev *dev)
-{
- u_long mmio_base;
-
- mmio_base = pci_resource_start(dev, 0) + MMIO_OFFSET;
-
- cfb->fb.fix.mmio_start = mmio_base;
- cfb->fb.fix.mmio_len = MMIO_SIZE;
-
- CyberRegs = ioremap(mmio_base, MMIO_SIZE);
- if (!CyberRegs) {
- printk("%s: unable to map memory mapped IO\n",
- cfb->fb.fix.id);
- return -ENOMEM;
- }
- return 0;
-}
-
-/*
- * Unmap registers
+ * Parse Cyber2000fb options. Usage:
+ * video=cyber2000:font:fontname
*/
-static void __devinit cyberpro_unmap_mmio(struct cfb_info *cfb)
+int
+cyber2000fb_setup(char *options)
{
- if (cfb && CyberRegs) {
- iounmap(CyberRegs);
- CyberRegs = NULL;
- }
-}
+ char *opt;
-/*
- * Map in screen memory
- */
-static int __devinit
-cyberpro_map_smem(struct cfb_info *cfb, struct pci_dev *dev, u_long smem_len)
-{
- u_long smem_base;
+ if (!options || !*options)
+ return 0;
- smem_base = pci_resource_start(dev, 0);
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
- cfb->fb.fix.smem_start = smem_base;
- cfb->fb.fix.smem_len = smem_len;
+ if (strncmp(opt, "font:", 5) == 0) {
+ strncpy(default_font_storage, opt + 5, sizeof(default_font_storage));
+ default_font = default_font_storage;
+ continue;
+ }
- cfb->fb.screen_base = ioremap(smem_base, smem_len);
- if (!cfb->fb.screen_base) {
- printk("%s: unable to map screen memory\n",
- cfb->fb.fix.id);
- return -ENOMEM;
+ printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", opt);
}
-
return 0;
}
-static void __devinit cyberpro_unmap_smem(struct cfb_info *cfb)
-{
- if (cfb && cfb->fb.screen_base) {
- iounmap(cfb->fb.screen_base);
- cfb->fb.screen_base = NULL;
- }
-}
-
static int __devinit
cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
err = -ENOMEM;
cfb = cyberpro_alloc_fb_info(dev, id, name);
if (!cfb)
- goto failed;
+ goto failed_release;
- err = cyberpro_map_mmio(cfb, dev);
- if (err)
- goto failed;
+ cfb->region = ioremap(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0));
+ if (!cfb->region)
+ goto failed_ioremap;
+
+ cfb->regs = cfb->region + MMIO_OFFSET;
cyberpro_init_hw(cfb, 1);
default: smem_size = 0x00100000; break;
}
- err = cyberpro_map_smem(cfb, dev, smem_size);
- if (err)
- goto failed;
+ /*
+ * Hmm, we _need_ a portable way of finding the address for
+ * the remap stuff, both for mmio and for smem.
+ */
+ cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
+ cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+ cfb->fb.fix.mmio_len = MMIO_SIZE;
+ cfb->fb.fix.smem_len = smem_size;
+ cfb->fb.screen_base = cfb->region;
if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
&cyber2000fb_default_mode, 8)) {
return 0;
failed:
- cyberpro_unmap_smem(cfb);
- cyberpro_unmap_mmio(cfb);
+ iounmap(cfb->region);
+failed_ioremap:
cyberpro_free_fb_info(cfb);
-
-release:
+failed_release:
pci_release_regions(dev);
return err;
printk(KERN_WARNING "%s: danger Will Robinson, "
"danger danger! Oopsen imminent!\n",
cfb->fb.fix.id);
- cyberpro_unmap_smem(cfb);
- cyberpro_unmap_mmio(cfb);
+ iounmap(cfb->region);
cyberpro_free_fb_info(cfb);
/*
}
#ifdef MODULE
-MODULE_LICENSE("GPL");
module_init(cyber2000fb_init);
#endif
module_exit(cyberpro_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
+MODULE_LICENSE("GPL");
*/
#include <linux/config.h>
-#define cyber2000_outb(dat,reg) writeb(dat, CyberRegs + reg)
-#define cyber2000_outw(dat,reg) writew(dat, CyberRegs + reg)
-#define cyber2000_outl(dat,reg) writel(dat, CyberRegs + reg)
-
-#define cyber2000_inb(reg) readb(CyberRegs + reg)
-#define cyber2000_inw(reg) readw(CyberRegs + reg)
-#define cyber2000_inl(reg) readl(CyberRegs + reg)
-
/*
* Internal CyberPro sizes and offsets.
*/
#if defined(DEBUG) && defined(CONFIG_DEBUG_LL)
static void debug_printf(char *fmt, ...)
{
+ extern void printascii(const char *);
char buffer[128];
va_list ap;
#define debug_printf(x...) do { } while (0)
#endif
-static inline void cyber2000_crtcw(int reg, int val)
-{
- cyber2000_outb(reg, 0x3d4);
- cyber2000_outb(val, 0x3d5);
-}
-
-static inline void cyber2000_grphw(int reg, int val)
-{
- cyber2000_outb(reg, 0x3ce);
- cyber2000_outb(val, 0x3cf);
-}
-
-static inline unsigned int cyber2000_grphr(int reg)
-{
- cyber2000_outb(reg, 0x3ce);
- return cyber2000_inb(0x3cf);
-}
-
-static inline void cyber2000_attrw(int reg, int val)
-{
- cyber2000_inb(0x3da);
- cyber2000_outb(reg, 0x3c0);
- cyber2000_inb(0x3c1);
- cyber2000_outb(val, 0x3c0);
-}
-
-static inline void cyber2000_seqw(int reg, int val)
-{
- cyber2000_outb(reg, 0x3c4);
- cyber2000_outb(val, 0x3c5);
-}
-
#define PIXFORMAT_8BPP 0
#define PIXFORMAT_16BPP 1
#define PIXFORMAT_24BPP 2
#define DCLK_MULT 0xb0
#define DCLK_DIV 0xb1
+#define DCLK_DIV_VFSEL 0x20
#define MCLK_MULT 0xb2
#define MCLK_DIV 0xb3
(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
if (!error)
- inode_setattr(inode, attr);
+ error = inode_setattr(inode, attr);
}
}
unlock_kernel();
#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512)
-static inline unsigned int blksize_bits(unsigned int size)
-{
- unsigned int bits = 8;
- do {
- bits++;
- size >>= 1;
- } while (size > 256);
- return bits;
-}
-
-static inline unsigned int block_size(kdev_t dev)
-{
- int retval = BLOCK_SIZE;
- int major = MAJOR(dev);
-
- if (blksize_size[major]) {
- int minor = MINOR(dev);
- if (blksize_size[major][minor])
- retval = blksize_size[major][minor];
- }
- return retval;
-}
-
static unsigned long max_block(kdev_t dev)
{
unsigned int retval = ~0U;
#include <linux/module.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/bitops.h>
O_TARGET := ext2.o
-obj-y := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o
obj-m := $(O_TARGET)
+++ /dev/null
-/*
- * linux/fs/ext2/acl.c
- *
- * Copyright (C) 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- */
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-
-
-/*
- * This file will contain the Access Control Lists management for the
- * second extended file system.
- */
#include <linux/ext2_fs.h>
#include <linux/sched.h>
-static loff_t ext2_file_lseek(struct file *, loff_t, int);
-static int ext2_open_file (struct inode *, struct file *);
-
-#define EXT2_MAX_SIZE(bits) \
- (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \
- (1LL << (bits - 2)) * (1LL << (bits - 2)) + \
- (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) * \
- (1LL << bits)) - 1)
-
-static long long ext2_max_sizes[] = {
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13)
-};
-
-/*
- * Make sure the offset never goes beyond the 32-bit mark..
- */
-static loff_t ext2_file_lseek(
- struct file *file,
- loff_t offset,
- int origin)
-{
- struct inode *inode = file->f_dentry->d_inode;
-
- switch (origin) {
- case 2:
- offset += inode->i_size;
- break;
- case 1:
- offset += file->f_pos;
- }
- if (offset<0)
- return -EINVAL;
- if (((unsigned long long) offset >> 32) != 0) {
- if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
- return -EINVAL;
- }
- if (offset != file->f_pos) {
- file->f_pos = offset;
- file->f_reada = 0;
- file->f_version = ++event;
- }
- return offset;
-}
-
/*
* Called when an inode is released. Note that this is different
* from ext2_open_file: open gets called at every open, but release
return 0;
}
-/*
- * Called when an inode is about to be open.
- * We use this to disallow opening RW large files on 32bit systems if
- * the caller didn't specify O_LARGEFILE. On 64bit systems we force
- * on this flag in sys_open.
- */
-static int ext2_open_file (struct inode * inode, struct file * filp)
-{
- if (!(filp->f_flags & O_LARGEFILE) &&
- inode->i_size > 0x7FFFFFFFLL)
- return -EFBIG;
- return 0;
-}
-
/*
* We have mostly NULL's here: the current defaults are ok for
* the ext2 filesystem.
*/
struct file_operations ext2_file_operations = {
- llseek: ext2_file_lseek,
+ llseek: generic_file_llseek,
read: generic_file_read,
write: generic_file_write,
ioctl: ext2_ioctl,
mmap: generic_file_mmap,
- open: ext2_open_file,
+ open: generic_file_open,
release: ext2_release_file,
fsync: ext2_sync_file,
};
#include <linux/sched.h>
#include <linux/highuid.h>
#include <linux/quotaops.h>
+#include <linux/module.h>
+
+MODULE_AUTHOR("Remy Card and others");
+MODULE_DESCRIPTION("Second Extended Filesystem");
+MODULE_LICENSE("GPL");
+
static int ext2_update_inode(struct inode * inode, int do_sync);
sync_page: block_sync_page,
prepare_write: ext2_prepare_write,
commit_write: generic_commit_write,
- bmap: ext2_bmap,
+ bmap: ext2_bmap
};
/*
MODULE_AUTHOR("Christoph Hellwig");
MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
+MODULE_LICENSE("Dual BSD/GPL");
static void vxfs_put_super(struct super_block *);
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fs.h>
case NLM_LCK_BLOCKED:
printk(KERN_NOTICE "lockd: unexpected status NLM_BLOCKED\n");
return -ENOLCK;
+#ifdef CONFIG_LOCKD_V4
+ case NLM_DEADLCK:
+ return -EDEADLK;
+ case NLM_ROFS:
+ return -EROFS;
+ case NLM_STALE_FH:
+ return -ESTALE;
+ case NLM_FBIG:
+ return -EOVERFLOW;
+ case NLM_FAILED:
+ return -ENOLCK;
+#endif
}
printk(KERN_NOTICE "lockd: unexpected server status %d\n", status);
return -ENOLCK;
#include <linux/lockd/nlm.h>
#include <linux/lockd/lockd.h>
-
#define NLMDBG_FACILITY NLMDBG_SVCLOCK
+#ifdef CONFIG_LOCKD_V4
+#define nlm_deadlock nlm4_deadlock
+#else
+#define nlm_deadlock nlm_lck_denied
+#endif
+
static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
static int nlmsvc_remove_block(struct nlm_block *block);
static void nlmsvc_grant_callback(struct rpc_task *task);
case 0:
return nlm_granted;
case EDEADLK:
-#ifdef CONFIG_LOCKD_V4
- return nlm4_deadlock; /* will be downgraded to lck_deined if this
- * is a NLMv1,3 request */
-#else
- /* no applicable NLM status */
-#endif
+ return nlm_deadlock;
case EAGAIN:
return nlm_lck_denied;
default: /* includes ENOLCK */
return nlm_lck_denied;
}
+ if (posix_locks_deadlock(&lock->fl, conflock)) {
+ up(&file->f_sema);
+ return nlm_deadlock;
+ }
+
/* If we don't have a block, create and initialize it. Then
* retry because we may have slept in kmalloc. */
if (block == NULL) {
static u32
cast_to_nlm(u32 status, u32 vers)
{
-
+ /* Note: status is assumed to be in network byte order !!! */
if (vers != 4){
- switch(ntohl(status)){
- case NLM_LCK_GRANTED:
- case NLM_LCK_DENIED:
- case NLM_LCK_DENIED_NOLOCKS:
- case NLM_LCK_BLOCKED:
- case NLM_LCK_DENIED_GRACE_PERIOD:
+ switch (status) {
+ case nlm_granted:
+ case nlm_lck_denied:
+ case nlm_lck_denied_nolocks:
+ case nlm_lck_blocked:
+ case nlm_lck_denied_grace_period:
+ break;
+ case nlm4_deadlock:
+ status = nlm_lck_denied;
break;
default:
- status = NLM_LCK_DENIED_NOLOCKS;
+ status = nlm_lck_denied_nolocks;
}
}
return (1);
default:
- printk("locks_conflict(): impossible lock type - %d\n",
+ printk(KERN_ERR "locks_conflict(): impossible lock type - %d\n",
caller_fl->fl_type);
break;
}
* from a broken NFS client. But broken NFS clients have a lot more to
* worry about than proper deadlock detection anyway... --okir
*/
-static int posix_locks_deadlock(struct file_lock *caller_fl,
+int posix_locks_deadlock(struct file_lock *caller_fl,
struct file_lock *block_fl)
{
struct list_head *tmp;
struct file_lock *new_fl = locks_alloc_lock(0);
int error;
+ if (new_fl == NULL)
+ return -ENOMEM;
+
new_fl->fl_owner = current->files;
new_fl->fl_pid = current->pid;
new_fl->fl_file = filp;
struct inode *inode;
int error;
+ if (file_lock == NULL)
+ return -ENOLCK;
+
/*
* This might block, so we do it before checking the inode.
*/
struct inode *inode;
int error;
+ if (file_lock == NULL)
+ return -ENOLCK;
+
/*
* This might block, so we do it before checking the inode.
*/
static __inline__ struct nfs_read_data *nfs_readdata_alloc(void)
{
struct nfs_read_data *p;
- p = kmem_cache_alloc(nfs_rdata_cachep, SLAB_NFS);
+ p = kmem_cache_alloc(nfs_rdata_cachep, SLAB_NOFS);
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
static __inline__ struct nfs_page *nfs_page_alloc(void)
{
struct nfs_page *p;
- p = kmem_cache_alloc(nfs_page_cachep, SLAB_KERNEL);
+ p = kmem_cache_alloc(nfs_page_cachep, SLAB_NOFS);
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->wb_hash);
static __inline__ struct nfs_write_data *nfs_writedata_alloc(void)
{
struct nfs_write_data *p;
- p = kmem_cache_alloc(nfs_wdata_cachep, SLAB_NFS);
+ p = kmem_cache_alloc(nfs_wdata_cachep, SLAB_NOFS);
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
if (*name == '\0' || *name == '/')
return NULL;
}
- *name = '\0';
}
return p;
printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
bdev = bdget(kdev_t_to_nr(dev));
bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
+ bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
for (i = 0; check_part[i]; i++) {
int res;
res = check_part[i](hd, bdev, first_sector, first_part_minor);
*/
static void extended_partition(struct gendisk *hd, struct block_device *bdev,
- int minor, int *current_minor)
+ int minor, unsigned long first_size, int *current_minor)
{
struct partition *p;
Sector sect;
unsigned char *data;
- unsigned long first_sector, first_size, this_sector, this_size;
+ unsigned long first_sector, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
int loopct = 0; /* number of links followed
without finding a data partition */
int i;
- first_sector = hd->part[minor].start_sect;
- first_size = hd->part[minor].nr_sects;
- this_sector = first_sector;
+ this_sector = first_sector = hd->part[minor].start_sect;
+ this_size = first_size;
while (1) {
if (++loopct > 100)
p = (struct partition *) (data + 0x1be);
- this_size = hd->part[minor].nr_sects;
-
/*
* Usually, the first entry is the real data partition,
* the 2nd entry is the next extended partition, or empty,
goto done; /* nothing left to do */
this_sector = first_sector + START_SECT(p) * sector_size;
+ this_size = NR_SECTS(p) * sector_size;
minor = *current_minor;
put_dev_sector(sect);
}
}
#endif
if (is_extended_partition(p)) {
+ unsigned long size = hd->part[minor].nr_sects;
printk(" <");
/* prevent someone doing mkfs or mkswap on an
extended partition, but leave room for LILO */
- if (hd->part[minor].nr_sects > 2)
+ if (size > 2)
hd->part[minor].nr_sects = 2;
- extended_partition(hd, bdev, minor, ¤t_minor);
+ extended_partition(hd, bdev, minor, size, ¤t_minor);
printk(" >");
}
}
read_lock(&tasklist_lock);
buffer += sprintf(buffer,
"State:\t%s\n"
+ "Tgid:\t%d\n"
"Pid:\t%d\n"
"PPid:\t%d\n"
"TracerPid:\t%d\n"
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
- get_task_state(p),
+ get_task_state(p), p->tgid,
p->pid, p->pid ? p->p_opptr->pid : 0, 0,
p->uid, p->euid, p->suid, p->fsuid,
p->gid, p->egid, p->sgid, p->fsgid);
{
struct sysinfo i;
int len;
+ int pg_size ;
/*
* display in kilobytes.
#define B(x) ((unsigned long long)(x) << PAGE_SHIFT)
si_meminfo(&i);
si_swapinfo(&i);
+ pg_size = atomic_read(&page_cache_size) - i.bufferram ;
+
len = sprintf(page, " total: used: free: shared: buffers: cached:\n"
"Mem: %8Lu %8Lu %8Lu %8Lu %8Lu %8Lu\n"
"Swap: %8Lu %8Lu %8Lu\n",
B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
B(i.sharedram), B(i.bufferram),
- B(atomic_read(&page_cache_size)), B(i.totalswap),
+ B(pg_size), B(i.totalswap),
B(i.totalswap-i.freeswap), B(i.freeswap));
/*
* Tagged format, for easy grepping and expansion.
K(i.freeram),
K(i.sharedram),
K(i.bufferram),
- K(atomic_read(&page_cache_size) - swapper_space.nrpages),
+ K(pg_size - swapper_space.nrpages),
K(swapper_space.nrpages),
K(nr_active_pages),
K(nr_inactive_pages),
#define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x)
#define leNUM_to_cpup(x,y) xleNUM_to_cpup(x,y)
#define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
+#define UintBPL Uint(BITS_PER_LONG)
+#define Uint(x) xUint(x)
+#define xUint(x) Uint ## x
extern inline int find_next_one_bit (void * addr, int size, int offset)
{
- unsigned long * p = ((unsigned long *) addr) + (offset / BITS_PER_LONG);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
+ UintBPL * p = ((UintBPL *) addr) + (offset / BITS_PER_LONG);
+ UintBPL result = offset & ~(BITS_PER_LONG-1);
+ UintBPL tmp;
if (offset >= size)
return size;
}
}
-static inline int load_block_bitmap(struct super_block *sb,
+static inline int load_block_bitmap(struct super_block * sb,
struct udf_bitmap *bitmap, unsigned int block_group)
{
int slot;
return slot;
}
-static void udf_bitmap_free_blocks(struct inode * inode,
+static void udf_bitmap_free_blocks(struct super_block * sb,
+ struct inode * inode,
struct udf_bitmap *bitmap, lb_addr bloc, Uint32 offset, Uint32 count)
{
struct buffer_head * bh = NULL;
unsigned long i;
int bitmap_nr;
unsigned long overflow;
- struct super_block * sb;
-
- sb = inode->i_sb;
- if (!sb)
- {
- udf_debug("nonexistent device");
- return;
- }
lock_super(sb);
if (bloc.logicalBlockNum < 0 ||
}
else
{
- DQUOT_FREE_BLOCK(inode, 1);
+ if (inode)
+ DQUOT_FREE_BLOCK(inode, 1);
if (UDF_SB_LVIDBH(sb))
{
UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
return;
}
-static int udf_bitmap_prealloc_blocks(struct inode * inode,
+static int udf_bitmap_prealloc_blocks(struct super_block * sb,
+ struct inode * inode,
struct udf_bitmap *bitmap, Uint16 partition, Uint32 first_block,
Uint32 block_count)
{
int bit, block, block_group, group_start;
int nr_groups, bitmap_nr;
struct buffer_head *bh;
- struct super_block *sb;
- sb = inode->i_sb;
- if (!sb)
- {
- udf_debug("nonexistent device\n");
- return 0;
- }
lock_super(sb);
if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
return alloc_count;
}
-static int udf_bitmap_new_block(struct inode * inode,
+static int udf_bitmap_new_block(struct super_block * sb,
+ struct inode * inode,
struct udf_bitmap *bitmap, Uint16 partition, Uint32 goal, int *err)
{
int newbit, bit=0, block, block_group, group_start;
int end_goal, nr_groups, bitmap_nr, i;
struct buffer_head *bh = NULL;
- struct super_block *sb;
char *ptr;
int newblock = 0;
*err = -ENOSPC;
- sb = inode->i_sb;
- if (!sb)
- {
- udf_debug("nonexistent device\n");
- return newblock;
- }
lock_super(sb);
repeat:
/*
* Check quota for allocation of this block.
*/
- if (DQUOT_ALLOC_BLOCK(inode, 1))
+ if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
{
unlock_super(sb);
*err = -EDQUOT;
return 0;
}
-static void udf_table_free_blocks(struct inode * inode,
+static void udf_table_free_blocks(struct super_block * sb,
+ struct inode * inode,
struct inode * table, lb_addr bloc, Uint32 offset, Uint32 count)
{
- struct super_block * sb;
Uint32 start, end;
Uint32 nextoffset, oextoffset, elen;
lb_addr nbloc, obloc, eloc;
struct buffer_head *obh, *nbh;
- char etype;
+ Sint8 etype;
int i;
- udf_debug("ino=%ld, bloc=%d, offset=%d, count=%d\n",
- inode->i_ino, bloc.logicalBlockNum, offset, count);
-
- sb = inode->i_sb;
- if (!sb)
- {
- udf_debug("nonexistent device");
- return;
- }
-
- if (table == NULL)
- return;
-
lock_super(sb);
if (bloc.logicalBlockNum < 0 ||
(bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum))
/* We do this up front - There are some error conditions that could occure,
but.. oh well */
- DQUOT_FREE_BLOCK(inode, count);
+ if (inode)
+ DQUOT_FREE_BLOCK(inode, count);
if (UDF_SB_LVIDBH(sb))
{
UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
return;
}
-static int udf_table_prealloc_blocks(struct inode * inode,
+static int udf_table_prealloc_blocks(struct super_block * sb,
+ struct inode * inode,
struct inode *table, Uint16 partition, Uint32 first_block,
Uint32 block_count)
{
- struct super_block *sb;
int alloc_count = 0;
Uint32 extoffset, elen, adsize;
lb_addr bloc, eloc;
struct buffer_head *bh;
- char etype = -1;
-
- udf_debug("ino=%ld, partition=%d, first_block=%d, block_count=%d\n",
- inode->i_ino, partition, first_block, block_count);
-
- sb = inode->i_sb;
- if (!sb)
- {
- udf_debug("nonexistent device\n");
- return 0;
- }
+ Sint8 etype = -1;
if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
return 0;
- if (table == NULL)
- return 0;
-
if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG)
extoffset -= adsize;
alloc_count = (elen >> sb->s_blocksize_bits);
- if (alloc_count > block_count)
+ if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count))
+ alloc_count = 0;
+ else if (alloc_count > block_count)
{
alloc_count = block_count;
eloc.logicalBlockNum += alloc_count;
UDF_SB_LVID(sb)->freeSpaceTable[partition] =
cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-alloc_count);
mark_buffer_dirty(UDF_SB_LVIDBH(sb));
+ sb->s_dirt = 1;
}
- sb->s_dirt = 1;
unlock_super(sb);
- udf_debug("alloc_count=%d\n", alloc_count);
return alloc_count;
}
-static int udf_table_new_block(const struct inode * inode,
+static int udf_table_new_block(struct super_block * sb,
+ struct inode * inode,
struct inode *table, Uint16 partition, Uint32 goal, int *err)
{
- struct super_block *sb;
Uint32 spread = 0xFFFFFFFF, nspread;
Uint32 newblock = 0, adsize;
Uint32 extoffset, goal_extoffset, elen, goal_elen = 0;
lb_addr bloc, goal_bloc, eloc, goal_eloc;
struct buffer_head *bh, *goal_bh;
- char etype;
-
- udf_debug("ino=%ld, partition=%d, goal=%d\n",
- inode->i_ino, partition, goal);
+ Sint8 etype;
*err = -ENOSPC;
- sb = inode->i_sb;
- if (!sb)
- {
- udf_debug("nonexistent device\n");
- return newblock;
- }
-
- if (table == NULL)
- return newblock;
if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
goal_eloc.logicalBlockNum ++;
goal_elen -= sb->s_blocksize;
+ if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
+ {
+ udf_release_data(goal_bh);
+ unlock_super(sb);
+ *err = -EDQUOT;
+ return 0;
+ }
+
if (goal_elen)
udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1);
else
return newblock;
}
-inline void udf_free_blocks(struct inode * inode, lb_addr bloc,
- Uint32 offset, Uint32 count)
+inline void udf_free_blocks(struct super_block * sb,
+ struct inode * inode,
+ lb_addr bloc, Uint32 offset, Uint32 count)
{
- if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_BITMAP)
+ Uint16 partition = bloc.partitionReferenceNum;
+
+ if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
{
- return udf_bitmap_free_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_bitmap,
+ return udf_bitmap_free_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,
bloc, offset, count);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_TABLE)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
{
- return udf_table_free_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_table,
+ return udf_table_free_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_table,
bloc, offset, count);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_BITMAP)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
{
- return udf_bitmap_free_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_bitmap,
+ return udf_bitmap_free_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_bitmap,
bloc, offset, count);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_TABLE)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_TABLE)
{
- return udf_table_free_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_table,
+ return udf_table_free_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_table,
bloc, offset, count);
}
else
return;
}
-inline int udf_prealloc_blocks(struct inode * inode, Uint16 partition,
- Uint32 first_block, Uint32 block_count)
+inline int udf_prealloc_blocks(struct super_block * sb,
+ struct inode * inode,
+ Uint16 partition, Uint32 first_block, Uint32 block_count)
{
- if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
+ if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
{
- return udf_bitmap_prealloc_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap,
+ return udf_bitmap_prealloc_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,
partition, first_block, block_count);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
{
- return udf_table_prealloc_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table,
+ return udf_table_prealloc_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_table,
partition, first_block, block_count);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
{
- return udf_bitmap_prealloc_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap,
+ return udf_bitmap_prealloc_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_bitmap,
partition, first_block, block_count);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_TABLE)
{
- return udf_table_prealloc_blocks(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table,
+ return udf_table_prealloc_blocks(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_table,
partition, first_block, block_count);
}
else
return 0;
}
-inline int udf_new_block(struct inode * inode, Uint16 partition,
- Uint32 goal, int *err)
+inline int udf_new_block(struct super_block * sb,
+ struct inode * inode,
+ Uint16 partition, Uint32 goal, int *err)
{
- if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
+ if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
{
- return udf_bitmap_new_block(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap,
+ return udf_bitmap_new_block(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,
partition, goal, err);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE)
{
- return udf_table_new_block(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table,
+ return udf_table_new_block(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_table,
partition, goal, err);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_BITMAP)
{
- return udf_bitmap_new_block(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap,
+ return udf_bitmap_new_block(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_bitmap,
partition, goal, err);
}
- else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE)
+ else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_TABLE)
{
- return udf_table_new_block(inode,
- UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table,
+ return udf_table_new_block(sb, inode,
+ UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_table,
partition, goal, err);
}
else
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
- return -ENOENT;
+ return 0;
}
liu = le16_to_cpu(cfi.lengthOfImpUse);
int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
- int result = -1;
+ int result = -EINVAL;
struct buffer_head *bh = NULL;
long_ad eaicb;
Uint8 *ea = NULL;
switch (cmd)
{
case UDF_GETVOLIDENT:
- if ( (result == verify_area(VERIFY_WRITE, (char *)arg, 32)) == 0)
- result = copy_to_user((char *)arg, UDF_SB_VOLIDENT(inode->i_sb), 32);
- return result;
+ return copy_to_user((char *)arg,
+ UDF_SB_VOLIDENT(inode->i_sb), 32) ? -EFAULT : 0;
case UDF_RELOCATE_BLOCKS:
{
long old, new;
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- get_user(old, (long *)arg);
- if ((result = udf_relocate_blocks(inode->i_sb, old, &new)) == 0)
+ if (get_user(old, (long *)arg)) return -EFAULT;
+ if ((result = udf_relocate_blocks(inode->i_sb,
+ old, &new)) == 0)
result = put_user(new, (long *)arg);
return result;
switch (cmd)
{
case UDF_GETEASIZE:
- if ( (result = verify_area(VERIFY_WRITE, (char *)arg, 4)) == 0)
- result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
+ result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
break;
case UDF_GETEABLOCK:
- if ( (result = verify_area(VERIFY_WRITE, (char *)arg, UDF_I_LENEATTR(inode))) == 0)
- result = copy_to_user((char *)arg, ea, UDF_I_LENEATTR(inode));
- break;
-
- default:
+ result = copy_to_user((char *)arg, ea,
+ UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
break;
}
mark_buffer_dirty(UDF_SB_LVIDBH(sb));
}
-
unlock_super(sb);
- udf_free_blocks(inode, UDF_I_LOCATION(inode), 0, 1);
+ udf_free_blocks(sb, NULL, UDF_I_LOCATION(inode), 0, 1);
}
struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
}
*err = -ENOSPC;
- block = udf_new_block(dir, UDF_I_LOCATION(dir).partitionReferenceNum,
+ block = udf_new_block(dir->i_sb, NULL, UDF_I_LOCATION(dir).partitionReferenceNum,
start, err);
if (*err)
{
}
/* alloc block, and copy data to it */
- *block = udf_new_block(inode,
+ *block = udf_new_block(inode->i_sb, inode,
UDF_I_LOCATION(inode).partitionReferenceNum,
UDF_I_LOCATION(inode).logicalBlockNum, err);
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
/* UniqueID stuff */
- inode->i_blocks = inode->i_sb->s_blocksize / 512;
mark_buffer_dirty(sbh);
udf_release_data(sbh);
mark_inode_dirty(inode);
Uint32 elen = 0;
lb_addr eloc, pbloc, cbloc, nbloc;
int c = 1;
- int lbcount = 0, b_off = 0, offset = 0;
- Uint32 newblocknum, newblock;
- char etype;
+ Uint64 lbcount = 0, b_off = 0;
+ Uint32 newblocknum, newblock, offset = 0;
+ Sint8 etype;
int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
char lastblock = 0;
pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
- b_off = block << inode->i_sb->s_blocksize_bits;
+ b_off = (Uint64)block << inode->i_sb->s_blocksize_bits;
pbloc = cbloc = nbloc = UDF_I_LOCATION(inode);
/* find the extent which contains the block we are looking for.
goal = UDF_I_LOCATION(inode).logicalBlockNum + 1;
}
- if (!(newblocknum = udf_new_block(inode,
+ if (!(newblocknum = udf_new_block(inode->i_sb, inode,
UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
{
udf_release_data(pbh);
UDF_I_NEXT_ALLOC_GOAL(inode) = newblocknum;
inode->i_ctime = CURRENT_TIME;
UDF_I_UCTIME(inode) = CURRENT_UTIME;
- inode->i_blocks += inode->i_sb->s_blocksize / 512;
+
if (IS_SYNC(inode))
udf_sync_inode(inode);
else
int next = laarr[start].extLocation.logicalBlockNum +
(((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
- int numalloc = udf_prealloc_blocks(inode,
+ int numalloc = udf_prealloc_blocks(inode->i_sb, inode,
laarr[start].extLocation.partitionReferenceNum,
next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ? length :
UDF_DEFAULT_PREALLOC_BLOCKS) - currlength);
int create, int * err)
{
struct buffer_head * bh = NULL;
- int prev_blocks;
-
- prev_blocks = inode->i_blocks;
bh = udf_getblk(inode, block, create, err);
if (!bh)
return inode;
}
-int udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
+Sint8 udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr eloc, Uint32 elen, struct buffer_head **bh, int inc)
{
int adsize;
int err, loffset;
lb_addr obloc = *bloc;
- if (!(bloc->logicalBlockNum = udf_new_block(inode,
+ if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, inode,
obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
{
return -1;
return ret;
}
-int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
+Sint8 udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
lb_addr eloc, Uint32 elen, struct buffer_head *bh, int inc)
{
int adsize;
return (elen >> 30);
}
-int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
+Sint8 udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc)
{
Uint16 tagIdent;
int pos, alen;
- Uint8 etype;
+ Sint8 etype;
if (!(*bh))
{
return -1;
}
-int udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
+Sint8 udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc)
{
int pos, alen;
- Uint8 etype;
+ Sint8 etype;
if (!(*bh))
{
return -1;
}
-int udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
+Sint8 udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
lb_addr neloc, Uint32 nelen, struct buffer_head *bh)
{
lb_addr oeloc;
Uint32 oelen;
- int type;
+ Sint8 etype;
if (!bh)
{
else
atomic_inc(&bh->b_count);
- while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
+ while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
{
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
neloc = oeloc;
- nelen = (type << 30) | oelen;
+ nelen = (etype << 30) | oelen;
}
udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
udf_release_data(bh);
return (nelen >> 30);
}
-int udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
+Sint8 udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
lb_addr eloc, Uint32 elen, struct buffer_head *nbh)
{
struct buffer_head *obh;
lb_addr obloc;
int oextoffset, adsize;
- char type;
+ Sint8 etype;
struct AllocExtDesc *aed;
if (!(nbh))
if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1)
return -1;
- while ((type = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
+ while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
{
- udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, obh, 1);
+ udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
{
obloc = nbloc;
if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
{
- udf_free_blocks(inode, nbloc, 0, 1);
+ udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
return (elen >> 30);
}
-int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
+Sint8 inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
lb_addr *eloc, Uint32 *elen, Uint32 *offset, struct buffer_head **bh)
{
- Uint64 lbcount = 0, bcount = block << inode->i_sb->s_blocksize_bits;
- char etype;
+ Uint64 lbcount = 0, bcount = (Uint64)block << inode->i_sb->s_blocksize_bits;
+ Sint8 etype;
if (block < 0)
{
static int udf_rmdir(struct inode * dir, struct dentry * dentry)
{
int retval;
- struct inode * inode;
+ struct inode * inode = dentry->d_inode;
struct udf_fileident_bh fibh;
struct FileIdentDesc *fi, cfi;
if (!fi)
goto out;
- inode = dentry->d_inode;
- DQUOT_INIT(inode);
-
retval = -EIO;
if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) != inode->i_ino)
goto end_rmdir;
static int udf_unlink(struct inode * dir, struct dentry * dentry)
{
int retval;
- struct inode * inode;
+ struct inode * inode = dentry->d_inode;
struct udf_fileident_bh fibh;
struct FileIdentDesc *fi;
struct FileIdentDesc cfi;
if (!fi)
goto out;
- inode = dentry->d_inode;
- DQUOT_INIT(inode);
-
retval = -EIO;
if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) !=
lb_addr bloc, eloc;
Uint32 elen, extoffset;
- block = udf_new_block(inode,
+ block = udf_new_block(inode->i_sb, inode,
UDF_I_LOCATION(inode).partitionReferenceNum,
UDF_I_LOCATION(inode).logicalBlockNum, &err);
if (!block)
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0);
udf_release_data(bh);
- inode->i_blocks = inode->i_sb->s_blocksize / 512;
block = udf_get_pblock(inode->i_sb, block,
UDF_I_LOCATION(inode).partitionReferenceNum, 0);
bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize);
static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
struct inode * new_dir, struct dentry * new_dentry)
{
- struct inode * old_inode, * new_inode;
+ struct inode * old_inode = old_dentry->d_inode;
+ struct inode * new_inode = new_dentry->d_inode;
struct udf_fileident_bh ofibh, nfibh;
struct FileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;
struct buffer_head *dir_bh = NULL;
int retval = -ENOENT;
- old_inode = old_dentry->d_inode;
if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi)))
{
if (ofibh.sbh != ofibh.ebh)
goto end_rename;
}
- new_inode = new_dentry->d_inode;
nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);
if (nfi)
{
udf_release_data(nfibh.sbh);
nfi = NULL;
}
- else
- {
- DQUOT_INIT(new_inode);
- }
}
if (S_ISDIR(old_inode->i_mode))
{
static int udf_load_partition(struct super_block *, lb_addr *);
static int udf_load_logicalvol(struct super_block *, struct buffer_head *, lb_addr *);
static void udf_load_logicalvolint(struct super_block *, extent_ad);
-static int udf_find_anchor(struct super_block *, int, int);
+static void udf_find_anchor(struct super_block *);
static int udf_find_fileset(struct super_block *, lb_addr *, lb_addr *);
static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
static void udf_load_fileset(struct super_block *, struct buffer_head *, lb_addr *);
* noadinicb Don't embed data in the inode
* shortad Use short ad's
* longad Use long ad's (default)
- * strict Set strict conformance
+ * nostrict Unset strict conformance
* iocharset= Set the NLS character set
*
* The remaining are for debugging and disaster recovery:
uopt->blocksize = 2048;
uopt->partition = 0xFFFF;
uopt->session = 0xFFFFFFFF;
- uopt->lastblock = 0xFFFFFFFF;
- uopt->anchor = 0xFFFFFFFF;
+ uopt->lastblock = 0;
+ uopt->anchor = 0;
uopt->volume = 0xFFFFFFFF;
uopt->rootdir = 0xFFFFFFFF;
uopt->fileset = 0xFFFFFFFF;
uopt->gid = simple_strtoul(val, NULL, 0);
else if (!strcmp(opt, "umask") && val)
uopt->umask = simple_strtoul(val, NULL, 0);
- else if (!strcmp(opt, "strict") && !val)
- uopt->flags |= (1 << UDF_FLAG_STRICT);
+ else if (!strcmp(opt, "nostrict") && !val)
+ uopt->flags &= ~(1 << UDF_FLAG_STRICT);
else if (!strcmp(opt, "uid") && val)
uopt->uid = simple_strtoul(val, NULL, 0);
else if (!strcmp(opt, "session") && val)
* July 1, 1997 - Andrew E. Mileski
* Written, tested, and released.
*/
-static int
-udf_find_anchor(struct super_block *sb, int useranchor, int lastblock)
+static void
+udf_find_anchor(struct super_block *sb)
{
- int varlastblock = udf_variable_to_fixed(lastblock);
- int last[] = { lastblock, lastblock - 2,
- lastblock - 150, lastblock - 152,
- varlastblock, varlastblock - 2,
- varlastblock - 150, varlastblock - 152 };
+ int lastblock = UDF_SB_LASTBLOCK(sb);
struct buffer_head *bh = NULL;
Uint16 ident;
Uint32 location;
int i;
- UDF_SB_ANCHOR(sb)[0] = 0;
- UDF_SB_ANCHOR(sb)[1] = 0;
- UDF_SB_ANCHOR(sb)[2] = 0;
- UDF_SB_ANCHOR(sb)[3] = 256 + UDF_SB_SESSION(sb);
+ if (lastblock)
+ {
+ int varlastblock = udf_variable_to_fixed(lastblock);
+ int last[] = { lastblock, lastblock - 2,
+ lastblock - 150, lastblock - 152,
+ varlastblock, varlastblock - 2,
+ varlastblock - 150, varlastblock - 152 };
- lastblock = 0;
+ lastblock = 0;
- /* Search for an anchor volume descriptor pointer */
+ /* Search for an anchor volume descriptor pointer */
- /* according to spec, anchor is in either:
- * block 256
- * lastblock-256
- * lastblock
- * however, if the disc isn't closed, it could be 512 */
+ /* according to spec, anchor is in either:
+ * block 256
+ * lastblock-256
+ * lastblock
+ * however, if the disc isn't closed, it could be 512 */
- for (i=0; (!lastblock && i<sizeof(last)/sizeof(int)); i++)
- {
- if (last[i] < 0 || !(bh = bread(sb->s_dev, last[i], sb->s_blocksize)))
- {
- ident = location = 0;
- }
- else
+ for (i=0; (!lastblock && i<sizeof(last)/sizeof(int)); i++)
{
- ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
- location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
- udf_release_data(bh);
- }
-
- if (ident == TID_ANCHOR_VOL_DESC_PTR)
- {
- if (location == last[i] - UDF_SB_SESSION(sb))
- {
- lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
- UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
- }
- else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
- {
- UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
- lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
- UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
- }
- else
- udf_debug("Anchor found at block %d, location mismatch %d.\n",
- last[i], location);
- }
- else if (ident == TID_FILE_ENTRY || ident == TID_EXTENDED_FILE_ENTRY)
- {
- lastblock = last[i];
- UDF_SB_ANCHOR(sb)[2] = 512 + UDF_SB_SESSION(sb);
- }
- else
- {
- if (!(bh = bread(sb->s_dev, last[i] - 256, sb->s_blocksize)))
+ if (last[i] < 0 || !(bh = bread(sb->s_dev, last[i], sb->s_blocksize)))
{
ident = location = 0;
}
location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
udf_release_data(bh);
}
-
- if (ident == TID_ANCHOR_VOL_DESC_PTR &&
- location == last[i] - 256 - UDF_SB_SESSION(sb))
+
+ if (ident == TID_ANCHOR_VOL_DESC_PTR)
+ {
+ if (location == last[i] - UDF_SB_SESSION(sb))
+ {
+ lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
+ UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
+ }
+ else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
+ {
+ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+ lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
+ UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
+ }
+ else
+ udf_debug("Anchor found at block %d, location mismatch %d.\n",
+ last[i], location);
+ }
+ else if (ident == TID_FILE_ENTRY || ident == TID_EXTENDED_FILE_ENTRY)
{
lastblock = last[i];
- UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
+ UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb);
}
else
{
- if (!(bh = bread(sb->s_dev, last[i] - 312 - UDF_SB_SESSION(sb),
- sb->s_blocksize)))
+ if (last[i] < 256 || !(bh = bread(sb->s_dev, last[i] - 256, sb->s_blocksize)))
{
ident = location = 0;
}
location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
udf_release_data(bh);
}
-
+
if (ident == TID_ANCHOR_VOL_DESC_PTR &&
- location == udf_variable_to_fixed(last[i]) - 256)
+ location == last[i] - 256 - UDF_SB_SESSION(sb))
{
- UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
- lastblock = udf_variable_to_fixed(last[i]);
- UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
+ lastblock = last[i];
+ UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
+ }
+ else
+ {
+ if (last[i] < 312 + UDF_SB_SESSION(sb) || !(bh = bread(sb->s_dev, last[i] - 312 - UDF_SB_SESSION(sb),
+ sb->s_blocksize)))
+ {
+ ident = location = 0;
+ }
+ else
+ {
+ ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent);
+ location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
+ udf_release_data(bh);
+ }
+
+ if (ident == TID_ANCHOR_VOL_DESC_PTR &&
+ location == udf_variable_to_fixed(last[i]) - 256)
+ {
+ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+ lastblock = udf_variable_to_fixed(last[i]);
+ UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
+ }
}
}
}
}
}
}
- else if (useranchor != 0xFFFFFFFF)
- {
- UDF_SB_ANCHOR(sb)[i] = useranchor;
- useranchor = 0xFFFFFFFF;
- i --;
- }
}
- return lastblock;
+ UDF_SB_LASTBLOCK(sb) = lastblock;
}
static int
struct buffer_head *bh = NULL;
Uint16 ident;
- while ((bh = udf_read_tagged(sb, loc.extLocation, loc.extLocation, &ident)) &&
- ident == TID_LOGICAL_VOL_INTEGRITY_DESC && loc.extLength > 0)
+ while (loc.extLength > 0 &&
+ (bh = udf_read_tagged(sb, loc.extLocation,
+ loc.extLocation, &ident)) &&
+ ident == TID_LOGICAL_VOL_INTEGRITY_DESC)
{
UDF_SB_LVIDBH(sb) = bh;
else if ((block = udf_vrs(sb, silent)) == -1)
{
udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n");
+ if (!UDF_SB_LASTBLOCK(sb))
+ UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb);
return 0;
}
else
{
lb_addr ino;
+ if (!UDF_SB_LASTBLOCK(sb))
+ {
+ UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb);
+ udf_find_anchor(sb);
+ }
+
if (!UDF_SB_LASTBLOCK(sb))
{
udf_debug("Unable to determine Lastblock (For Virtual Partition)\n");
struct udf_options uopt;
lb_addr rootdir, fileset;
- uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB);
+ uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
uopt.uid = -1;
uopt.gid = -1;
uopt.umask = 0;
udf_debug("Multi-session=%d\n", UDF_SB_SESSION(sb));
- if ( uopt.lastblock == 0xFFFFFFFF )
- UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb);
- else
- UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
-
- UDF_SB_LASTBLOCK(sb) = udf_find_anchor(sb, uopt.anchor, UDF_SB_LASTBLOCK(sb));
-
- udf_debug("Lastblock=%d\n", UDF_SB_LASTBLOCK(sb));
+ UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
+ UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0;
+ UDF_SB_ANCHOR(sb)[2] = uopt.anchor;
+ UDF_SB_ANCHOR(sb)[3] = UDF_SB_SESSION(sb) + 256;
if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
{
goto error_out;
}
+ udf_find_anchor(sb);
+
/* Fill in the rest of the superblock */
sb->s_op = &udf_sb_ops;
sb->dq_op = NULL;
goto error_out;
}
+ udf_debug("Lastblock=%d\n", UDF_SB_LASTBLOCK(sb));
+
if ( UDF_SB_LVIDBH(sb) )
{
Uint16 minUDFReadRev = le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev);
unsigned int accum = 0;
Uint32 extoffset, elen;
lb_addr bloc, eloc;
- char etype;
+ Sint8 etype;
struct buffer_head *bh = NULL;
bloc = UDF_I_LOCATION(table);
{
unsigned int accum = 0;
+ if (UDF_SB_LVIDBH(sb))
+ {
+ if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb))
+ {
+ accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]);
+
+ if (accum == 0xFFFFFFFF)
+ accum = 0;
+ }
+ }
+
+ if (accum)
+ return accum;
+
if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
{
accum += udf_count_free_bitmap(sb,
accum += udf_count_free_table(sb,
UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
}
- if (accum)
- return accum;
- if (UDF_SB_LVIDBH(sb))
- {
- if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb))
- {
- accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]);
-
- if (accum == 0xFFFFFFFF)
- accum = 0;
- }
- }
return accum;
}
#include "udf_sb.h"
static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
- lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head *bh, Uint32 nelen)
+ lb_addr eloc, Sint8 etype, Uint32 elen, struct buffer_head *bh, Uint32 nelen)
{
lb_addr neloc = { 0, 0 };
- int blocks = inode->i_sb->s_blocksize / 512;
int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
if (last_block - first_block > 0)
{
if (etype == EXTENT_RECORDED_ALLOCATED)
- {
- inode->i_blocks -= (blocks * (last_block - first_block));
mark_inode_dirty(inode);
- }
+
if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
- udf_free_blocks(inode, eloc, first_block, last_block - first_block);
+ udf_free_blocks(inode->i_sb, inode, eloc, first_block, last_block - first_block);
}
}
}
{
lb_addr bloc, eloc, neloc = { 0, 0 };
Uint32 extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
- int etype;
+ Sint8 etype;
int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
struct buffer_head *bh = NULL;
int adsize;
memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
else
memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
- udf_free_blocks(inode, bloc, 0, lelen);
+ udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
}
else
{
memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
else
memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
- udf_free_blocks(inode, bloc, 0, lelen);
+ udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
}
else
{
#include <linux/config.h>
#include <linux/types.h>
-
#include <linux/fs.h>
#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
extern void udf_delete_inode(struct inode *);
extern void udf_write_inode(struct inode *, int);
extern long udf_block_map(struct inode *, long);
-extern int inode_bmap(struct inode *, int, lb_addr *, Uint32 *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **);
-extern int udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, Uint32, struct buffer_head **, int);
-extern int udf_write_aext(struct inode *, lb_addr, int *, lb_addr, Uint32, struct buffer_head *, int);
-extern int udf_insert_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
-extern int udf_delete_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
-extern int udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
-extern int udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
+extern Sint8 inode_bmap(struct inode *, int, lb_addr *, Uint32 *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **);
+extern Sint8 udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, Uint32, struct buffer_head **, int);
+extern Sint8 udf_write_aext(struct inode *, lb_addr, int *, lb_addr, Uint32, struct buffer_head *, int);
+extern Sint8 udf_insert_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
+extern Sint8 udf_delete_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
+extern Sint8 udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
+extern Sint8 udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
extern void udf_discard_prealloc(struct inode *);
/* misc.c */
extern void udf_truncate_extents(struct inode *);
/* balloc.c */
-extern void udf_free_blocks(struct inode *, lb_addr, Uint32, Uint32);
-extern int udf_prealloc_blocks(struct inode *, Uint16, Uint32, Uint32);
-extern int udf_new_block(struct inode *, Uint16, Uint32, int *);
+extern void udf_free_blocks(struct super_block *, struct inode *, lb_addr, Uint32, Uint32);
+extern int udf_prealloc_blocks(struct super_block *, struct inode *, Uint16, Uint32, Uint32);
+extern int udf_new_block(struct super_block *, struct inode *, Uint16, Uint32, int *);
/* fsync.c */
extern int udf_fsync_file(struct file *, struct dentry *, int);
#ifndef __ARM_A_OUT_H__
#define __ARM_A_OUT_H__
+#include <linux/personality.h>
#include <asm/types.h>
struct exec
* SKID ID Register
*/
-#define _SKCR _SA1111( 0x0000 )
-#define _SMCR _SA1111( 0x0004 )
-#define _SKID _SA1111( 0x0008 )
+#define _SBI_SKCR _SA1111( 0x0000 )
+#define _SBI_SMCR _SA1111( 0x0004 )
+#define _SBI_SKID _SA1111( 0x0008 )
#if LANGUAGE == C
-#define SKCR (*((volatile Word *) SA1111_p2v (_SKCR)))
-#define SMCR (*((volatile Word *) SA1111_p2v (_SMCR)))
-#define SKID (*((volatile Word *) SA1111_p2v (_SKID)))
+#define SBI_SKCR (*((volatile Word *) SA1111_p2v (_SBI_SKCR)))
+#define SBI_SMCR (*((volatile Word *) SA1111_p2v (_SBI_SMCR)))
+#define SBI_SKID (*((volatile Word *) SA1111_p2v (_SBI_SKID)))
#endif /* LANGUAGE == C */
#define SKCR_OPPC (1<<9)
#define SKCR_PLLTSTEN (1<<10)
#define SKCR_USBIOTSTEN (1<<11)
+/*
+ * Don't believe the specs! Take them, throw them outside. Leave them
+ * there for a week. Spit on them. Walk on them. Stamp on them.
+ * Pour gasoline over them and finally burn them. Now think about coding.
+ * - The October 1999 errata (278260-007) says its bit 13, 1 to enable.
+ * - The Feb 2001 errata (278260-010) says that the previous errata
+ * (278260-009) is wrong, and its bit actually 12, fixed in spec
+ * 278242-003.
+ * - The SA1111 manual (278242) says bit 12, but 0 to enable.
+ * - Reality is bit 13, 1 to enable.
+ * -- rmk
+ */
#define SKCR_OE_EN (1<<13)
#define SMCR_DTIM (1<<0)
#define SKPCR_DCLKEN (1<<7)
#define SKPCR_PWMCLKEN (1<<8)
+/*
+ * USB Host controller
+ */
+#define _USB_OHCI_OP_BASE _SA1111( 0x400 )
+#define _USB_STATUS _SA1111( 0x518 )
+#define _USB_RESET _SA1111( 0x51c )
+#define _USB_INTERRUPTEST _SA1111( 0x520 )
+
+#define _USB_EXTENT (_USB_INTERRUPTEST - _USB_OHCI_OP_BASE + 4)
+
+#if LANGUAGE == C
+
+#define USB_OHCI_OP_BASE (*((volatile Word *) SA1111_p2v (_USB_OHCI_OP_BASE)))
+#define USB_STATUS (*((volatile Word *) SA1111_p2v (_USB_STATUS)))
+#define USB_RESET (*((volatile Word *) SA1111_p2v (_USB_RESET)))
+#define USB_INTERRUPTEST (*((volatile Word *) SA1111_p2v (_USB_INTERRUPTEST)))
+
+#endif /* LANGUAGE == C */
+
+#define USB_RESET_FORCEIFRESET (1 << 0)
+#define USB_RESET_FORCEHCRESET (1 << 1)
+#define USB_RESET_CLKGENRESET (1 << 2)
+#define USB_RESET_SIMSCALEDOWN (1 << 3)
+#define USB_RESET_USBINTTEST (1 << 4)
+#define USB_RESET_SLEEPSTBYEN (1 << 5)
+#define USB_RESET_PWRSENSELOW (1 << 6)
+#define USB_RESET_PWRCTRLLOW (1 << 7)
+
/*
* Serial Audio Controller
*
--- /dev/null
+/*
+ * linux/include/asm-arm/arch-sa1100/adsbitsy.h
+ *
+ * Created 7/3/01 by Woojung <whuh@applieddata.net>
+ *
+ * This file contains the hardware specific definitions for the
+ * ADS Bitsy Board
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error "include <asm/hardware.h> instead"
+#endif
+
+#define SA1111_BASE (0x18000000)
#define BCR_DB1111 \
(BCR_SPK_OFF | BCR_QMUTE | BCR_LED_GREEN | BCR_LED_RED | \
BCR_RS232EN | BCR_LCD_12RGB | BCR_CF_BUS_OFF | BCR_STEREO_LB | \
- BCR_IRDA_MD1 | BCR_CF_RST)
+ BCR_IRDA_MD0 | BCR_CF_RST)
#define BCR_CF_PWR (1<<0) /* Compact Flash Power (1 = 3.3v, 0 = off) */
#define BCR_CF_RST (1<<1) /* Compact Flash Reset (1 = power up reset) */
#define NCR_A1VPP (1<<6)
#ifndef __ASSEMBLY__
+#ifdef CONFIG_ASSABET_NEPONSET
#define machine_has_neponset() ((SCR_value & SCR_SA1111) == 0)
+#else
+#define machine_has_neponset() (0)
+#endif
#endif
+++ /dev/null
-/*
-*
-* Definitions for H3600 Handheld Computer
-*
-* Copyright 2000 Compaq Computer Corporation.
-*
-* Use consistent with the GNU GPL is permitted,
-* provided that this copyright notice is
-* preserved in its entirety in all copies and derived works.
-*
-* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
-* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
-* FITNESS FOR ANY PARTICULAR PURPOSE.
-*
-* Author: Jamey Hicks.
-*
-*/
-
-#ifndef _INCLUDE_BITSY_H_
-#define _INCLUDE_BITSY_H_
-
-#define GPIO_BITSY_NPOWER_BUTTON GPIO_GPIO (0)
-#define GPIO_BITSY_ACTION_BUTTON GPIO_GPIO (18)
-
-#define GPIO_BITSY_PCMCIA_CD0 GPIO_GPIO (17)
-#define GPIO_BITSY_PCMCIA_CD1 GPIO_GPIO (10)
-#define GPIO_BITSY_PCMCIA_IRQ0 GPIO_GPIO (21)
-#define GPIO_BITSY_PCMCIA_IRQ1 GPIO_GPIO (11)
-
-/* audio sample rate clock generator */
-#define GPIO_BITSY_CLK_SET0 GPIO_GPIO (12)
-#define GPIO_BITSY_CLK_SET1 GPIO_GPIO (13)
-
-/* UDA1341 L3 Interface */
-#define GPIO_BITSY_L3_DATA GPIO_GPIO (14)
-#define GPIO_BITSY_L3_CLOCK GPIO_GPIO (16)
-#define GPIO_BITSY_L3_MODE GPIO_GPIO (15)
-
-#define GPIO_BITSY_OPT_LOCK GPIO_GPIO (22)
-#define GPIO_BITSY_OPT_IRQ GPIO_GPIO (24)
-#define GPIO_BITSY_OPT_DET GPIO_GPIO (27)
-
-#define GPIO_BITSY_COM_DCD GPIO_GPIO (23)
-#define GPIO_BITSY_COM_CTS GPIO_GPIO (25)
-#define GPIO_BITSY_COM_RTS GPIO_GPIO (26)
-
-#define IRQ_GPIO_BITSY_NPOWER_BUTTON IRQ_GPIO0
-#define IRQ_GPIO_BITSY_ACTION_BUTTON IRQ_GPIO18
-#define IRQ_GPIO_BITSY_PCMCIA_CD0 IRQ_GPIO17
-#define IRQ_GPIO_BITSY_PCMCIA_CD1 IRQ_GPIO10
-#define IRQ_GPIO_BITSY_PCMCIA_IRQ0 IRQ_GPIO21
-#define IRQ_GPIO_BITSY_PCMCIA_IRQ1 IRQ_GPIO11
-#define IRQ_GPIO_BITSY_OPT_IRQ IRQ_GPIO24
-#define IRQ_GPIO_BITSY_OPT_DET IRQ_GPIO27
-#define IRQ_GPIO_BITSY_COM_DCD IRQ_GPIO23
-#define IRQ_GPIO_BITSY_COM_CTS IRQ_GPIO25
-
-#define EGPIO_BITSY_VPP_ON (1 << 0)
-#define EGPIO_BITSY_CARD_RESET (1 << 1) /* reset the attached pcmcia/compactflash card. active high. */
-#define EGPIO_BITSY_OPT_RESET (1 << 2) /* reset the attached option pack. active high. */
-#define EGPIO_BITSY_CODEC_NRESET (1 << 3) /* reset the onboard UDA1341. active low. */
-#define EGPIO_BITSY_OPT_NVRAM_ON (1 << 4) /* apply power to optionpack nvram, active high. */
-#define EGPIO_BITSY_OPT_ON (1 << 5) /* full power to option pack. active high. */
-#define EGPIO_BITSY_LCD_ON (1 << 6) /* enable 3.3V to LCD. active high. */
-#define EGPIO_BITSY_RS232_ON (1 << 7) /* UART3 transceiver force on. Active high. */
-#define EGPIO_BITSY_LCD_PCI (1 << 8) /* LCD control IC enable. active high. */
-#define EGPIO_BITSY_IR_ON (1 << 9) /* apply power to IR module. active high. */
-#define EGPIO_BITSY_AUD_AMP_ON (1 << 10) /* apply power to audio power amp. active high. */
-#define EGPIO_BITSY_AUD_PWR_ON (1 << 11) /* apply poewr to reset of audio circuit. active high. */
-#define EGPIO_BITSY_QMUTE (1 << 12) /* mute control for onboard UDA1341. active high. */
-#define EGPIO_BITSY_IR_FSEL (1 << 13) /* IR speed select: 1->fast, 0->slow */
-#define EGPIO_BITSY_LCD_5V_ON (1 << 14) /* enable 5V to LCD. active high. */
-#define EGPIO_BITSY_LVDD_ON (1 << 15) /* enable 9V and -6.5V to LCD. */
-
-#ifndef __ASSEMBLY__
-#define BITSY_EGPIO (*(volatile int *)0xf0000000)
-extern void clr_bitsy_egpio(unsigned long x);
-extern void set_bitsy_egpio(unsigned long x);
-#endif
-
-#endif
static inline void
__arch_adjust_zones(int node, unsigned long *size, unsigned long *holes)
{
- size[1] = size[0] - 256;
- size[0] = 256;
+ unsigned int sz = 256;
+
+ if (node != 0)
+ sz = 0;
+
+ size[1] = size[0] - sz;
+ size[0] = sz;
}
#define arch_adjust_zones(node,size,holes) __arch_adjust_zones(node,size,holes)
--- /dev/null
+/*
+ * linux/include/asm-arm/arch-sa1100/graphicsmaster.h
+ *
+ * Created 2000/12/18 by Woojung Huh <whuh@applieddata.net>
+ *
+ * This file comes from graphicsclient.h of Nicolas Pitre <nico@cam.org>
+ *
+ * This file contains the hardware specific definitions for the
+ * ADS GraphicsMaster
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error "include <asm/hardware.h> instead"
+#endif
+
+#define ADS_CPLD_BASE (0x10000000)
+#define ADS_p2v( x ) ((x) - ADS_CPLD_BASE + 0xf0000000)
+#define ADS_v2p( x ) ((x) - 0xf0000000 + ADS_CPLD_BASE)
+
+
+#define _ADS_SW_SWITCHES 0x10060000 /* Software Switches */
+
+/* Extra IRQ Controller */
+#define _ADS_INT_ST1 0x10080000 /* IRQ Status #1 */
+#define _ADS_INT_ST2 0x10080004 /* IRQ Status #2 */
+#define _ADS_INT_EN1 0x10080008 /* IRQ Enable #1 */
+#define _ADS_INT_EN2 0x1008000c /* IRQ Enable #2 */
+#define _ADS_DCR 0x10080018 /* Discrete Control Reg */
+
+/* Discrete Controller (AVR:Atmel AT90LS8535) */
+#define _ADS_AVR_REG 0x10080018
+
+/* On-Board Ethernet */
+#define _ADS_ETHERNET 0x100e0000 /* Ethernet */
+
+/* On-Board Quad UART 16C554 */
+#define ADS_QUAD_UART1 0x10100000
+#define ADS_QUAD_UART2 0x10120000
+#define ADS_QUAD_UART3 0x10140000
+#define ADS_QUAD_UART4 0x10160000
+
+/* LEDs */
+#define ADS_LED0 GPIO_GPIO20 /* on-board Green */
+#define ADS_LED1 GPIO_GPIO25 /* on-board Yellow */
+#define ADS_LED2 GPIO_GPIO26 /* on-board Red */
+
+/* DCR */
+#define DCR_AVR_RESET 0x01
+#define DCR_SA1111_RESET 0x02
+#define DCR_BACKLITE_ON 0x04
+
+/* Virtual register addresses */
+
+#ifndef __ASSEMBLY__
+#define ADS_INT_ST1 (*((volatile u_char *) ADS_p2v(_ADS_INT_ST1)))
+#define ADS_INT_ST2 (*((volatile u_char *) ADS_p2v(_ADS_INT_ST2)))
+#define ADS_INT_EN1 (*((volatile u_char *) ADS_p2v(_ADS_INT_EN1)))
+#define ADS_INT_EN2 (*((volatile u_char *) ADS_p2v(_ADS_INT_EN2)))
+#define ADS_ETHERNET ((int) ADS_p2v(_ADS_ETHERNET))
+#define ADS_AVR_REG (*((volatile u_char *) ADS_p2v(_ADS_AVR_REG)))
+#define ADS_DCR (*((volatile u_char *) ADS_p2v(_ADS_DCR)))
+#endif
+
+#define SA1111_BASE (0x18000000)
+
+#include "SA-1111.h"
--- /dev/null
+/*
+*
+* Definitions for H3600 Handheld Computer
+*
+* Copyright 2000 Compaq Computer Corporation.
+*
+* Use consistent with the GNU GPL is permitted,
+* provided that this copyright notice is
+* preserved in its entirety in all copies and derived works.
+*
+* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+* FITNESS FOR ANY PARTICULAR PURPOSE.
+*
+* Author: Jamey Hicks.
+*
+*/
+
+#ifndef _INCLUDE_H3600_H_
+#define _INCLUDE_H3600_H_
+
+#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0)
+#define GPIO_H3600_ACTION_BUTTON GPIO_GPIO (18)
+
+#define GPIO_H3600_PCMCIA_CD0 GPIO_GPIO (17)
+#define GPIO_H3600_PCMCIA_CD1 GPIO_GPIO (10)
+#define GPIO_H3600_PCMCIA_IRQ0 GPIO_GPIO (21)
+#define GPIO_H3600_PCMCIA_IRQ1 GPIO_GPIO (11)
+
+/* audio sample rate clock generator */
+#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12)
+#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13)
+
+/* UDA1341 L3 Interface */
+#define GPIO_H3600_L3_DATA GPIO_GPIO (14)
+#define GPIO_H3600_L3_CLOCK GPIO_GPIO (16)
+#define GPIO_H3600_L3_MODE GPIO_GPIO (15)
+
+#define GPIO_H3600_OPT_LOCK GPIO_GPIO (22)
+#define GPIO_H3600_OPT_IRQ GPIO_GPIO (24)
+#define GPIO_H3600_OPT_DET GPIO_GPIO (27)
+
+#define GPIO_H3600_COM_DCD GPIO_GPIO (23)
+#define GPIO_H3600_COM_CTS GPIO_GPIO (25)
+#define GPIO_H3600_COM_RTS GPIO_GPIO (26)
+
+#define IRQ_GPIO_H3600_NPOWER_BUTTON IRQ_GPIO0
+#define IRQ_GPIO_H3600_ACTION_BUTTON IRQ_GPIO18
+#define IRQ_GPIO_H3600_PCMCIA_CD0 IRQ_GPIO17
+#define IRQ_GPIO_H3600_PCMCIA_CD1 IRQ_GPIO10
+#define IRQ_GPIO_H3600_PCMCIA_IRQ0 IRQ_GPIO21
+#define IRQ_GPIO_H3600_PCMCIA_IRQ1 IRQ_GPIO11
+#define IRQ_GPIO_H3600_OPT_IRQ IRQ_GPIO24
+#define IRQ_GPIO_H3600_OPT_DET IRQ_GPIO27
+#define IRQ_GPIO_H3600_COM_DCD IRQ_GPIO23
+#define IRQ_GPIO_H3600_COM_CTS IRQ_GPIO25
+
+#define EGPIO_H3600_VPP_ON (1 << 0)
+#define EGPIO_H3600_CARD_RESET (1 << 1) /* reset the attached pcmcia/compactflash card. active high. */
+#define EGPIO_H3600_OPT_RESET (1 << 2) /* reset the attached option pack. active high. */
+#define EGPIO_H3600_CODEC_NRESET (1 << 3) /* reset the onboard UDA1341. active low. */
+#define EGPIO_H3600_OPT_NVRAM_ON (1 << 4) /* apply power to optionpack nvram, active high. */
+#define EGPIO_H3600_OPT_ON (1 << 5) /* full power to option pack. active high. */
+#define EGPIO_H3600_LCD_ON (1 << 6) /* enable 3.3V to LCD. active high. */
+#define EGPIO_H3600_RS232_ON (1 << 7) /* UART3 transceiver force on. Active high. */
+#define EGPIO_H3600_LCD_PCI (1 << 8) /* LCD control IC enable. active high. */
+#define EGPIO_H3600_IR_ON (1 << 9) /* apply power to IR module. active high. */
+#define EGPIO_H3600_AUD_AMP_ON (1 << 10) /* apply power to audio power amp. active high. */
+#define EGPIO_H3600_AUD_PWR_ON (1 << 11) /* apply poewr to reset of audio circuit. active high. */
+#define EGPIO_H3600_QMUTE (1 << 12) /* mute control for onboard UDA1341. active high. */
+#define EGPIO_H3600_IR_FSEL (1 << 13) /* IR speed select: 1->fast, 0->slow */
+#define EGPIO_H3600_LCD_5V_ON (1 << 14) /* enable 5V to LCD. active high. */
+#define EGPIO_H3600_LVDD_ON (1 << 15) /* enable 9V and -6.5V to LCD. */
+
+#ifndef __ASSEMBLY__
+#define H3600_EGPIO (*(volatile int *)0xf0000000)
+extern void clr_h3600_egpio(unsigned long x);
+extern void set_h3600_egpio(unsigned long x);
+#endif
+
+#endif
#include "empeg.h"
#endif
-#ifdef CONFIG_SA1100_BITSY
-#include "bitsy.h"
+#ifdef CONFIG_SA1100_H3600
+#include "h3600.h"
#endif
#ifdef CONFIG_SA1100_ITSY
#include "simpad.h"
#endif
+#if defined(CONFIG_SA1100_GRAPHICSMASTER)
+#include "graphicsmaster.h"
+#endif
+
+#if defined(CONFIG_SA1100_ADSBITSY)
+#include "adsbitsy.h"
+#endif
+
#ifdef CONFIG_SA1101
/*
#define NR_IRQS (IRQ_GPIO27 + 1)
-#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
+#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || defined(CONFIG_SA1100_GRAPHICSMASTER)
#define ADS_EXT_IRQ(x) (IRQ_GPIO27 + 1 + (x))
#undef NR_IRQS
#define NR_IRQS (ADS_EXT_IRQ(15) + 1)
#if defined(CONFIG_SA1111)
+#if defined(CONFIG_SA1100_GRAPHICSMASTER)
+#define SA1111_IRQ(x) (ADS_EXT_IRQ(15) + 1 + 1 + (x))
+#else
#define SA1111_IRQ(x) (IRQ_GPIO27 + 1 + (x))
+#endif
#define GPAIN0 SA1111_IRQ(0)
#define GPAIN1 SA1111_IRQ(1)
#define _SA1100_KEYBOARD_H
#include <linux/config.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+extern struct kbd_ops_struct *kbd_ops;
-// #ifdef CONFIG_SA1100_BRUTUS
-/* need fixing... */
-#if 0
+#define kbd_disable_irq() do { } while(0);
+#define kbd_enable_irq() do { } while(0);
+
+
+/*
+ * SA1111 keyboard driver
+ */
+extern void sa1111_kbd_init_hw(void);
+
+/*
+ * GraphicsClient keyboard driver
+ */
+extern void gc_kbd_init_hw(void);
+
+static inline void kbd_init_hw(void)
+{
+ if (machine_is_assabet() && machine_has_neponset())
+ sa1111_kbd_init_hw();
+
+ if (machine_is_graphicsclient())
+ gc_kbd_init_hw();
+}
+
+
+
+#if 0 /* Brutus needs fixing */
extern int Brutus_kbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
#define SYSRQ_KEY 0x54
-#elif CONFIG_SA1100_GRAPHICSCLIENT
+#elif 0 // CONFIG_SA1100_GRAPHICSCLIENT
+extern int gc_kbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int gc_kbd_getkeycode(unsigned int scancode);
extern int gc_kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode);
extern void gc_kbd_leds(unsigned char leds);
extern void gc_kbd_init_hw(void);
extern void gc_kbd_disable_irq(void);
extern unsigned char gc_kbd_sysrq_xlate[128];
-#define kbd_setkeycode(x...) (-ENOSYS)
-#define kbd_getkeycode(x...) (-ENOSYS)
+#define kbd_setkeycode(x...) gc_kbd_setkeycode //(-ENOSYS)
+#define kbd_getkeycode(x...) gc_kbd_getkeycode //(-ENOSYS)
#define kbd_translate gc_kbd_translate
#define kbd_unexpected_up(x...) (1)
#define kbd_leds gc_kbd_leds
#define kbd_init_hw gc_kbd_init_hw
#define kbd_enable_irq gc_kbd_enable_irq
#define kbd_disable_irq gc_kbd_disable_irq
-#define kbd_sysrq_xlate gc_kbd_sysrq_xlate
-
-#elif CONFIG_SA1100_BITSY
-
-#define kbd_setkeycode(x...) (-ENOSYS)
-#define kbd_getkeycode(x...) (-ENOSYS)
-#define kbd_translate(sc_,kc_,rm_) ((*(kc_)=(sc_)),1)
-#define kbd_unexpected_up(x...) (1)
-#define kbd_leds(x...) do { } while (0)
-#define kbd_init_hw(x...) do { } while (0)
-#define kbd_enable_irq(x...) do { } while (0)
-#define kbd_disable_irq(x...) do { } while (0)
-
-#elif 0 //defined(CONFIG_SA1111) /*@@@@@*/
-
-#define KEYBOARD_IRQ TPRXINT
-#define DISABLE_KBD_DURING_INTERRUPTS 0
+#define kbd_sysrq_xlate (1)
-/* redefine some macros */
-#ifdef KBD_DATA_REG
-#undef KBD_DATA_REG
#endif
-#ifdef KBD_STATUS_REG
-#undef KBD_STATUS_REG
-#endif
-#ifdef KBD_CNTL_REG
-#undef KBD_CNTL_REG
-#endif
-#define KBD_DATA_REG KBDDATA
-#define KBD_STATUS_REG KBDSTAT
-#define KBD_CNTL_REG KBDCR
-
-extern int sa1111_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int sa1111_getkeycode(unsigned int scancode);
-extern int sa1111_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char sa1111_unexpected_up(unsigned char keycode);
-extern void sa1111_leds(unsigned char leds);
-extern void sa1111_init_hw(void);
-extern unsigned char sa1111_sysrq_xlate[128];
-
-#define kbd_setkeycode sa1111_setkeycode
-#define kbd_getkeycode sa1111_getkeycode
-#define kbd_translate sa1111_translate
-#define kbd_unexpected_up sa1111_unexpected_up
-#define kbd_leds sa1111_leds
-#define kbd_init_hw sa1111_init_hw
-#define kbd_sysrq_xlate sa1111_sysrq_xlate
-#define kbd_disable_irq(x...) do{;}while(0)
-#define kbd_enable_irq(x...) do{;}while(0)
-
-#define SYSRQ_KEY 0x54
-
-/* resource allocation */
-#define kbd_request_region()
-#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
- "keyboard", NULL)
-
-/* How to access the keyboard macros on this platform. */
-#define kbd_read_input() (*KBDDATA & 0x00ff)
-#define kbd_read_status() (*KBDSTAT & 0x01ff)
-#define kbd_write_output(val) (*KBDDATA = (val))
-#define kbd_write_command(val) (*KBDCR = (val))
-
-/* Some stoneage hardware needs delays after some operations. */
-#define kbd_pause() do {;} while(0)
-
-/* bit definitions for some registers */
-#define KBD_CR_ENA (1<<3)
-
-#define KBD_STAT_RXB (1<<4)
-#define KBD_STAT_RXF (1<<5)
-#define KBD_STAT_TXB (1<<6)
-#define KBD_STAT_TXE (1<<7)
-#define KBD_STAT_STP (1<<8)
-
-/*
- * Machine specific bits for the PS/2 driver
- */
-
-#define AUX_IRQ MSRXINT
-
-#define aux_request_irq(hand, dev_id) \
- request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
-#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
-
-/* How to access the mouse macros on this platform. */
-#define mse_read_input() (*MSEDATA & 0x00ff)
-#define mse_read_status() (*MSESTAT & 0x01ff)
-#define mse_write_output(val) (*MSEDATA = (val))
-#define mse_write_command(val) (*MSECR = (val))
-
-/* bit definitions for some registers */
-#define MSE_CR_ENA (1<<3)
-
-#define MSE_STAT_RXB (1<<4)
-#define MSE_STAT_RXF (1<<5)
-#define MSE_STAT_TXB (1<<6)
-#define MSE_STAT_TXE (1<<7)
-#define MSE_STAT_STP (1<<8)
-
-
-#else
-
-/* dummy i.e. no real keyboard */
-#define kbd_setkeycode(x...) (-ENOSYS)
-#define kbd_getkeycode(x...) (-ENOSYS)
-#define kbd_translate(x...) (0)
-#define kbd_unexpected_up(x...) (1)
-#define kbd_leds(x...) do {;} while (0)
-#define kbd_init_hw(x...) do {;} while (0)
-#define kbd_enable_irq(x...) do {;} while (0)
-#define kbd_disable_irq(x...) do {;} while (0)
-
-#endif
-
-
-/* needed if MAGIC_SYSRQ is enabled for serial console */
-#ifndef SYSRQ_KEY
-#define SYSRQ_KEY ((unsigned char)(-1))
-#define kbd_sysrq_xlate ((unsigned char *)NULL)
-#endif
-
#endif /* _SA1100_KEYBOARD_H */
#error "include <asm/hardware.h> instead"
#endif
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* GPIOs for which the generic definition doesn't say much */
#define GPIO_CF_BUS_ON GPIO_GPIO (3)
#define IRQ_GPIO_CF_IRQ IRQ_GPIO21
#define IRQ_GPIO_CF_CD IRQ_GPIO22
+
+#else
+/*
+ * These definitions are for PCMCIA/IDE card
+ *
+ * PSKTSEL = 0 ---> PCMCIA
+ * PCMCIA_RESET = GPIO_7 ( output )( 0: normal 1: reset )
+ * PCMCIA_IRQ = GPIO_24 ( input )
+ * PCMCIA_CD = GPIO_25 ( input )
+ *
+ * PSKTSEL = 1 ---> IDE port
+ * IDE_IRQ = GPIO_23 ( input )
+ *
+ * !!WARNING!!
+ * When the PCMCIA/IDE card is inserted, the CF slot
+ * should not have any card inserted!!
+ *
+ */
+
+#define GPIO_PCMCIA_RESET GPIO_GPIO (7)
+#define GPIO_PCMCIA_IRQ GPIO_GPIO (24)
+#define GPIO_PCMCIA_CD GPIO_GPIO (25)
+#define GPIO_IDE_IRQ GPIO_GPIO (8)
+
+#define IRQ_PCMCIA_IRQ IRQ_GPIO24
+#define IRQ_PCMCIA_CD IRQ_GPIO25
+#define IRQ_IDE_IRQ IRQ_GPIO8
+
+#endif
+
+/*
+ * On board LAN chip
+ */
+#define PANGOLIN_LAN_ADDR 0x32000000
+#define PANGOLIN_LAN_RESET GPIO_GPIO (8)
+#define PANGOLIN_LAN_IRQ GPIO_GPIO (26)
+#define PANGOLIN_IRQ_LAN_IRQ IRQ_GPIO26
+
*
* (C) 1999 Nicolas Pitre <nico@cam.org>
*
- * Reorganised to use machine_is_*() macros.
+ * Reorganised to be machine independent.
*/
#include "hardware.h"
-#include <asm/mach-types.h>
-
-/* Assabet's Status Control "Register" */
-unsigned long SCR_value;
-
-/* sa1100_setup() will perform any special initialization for UART, etc. */
-extern void sa1100_setup( int arch_id );
-#define arch_decomp_setup() sa1100_setup(arch_id)
-
/*
* The following code assumes the serial port has already been
- * initialized by the bootloader or such...
+ * initialized by the bootloader. We search for the first enabled
+ * port in the most probable order. If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
*/
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
{
unsigned long serial_port;
- if (machine_is_assabet()) {
- if( machine_has_neponset() )
- serial_port = _Ser3UTCR0;
- else
- serial_port = _Ser1UTCR0;
- } else if (machine_is_brutus()||machine_is_nanoengine() ||
- machine_is_pangolin() || machine_is_freebird() ||
- machine_is_pfs168() || machine_is_flexanet())
- serial_port = _Ser1UTCR0;
- else if (machine_is_empeg() || machine_is_bitsy() ||
- machine_is_victor() || machine_is_lart() ||
- machine_is_sherman() || machine_is_yopy() ||
- machine_is_huw_webpanel() || machine_is_itsy() )
+ do {
serial_port = _Ser3UTCR0;
- else
+ if (UART(UTCR3) & UTCR3_TXE) break;
+ serial_port = _Ser1UTCR0;
+ if (UART(UTCR3) & UTCR3_TXE) break;
+ serial_port = _Ser2UTCR0;
+ if (UART(UTCR3) & UTCR3_TXE) break;
return;
+ } while (0);
for (; *s; s++) {
/* wait for space in the UART's transmiter */
/*
* Nothing to do for these
*/
+#define arch_decomp_setup()
#define arch_decomp_wdog()
#error SMP not supported
#endif
-#ifdef CONFIG_ARCH_CO285
typedef struct { volatile int counter; } atomic_t;
-#else
-typedef struct { int counter; } atomic_t;
-#endif
#define ATOMIC_INIT(i) { (i) }
*/
#ifndef __ASSEMBLY__
+#include <asm/memory.h>
#include <asm/page.h>
/* forward-declare task_struct */
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
+#define cpu_get_pgd() \
+ ({ \
+ unsigned long pg; \
+ __asm__("mrc p15, 0, %0, c2, c0, 0" \
+ : "=r" (pg)); \
+ pg &= ~0x3fff; \
+ (pgd_t *)phys_to_virt(pg); \
+ })
+
#endif
#ifndef __ASSEMBLY__
+#include <asm/memory.h>
#include <asm/page.h>
/* forward declare task_struct */
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
+#define cpu_get_pgd() \
+ ({ \
+ unsigned long pg; \
+ __asm__("mrc p15, 0, %0, c2, c0, 0" \
+ : "=r" (pg)); \
+ pg &= ~0x3fff; \
+ (pgd_t *)phys_to_virt(pg); \
+ })
+
#endif
#define __ASM_HARDIRQ_H
#include <linux/config.h>
+#include <linux/cache.h>
#include <linux/threads.h>
/* softirq.h is sensitive to the offsets of these fields */
/* PCI_CFG bits
*/
+#define V3_PCI_CFG_M_I2O_EN (1 << 15)
+#define V3_PCI_CFG_M_IO_REG_DIS (1 << 14)
+#define V3_PCI_CFG_M_IO_DIS (1 << 13)
+#define V3_PCI_CFG_M_EN3V (1 << 12)
#define V3_PCI_CFG_M_RETRY_EN (1 << 10)
#define V3_PCI_CFG_M_AD_LOW1 (1 << 9)
#define V3_PCI_CFG_M_AD_LOW0 (1 << 8)
#include <asm/arch/io.h>
/*
- * IO definitions. We define {out,in,outs,ins}[bwl] if __io is
- * defined by the machine. Otherwise, these definitions are left
- * for the machine specific header files to pick up.
+ * IO definitions. We define {out,in,outs,ins}[bwl] if __io is defined
+ * by the machine. Otherwise, these definitions are left for the machine
+ * specific header files to pick up.
+ *
+ * Note that we prevent GCC re-ordering or caching values in expressions
+ * by introducing sequence points into the in*() definitions. Note that
+ * __raw_* do not guarantee this behaviour.
*/
#ifdef __io
#define outb(v,p) __raw_writeb(v,__io(p))
#define outw(v,p) __raw_writew(v,__io(p))
#define outl(v,p) __raw_writel(v,__io(p))
-#define inb(p) __raw_readb(__io(p))
-#define inw(p) __raw_readw(__io(p))
-#define inl(p) __raw_readl(__io(p))
+#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
+#define inw(p) ({ unsigned int __v = __raw_readw(__io(p)); __v; })
+#define inl(p) ({ unsigned int __v = __raw_readl(__io(p)); __v; })
#define outsb(p,d,l) __raw_writesb(__io(p),d,l)
#define outsw(p,d,l) __raw_writesw(__io(p),d,l)
*/
#ifdef __mem_pci
-#define readb(addr) __raw_readb(__mem_pci(addr))
-#define readw(addr) __raw_readw(__mem_pci(addr))
-#define readl(addr) __raw_readl(__mem_pci(addr))
+#define readb(addr) ({ unsigned int __v = __raw_readb(__mem_pci(addr)); __v; })
+#define readw(addr) ({ unsigned int __v = __raw_readw(__mem_pci(addr)); __v; })
+#define readl(addr) ({ unsigned int __v = __raw_readl(__mem_pci(addr)); __v; })
+
#define writeb(val,addr) __raw_writeb(val,__mem_pci(addr))
#define writew(val,addr) __raw_writew(val,__mem_pci(addr))
#define writel(val,addr) __raw_writel(val,__mem_pci(addr))
unsigned int nr; /* architecture number */
unsigned int phys_ram; /* start of physical ram */
unsigned int phys_io; /* start of physical io */
- unsigned int virt_io; /* start of virtual io */
+ unsigned int io_pg_offst; /* byte offset for io
+ * page tabe entry */
const char *name; /* architecture name */
unsigned int param_offset; /* parameter page */
#define MAINTAINER(n)
#define BOOT_MEM(_pram,_pio,_vio) \
- phys_ram: _pram, \
- phys_io: _pio, \
- virt_io: _vio,
+ phys_ram: _pram, \
+ phys_io: _pio, \
+ io_pg_offst: ((_vio)>>18)&0xfffc,
#define BOOT_PARAMS(_params) \
param_offset: _params,
#ifndef HZ
#define HZ 100
#endif
+#if defined(__KERNEL__) && (HZ == 100)
+#define hz_to_std(a) (a)
+#endif
#ifndef NGROUPS
#define NGROUPS 32
consistent_free(vaddr, size, dma_handle);
}
-#if !defined(CONFIG_SA1111)
/* Map a single buffer of the indicated size for DMA in streaming mode.
* The 32-bit bus address to use is returned.
*
static inline dma_addr_t
pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
{
+#ifdef CONFIG_SA1111
+ extern dma_addr_t sa1111_map_single(struct pci_dev *, void *, size_t, int);
+
+ /*
+ * for SA1111 these functions are "magic" and relocate buffers. We
+ * only need to do these if hwdev is non-null; otherwise we expect
+ * the buffer to already be suitable for DMA.
+ */
+ if (hwdev != NULL)
+ return sa1111_map_single(hwdev, ptr, size, direction);
+#endif
consistent_sync(ptr, size, direction);
return virt_to_bus(ptr);
}
static inline void
pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction)
{
+#ifdef CONFIG_SA1111
+ extern void sa1111_unmap_single(struct pci_dev *, dma_addr_t, size_t, int);
+
+ if (hwdev != NULL)
+ sa1111_unmap_single(hwdev, dma_addr, size, direction);
+#endif
/* nothing to do */
}
-#else
-/* for SA1111 these functions are "magic" and relocate buffers */
-extern dma_addr_t pci_map_single(struct pci_dev *hwdev,
- void *ptr, size_t size, int direction);
-extern void pci_unmap_single(struct pci_dev *hwdev,
- dma_addr_t dma_addr,
- size_t size, int direction);
-#endif
/* Map a set of buffers described by scatterlist in streaming
* mode for DMA. This is the scather-gather version of the
#include <asm-generic/pgtable.h>
+extern void pgtable_cache_init(void);
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMARM_PGTABLE_H */
EXTRA_THREAD_STRUCT
};
+#define INIT_MMAP { \
+ vm_mm: &init_mm, \
+ vm_page_prot: PAGE_SHARED, \
+ vm_flags: VM_READ | VM_WRITE | VM_EXEC, \
+ vm_avl_height: 1, \
+}
+
#define INIT_THREAD { \
refcount: ATOMIC_INIT(1), \
EXTRA_THREAD_STRUCT_INIT \
struct tag_ramdisk {
u32 flags; /* bit 0 = load, bit 1 = prompt */
- u32 size; /* decompressed ramdisk size */
+ u32 size; /* decompressed ramdisk size in _kilo_ bytes */
u32 start; /* starting block of floppy-based RAM disk image */
};
struct tag_initrd {
u32 start; /* physical start address */
- u32 size; /* size of compressed ramdisk image */
+ u32 size; /* size of compressed ramdisk image in bytes */
};
/* board serial number. "64 bits should be enough for everybody" */
/*
* SA_FLAGS values:
*
- * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
- * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_SIGINFO deliver the signal with SIGINFO structs
+ * SA_THIRTYTWO delivers the signal in 32-bit mode, even if the task
+ * is running in 26-bit.
+ * SA_ONSTACK allows alternate signal stacks (see sigaltstack(2)).
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ * SA_RESETHAND clears the handler when the signal is delivered.
*
* SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
* Unix names RESETHAND and NODEFER respectively.
#define SA_NOCLDSTOP 0x00000001
#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
#define SA_SIGINFO 0x00000004
+#define SA_THIRTYTWO 0x02000000
+#define SA_RESTORER 0x04000000
#define SA_ONSTACK 0x08000000
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_ONESHOT SA_RESETHAND
#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
-#define SA_RESTORER 0x04000000
-#define SA_THIRTYTWO 0x02000000 /* deliver signal in 32-bit mode even if
- task is running 26 bits. */
/*
* sigaltstack controls
* error occurs, and leave it unchanged on success. Note that these
* versions are void (ie, don't return a value as such).
*/
-#define get_user(x,p) __get_user_check((x),(p),sizeof(*(p)))
+
+extern int __get_user_1(void *);
+extern int __get_user_2(void *);
+extern int __get_user_4(void *);
+extern int __get_user_8(void *);
+extern int __get_user_bad(void);
+
+#define __get_user_x(__r1,__p,__e,__s,__i...) \
+ __asm__ __volatile__ ("bl __get_user_" #__s \
+ : "=&r" (__e), "=r" (__r1) \
+ : "0" (__p) \
+ : __i)
+
+#define get_user(x,p) \
+ ({ \
+ const register typeof(*(p)) *__p asm("r0") = (p); \
+ register typeof(*(p)) __r1 asm("r1"); \
+ register int __e asm("r0"); \
+ switch (sizeof(*(p))) { \
+ case 1: \
+ __get_user_x(__r1, __p, __e, 1, "lr"); \
+ break; \
+ case 2: \
+ __get_user_x(__r1, __p, __e, 2, "r2", "lr"); \
+ break; \
+ case 4: \
+ __get_user_x(__r1, __p, __e, 4, "lr"); \
+ break; \
+ case 8: \
+ __get_user_x(__r1, __p, __e, 8, "lr"); \
+ break; \
+ default: __e = __get_user_bad(); break; \
+ } \
+ x = __r1; \
+ __e; \
+ })
+
#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p)))
#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
-#define put_user(x,p) __put_user_check((__typeof(*(p)))(x),(p),sizeof(*(p)))
+extern int __put_user_1(void *, unsigned int);
+extern int __put_user_2(void *, unsigned int);
+extern int __put_user_4(void *, unsigned int);
+extern int __put_user_8(void *, unsigned long long);
+extern int __put_user_bad(void);
+
+#define __put_user_x(__r1,__p,__e,__s,__i...) \
+ __asm__ __volatile__ ("bl __put_user_" #__s \
+ : "=&r" (__e) \
+ : "0" (__p), "r" (__r1) \
+ : __i)
+
+#define put_user(x,p) \
+ ({ \
+ const register typeof(*(p)) *__p asm("r0") = (p); \
+ const register typeof(*(p)) __r1 asm("r1") = (x); \
+ register int __e asm("r0"); \
+ switch (sizeof(*(p))) { \
+ case 1: \
+ __put_user_x(__r1, __p, __e, 1, "r2", "lr"); \
+ break; \
+ case 2: \
+ __put_user_x(__r1, __p, __e, 2, "r2", "lr"); \
+ break; \
+ case 4: \
+ __put_user_x(__r1, __p, __e, 4, "r2", "lr"); \
+ break; \
+ case 8: \
+ __put_user_x(__r1, __p, __e, 8, "ip", "lr"); \
+ break; \
+ default: __e = __put_user_bad(); break; \
+ } \
+ __e; \
+ })
+
#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
/*
* These are the work horses of the get/put_user functions
*/
+#if 0
#define __get_user_check(x,ptr,size) \
({ \
long __gu_err = -EFAULT, __gu_val = 0; \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
+#endif
#define __get_user_nocheck(x,ptr,size) \
({ \
(void) 0; \
})
-extern long __get_user_bad(void);
-
#define __get_user_size(x,ptr,size,retval) \
do { \
switch (size) { \
} \
} while (0)
-extern long __put_user_bad(void);
-
#define __put_user_size(x,ptr,size,retval) \
do { \
switch (size) { \
* I expect future Intel CPU's to have a weaker ordering,
* but I'd also expect them to finally get their act together
* and add some real memory barriers if so.
+ *
+ * Some non intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
*/
+
#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
#define rmb() mb()
+
+#ifdef CONFIG_X86_OOSTORE
+#define wmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#else
#define wmb() __asm__ __volatile__ ("": : :"memory")
+#endif
#ifdef CONFIG_SMP
#define smp_mb() mb()
* not operational the previous status is sent in the prevstatus variable.
* This can be used in cases when the default handling isn't quite adequete
* e.g. if a ssch is needed to reinitialize long running channel programs.
+ *
+ * This returns the number of devices found or -ENOMEM if the code didn't
+ * have enough memory to allocate the chandev control block
+ * or -EPERM if a duplicate entry is found.
*/
int chandev_register_and_probe(chandev_probefunc probefunc,
chandev_shutdownfunc shutdownfunc,
{
struct task_struct *current;
__asm__("lhi %0,-8192\n\t"
- "nr %0,15"
+ "al %0,0xc40"
: "=&r" (current) : : "cc" );
return current;
}
unsigned int dasd_io_time2[32]; /* histogram of time from start to irq */
unsigned int dasd_io_time2ps[32]; /* histogram of time from start to irq */
unsigned int dasd_io_time3[32]; /* histogram of time from irq to end */
+ unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */
} dasd_profile_info_t;
/*
#define DEBUG_MAX_LEVEL 6 /* debug levels range from 0 to 6 */
#define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */
+#define DEBUG_FLUSH_ALL -1 /* parameter to flush all areas */
#define DEBUG_MAX_VIEWS 10 /* max number of views in proc fs */
#define DEBUG_MAX_PROCF_LEN 16 /* max length for a proc file name */
#define DEBUG_DEFAULT_LEVEL 3 /* initial debug level */
#define __S390_GDB_STUB__
#include <linux/config.h>
#if CONFIG_REMOTE_DEBUG
-#include <asm/s390-gdbregs.h>
#include <asm/ptrace.h>
extern int gdb_stub_initialised;
-extern void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval);
+extern void gdb_stub_handle_exception(struct gdb_pt_regs *regs,int sigval);
+struct net_device;
+struct net_device *gdb_dev;
+void gdb_do_timers(void);
+extern int putDebugChar(char c); /* write a single character */
+extern char getDebugChar(void); /* read and return a single char */
#endif
#endif
#define __LC_SAVE_AREA 0xC00
#define __LC_KERNEL_STACK 0xC40
-#define __LC_KERNEL_LEVEL 0xC44
+#define __LC_ASYNC_STACK 0xC44
#define __LC_CPUID 0xC60
#define __LC_CPUADDR 0xC68
#define __LC_IPLDEV 0xC7C
#include <asm/atomic.h>
#include <asm/sigp.h>
+void restart_int_handler(void);
+void ext_int_handler(void);
+void system_call(void);
+void pgm_check_handler(void);
+void mcck_int_handler(void);
+void io_int_handler(void);
struct _lowcore
{
__u16 cpu_addr; /* 0x084 */
__u16 ext_int_code; /* 0x086 */
__u16 svc_ilc; /* 0x088 */
- __u16 scv_code; /* 0x08a */
+ __u16 svc_code; /* 0x08a */
__u16 pgm_ilc; /* 0x08c */
__u16 pgm_code; /* 0x08e */
__u32 trans_exc_code; /* 0x090 */
/* System info area */
__u32 save_area[16]; /* 0xc00 */
__u32 kernel_stack; /* 0xc40 */
- __u32 kernel_level; /* 0xc44 */
+ __u32 async_stack; /* 0xc44 */
/* entry.S sensitive area start */
__u8 pad10[0xc60-0xc48]; /* 0xc5c */
struct cpuinfo_S390 cpu_data; /* 0xc60 */
/* SMP info area: defined by DJB */
__u64 jiffy_timer_cc; /* 0xc80 */
atomic_t ext_call_fast; /* 0xc88 */
- atomic_t ext_call_queue; /* 0xc8c */
- atomic_t ext_call_count; /* 0xc90 */
- __u8 pad11[0xe00-0xc94]; /* 0xc94 */
+ __u8 pad11[0xe00-0xc8c]; /* 0xc8c */
/* 0xe00 is used as indicator for dump tools */
/* whether the kernel died with panic() or not */
#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(x) do { } while (0)
+#define pmd_free_slow(x) do { } while (0)
+#define pmd_free_fast(x) do { } while (0)
#define pgd_populate(mm, pmd, pte) BUG()
extern inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
#endif /* !__ASSEMBLY__ */
-/*
- * Certain architectures need to do special things when PTEs
- * within a page table are directly modified. Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-
/*
* PMD_SHIFT determines the size of the area a second-level page
* table can map
/* Bits in the page table entry */
#define _PAGE_PRESENT 0x001 /* Software */
+#define _PAGE_MKCLEAR 0x002 /* Software */
#define _PAGE_RO 0x200 /* HW read-only */
#define _PAGE_INVALID 0x400 /* HW invalid */
#define __S110 PAGE_SHARED
#define __S111 PAGE_SHARED
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
+ */
+extern inline void set_pte(pte_t *pteptr, pte_t pteval)
+{
+ if ((pte_val(pteval) & (_PAGE_MKCLEAR|_PAGE_INVALID))
+ == _PAGE_MKCLEAR)
+ {
+ pte_val(pteval) &= ~_PAGE_MKCLEAR;
+
+ asm volatile ("sske %0,%1"
+ : : "d" (0), "a" (pte_val(pteval)));
+ }
+
+ *pteptr = pteval;
+}
+
/*
* Permanent address of a page.
*/
extern inline pte_t pte_mkclean(pte_t pte)
{
- /* We can't clear the changed bit atomically. The iske/and/sske
- * sequence has a race condition with the page referenced bit.
- * At the moment pte_mkclean is always followed by a pte_mkold.
- * So its safe to ignore the problem for now. Hope this will
- * never change ... */
- asm volatile ("sske %0,%1"
- : : "d" (0), "a" (pte_val(pte)));
+ /* The only user of pte_mkclean is the fork() code.
+ We must *not* clear the *physical* page dirty bit
+ just because fork() wants to clear the dirty bit in
+ *one* of the page's mappings. So we just do nothing. */
return pte;
}
extern inline pte_t pte_mkdirty(pte_t pte)
{
- /* We can't set the changed bit atomically either. For now we
+ /* We can't set the changed bit atomically. For now we
* set (!) the page referenced bit. */
asm volatile ("sske %0,%1"
: : "d" (_PAGE_CHANGED|_PAGE_REFERENCED),
"a" (pte_val(pte)));
+
+ pte_val(pte) &= ~_PAGE_MKCLEAR;
return pte;
}
pte_val(__pte) = physpage + pgprot_val(pgprot);
return __pte;
}
-#define mk_pte(page,pgprot) mk_pte_phys(__pa(((page)-mem_map)<<PAGE_SHIFT),pgprot)
+
+#define mk_pte(pg, pgprot) \
+({ \
+ struct page *__page = (pg); \
+ unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT); \
+ pte_t __pte = mk_pte_phys(__physpage, (pgprot)); \
+ \
+ if (__page != ZERO_PAGE(__physpage)) { \
+ int __users = page_count(__page); \
+ __users -= !!__page->buffers + !!__page->mapping; \
+ \
+ if (__users == 1) \
+ pte_val(__pte) |= _PAGE_MKCLEAR; \
+ } \
+ \
+ __pte; \
+})
#define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
#define PageSkip(page) (0)
#define kern_addr_valid(addr) (1)
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init() do { } while (0)
+
#endif /* _S390_PAGE_H */
__u32 trap;
__u32 crs[16];
s390_fp_regs fp_regs;
+ __u32 old_ilc;
};
#endif
ec_restart,
ec_halt,
ec_power_off,
- ec_ptlb,
+ ec_call_function,
ec_bit_last
} ec_bit_sig;
-/* Signals which come with a parameter area, synchronous */
-typedef enum
-{
- ec_callback_async,
- ec_callback_sync
-} ec_cmd_sig;
-
-/* state information for synchronous signals */
-typedef enum
-{
- ec_pending,
- ec_executing,
- ec_done
-} ec_state;
-
-/* header for the queuing of signals with a parameter area */
-typedef struct ec_ext_call
-{
- ec_cmd_sig cmd;
- atomic_t status;
- struct ec_ext_call *next;
- void (*func)(void *info);
- void *info;
-} ec_ext_call;
-
/*
* Signal processor
*/
__u16 cpu;
} sigp_info;
+extern unsigned long cpu_online_map;
+
#define NO_PROC_ID 0xFF /* No processor magic marker */
/*
void smp_local_timer_interrupt(struct pt_regs * regs);
-sigp_ccode smp_ext_call(int cpu, void (*cb)(void *info), void *info, int wait);
-void smp_ext_call_others(void (*cb)(void *info), void *info, int wait);
-sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig);
-void smp_ext_bitcall_others(ec_bit_sig sig);
-
-int smp_signal_others(sigp_order_code order_code,__u32 parameter,
- int spin,sigp_info *info);
#endif
#endif
#include <asm/lowcore.h>
#define __cpu_bh_enable(cpu) \
- do { barrier(); local_bh_count(cpu)--; } while (0)
+ do { barrier(); local_bh_count(cpu)--; } while (0)
#define cpu_bh_disable(cpu) \
- do { local_bh_count(cpu)++; barrier(); } while (0)
+ do { local_bh_count(cpu)++; barrier(); } while (0)
#define local_bh_disable() cpu_bh_disable(smp_processor_id())
#define __local_bh_enable() __cpu_bh_enable(smp_processor_id())
#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
+extern void do_call_softirq(void);
+
#define local_bh_enable() \
do { \
- unsigned int *ptr = &local_bh_count(smp_processor_id()); \
- barrier(); \
- if (!--*ptr) \
+ unsigned int *ptr = &local_bh_count(smp_processor_id()); \
+ barrier(); \
+ if (!--*ptr) \
if (softirq_pending(smp_processor_id())) \
- do_softirq(); \
+ /* Use the async. stack for softirq */ \
+ do_call_softirq(); \
} while (0)
#endif /* __ASM_SOFTIRQ_H */
__asm__ __volatile(" bras 1,1f\n"
"0: diag 0,0,68\n"
"1: slr 0,0\n"
- " cs 0,1,%1\n"
+ " cs 0,1,0(%0)\n"
" jl 0b\n"
- : "=m" (lp->lock)
- : "0" (lp->lock) : "0", "1", "cc" );
+ : : "a" (&lp->lock) : "0", "1", "cc", "memory" );
}
extern inline int spin_trylock(spinlock_t *lp)
{
unsigned long result;
- __asm__ __volatile(" slr %1,%1\n"
+ __asm__ __volatile(" slr %0,%0\n"
" basr 1,0\n"
- "0: cs %1,1,%0"
- : "=m" (lp->lock), "=&d" (result)
- : "0" (lp->lock) : "1", "cc" );
+ "0: cs %0,1,0(%1)"
+ : "=&d" (result)
+ : "a" (&lp->lock) : "1", "cc", "memory" );
return !result;
}
{
__asm__ __volatile(" xc 0(4,%0),0(%0)\n"
" bcr 15,0"
- : /* no output */ : "a" (lp) : "memory", "cc" );
+ : : "a" (&lp->lock) : "memory", "cc" );
}
/*
#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
#define read_lock(rw) \
- asm volatile(" l 2,%0\n" \
+ asm volatile(" l 2,0(%0)\n" \
" j 1f\n" \
"0: diag 0,0,68\n" \
- "1: la 2,0(2)\n" /* clear high (=write) bit */ \
- " la 3,1(2)\n" /* one more reader */ \
- " cs 2,3,%0\n" /* try to write new value */ \
+ "1: la 2,0(2)\n" /* clear high (=write) bit */ \
+ " la 3,1(2)\n" /* one more reader */ \
+ " cs 2,3,0(%0)\n" /* try to write new value */ \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#define read_unlock(rw) \
- asm volatile(" l 2,%0\n" \
+ asm volatile(" l 2,0(%0)\n" \
" j 1f\n" \
"0: diag 0,0,68\n" \
"1: lr 3,2\n" \
" ahi 3,-1\n" /* one less reader */ \
- " cs 2,3,%0\n" \
+ " cs 2,3,0(%0)\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#define write_lock(rw) \
asm volatile(" lhi 3,1\n" \
" j 1f\n" \
"0: diag 0,0,68\n" \
"1: slr 2,2\n" /* old lock value must be 0 */ \
- " cs 2,3,%0\n" \
+ " cs 2,3,0(%0)\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#define write_unlock(rw) \
asm volatile(" slr 3,3\n" /* new lock value = 0 */ \
"0: diag 0,0,68\n" \
"1: lhi 2,1\n" \
" sll 2,31\n" /* old lock value must be 0x80000000 */ \
- " cs 2,3,%0\n" \
+ " cs 2,3,0(%0)\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#endif /* __ASM_SPINLOCK_H */
* use the right size if we just have the right pointer type.
*/
+extern inline int __put_user_asm_8(__u64 x, void *ptr)
+{
+ int err;
+
+ __asm__ __volatile__ ( " sr %1,%1\n"
+ " la 2,%2\n"
+ " la 4,%0\n"
+ " sacf 512\n"
+ "0: mvc 0(8,4),0(2)\n"
+ " sacf 0\n"
+ "1:\n"
+ ".section .fixup,\"ax\"\n"
+ "2: sacf 0\n"
+ " lhi %1,%h3\n"
+ " bras 4,3f\n"
+ " .long 1b\n"
+ "3: l 4,0(4)\n"
+ " br 4\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,2b\n"
+ ".previous"
+ : "=m" (*((__u32*) ptr)), "=&d" (err)
+ : "m" (x), "K" (-EFAULT)
+ : "cc", "2", "4" );
+ return err;
+}
+
extern inline int __put_user_asm_4(__u32 x, void *ptr)
{
int err;
case 4: \
__pu_err = __put_user_asm_4((__u32) x,(ptr));\
break; \
+ case 8: \
+ __pu_err = __put_user_asm_8((__u64) x,(ptr));\
+ break; \
default: \
__pu_err = __put_user_bad(); \
break; \
extern int __put_user_bad(void);
+#define __get_user_asm_8(x, ptr, err) \
+({ \
+ __asm__ __volatile__ ( " sr %1,%1\n" \
+ " la 2,%0\n" \
+ " la 4,%2\n" \
+ " sacf 512\n" \
+ "0: mvc 0(8,2),0(4)\n" \
+ " sacf 0\n" \
+ "1:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "2: sacf 0\n" \
+ " lhi %1,%h3\n" \
+ " bras 4,3f\n" \
+ " .long 1b\n" \
+ "3: l 4,0(4)\n" \
+ " br 4\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 0b,2b\n" \
+ ".previous" \
+ : "=m" (x) , "=&d" (err) \
+ : "m" (*(const __u64*)(ptr)),"K" (-EFAULT) \
+ : "cc", "2", "4" ); \
+})
#define __get_user_asm_4(x, ptr, err) \
({ \
case 4: \
__get_user_asm_4(x,ptr,__gu_err); \
break; \
+ case 8: \
+ __get_user_asm_8(x,ptr,__gu_err); \
+ break; \
default: \
(x) = 0; \
__gu_err = __get_user_bad(); \
"0: mvcle 2,4,0\n"
" jo 0b\n"
" sacf 0\n"
- " lr %0,3\n"
+ " lr %0,5\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,__copy_from_user_fixup\n"
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
+ _sigregs uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
- struct sigcontext *sc; /* Added for pthread support */
};
-
-
#endif /* !_ASM_S390_UCONTEXT_H */
#define __NR_capset 185
#define __NR_sigaltstack 186
#define __NR_sendfile 187
+#define __NR_getpmsg 188
+#define __NR_putpmsg 189
#define __NR_vfork 190
#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
#define __NR_mmap2 192
#define VTOC_ERROR "VTOC error:"
-enum failure {unable_to_open,
- unable_to_seek,
- unable_to_write,
- unable_to_read};
-
-unsigned char ASCtoEBC[256] =
-{
- /*00 NL SH SX EX ET NQ AK BL */
- 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
- /*08 BS HT LF VT FF CR SO SI */
- 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- /*10 DL D1 D2 D3 D4 NK SN EB */
- 0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26,
- /*18 CN EM SB EC FS GS RS US */
- 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
- /*20 SP ! " # $ % & ' */
- 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
- /*28 ( ) * + , - . / */
- 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
- /*30 0 1 2 3 4 5 6 7 */
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
- /*38 8 9 : ; < = > ? */
- 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
- /*40 @ A B C D E F G */
- 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
- /*48 H I J K L M N O */
- 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
- /*50 P Q R S T U V W */
- 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
- /*58 X Y Z [ \ ] ^ _ */
- 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
- /*60 ` a b c d e f g */
- 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- /*68 h i j k l m n o */
- 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
- /*70 p q r s t u v w */
- 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
- /*78 x y z { | } ~ DL */
- 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
-};
-
-
-unsigned char EBCtoASC[256] =
-{
- /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
- 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
- /* 0x08 -GE -SPS -RPT VT FF CR SO SI */
- 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- /* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC
- -ENP ->LF */
- 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
- /* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB
- -IUS */
- 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- /* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC
- -INP */
- 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
- /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL
- -SW */
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
- /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */
- 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
- /* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */
- 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
- /* 0x40 SP RSP ä ---- */
- 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
- /* 0x48 . < ( + | */
- 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
- /* 0x50 & ---- */
- 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
- /* 0x58 ß ! $ * ) ; */
- 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
- /* 0x60 - / ---- Ä ---- ---- ---- */
- 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
- /* 0x68 ---- , % _ > ? */
- 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
- /* 0x70 ---- ---- ---- ---- ---- ---- ---- */
- 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- /* 0x78 * ` : # @ ' = " */
- 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
- /* 0x80 * a b c d e f g */
- 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- /* 0x88 h i ---- ---- ---- */
- 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
- /* 0x90 ° j k l m n o p */
- 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
- /* 0x98 q r ---- ---- */
- 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
- /* 0xA0 ~ s t u v w x */
- 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- /* 0xA8 y z ---- ---- ---- ---- */
- 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
- /* 0xB0 ^ ---- § ---- */
- 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
- /* 0xB8 ---- [ ] ---- ---- ---- ---- */
- 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
- /* 0xC0 { A B C D E F G */
- 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- /* 0xC8 H I ---- ö ---- */
- 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
- /* 0xD0 } J K L M N O P */
- 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
- /* 0xD8 Q R ---- ü */
- 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
- /* 0xE0 \ S T U V W X */
- 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- /* 0xE8 Y Z ---- Ö ---- ---- ---- */
- 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
- /* 0xF0 0 1 2 3 4 5 6 7 */
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- /* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */
- 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
-};
typedef struct ttr
{
* not operational the previous status is sent in the prevstatus variable.
* This can be used in cases when the default handling isn't quite adequete
* e.g. if a ssch is needed to reinitialize long running channel programs.
+ *
+ * This returns the number of devices found or -ENOMEM if the code didn't
+ * have enough memory to allocate the chandev control block
+ * or -EPERM if a duplicate entry is found.
*/
int chandev_register_and_probe(chandev_probefunc probefunc,
chandev_shutdownfunc shutdownfunc,
{
struct task_struct *current;
__asm__("lghi %0,-16384\n\t"
- "ngr %0,15"
+ "alg %0,0xd40"
: "=&r" (current) : : "cc" );
return current;
}
unsigned int dasd_io_time2[32]; /* histogram of time from start to irq */
unsigned int dasd_io_time2ps[32]; /* histogram of time from start to irq */
unsigned int dasd_io_time3[32]; /* histogram of time from irq to end */
+ unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */
} dasd_profile_info_t;
/*
#define DEBUG_MAX_LEVEL 6 /* debug levels range from 0 to 6 */
#define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */
+#define DEBUG_FLUSH_ALL -1 /* parameter to flush all areas */
#define DEBUG_MAX_VIEWS 10 /* max number of views in proc fs */
#define DEBUG_MAX_PROCF_LEN 16 /* max length for a proc file name */
#define DEBUG_DEFAULT_LEVEL 3 /* initial debug level */
+
/*
* include/asm-s390/lowcore.h
*
#define __LC_SAVE_AREA 0xC00
#define __LC_KERNEL_STACK 0xD40
-#define __LC_KERNEL_LEVEL 0xD48
+#define __LC_ASYNC_STACK 0xD48
#define __LC_CPUID 0xD90
#define __LC_CPUADDR 0xD98
#define __LC_IPLDEV 0xDB8
#include <asm/atomic.h>
#include <asm/sigp.h>
+void restart_int_handler(void);
+void ext_int_handler(void);
+void system_call(void);
+void pgm_check_handler(void);
+void mcck_int_handler(void);
+void io_int_handler(void);
struct _lowcore
{
__u16 cpu_addr; /* 0x084 */
__u16 ext_int_code; /* 0x086 */
__u16 svc_ilc; /* 0x088 */
- __u16 scv_code; /* 0x08a */
+ __u16 svc_code; /* 0x08a */
__u16 pgm_ilc; /* 0x08c */
__u16 pgm_code; /* 0x08e */
__u32 data_exc_code; /* 0x090 */
__u64 save_area[16]; /* 0xc00 */
__u8 pad9[0xd40-0xc80]; /* 0xc80 */
__u64 kernel_stack; /* 0xd40 */
- __u64 kernel_level; /* 0xd48 */
+ __u64 async_stack; /* 0xd48 */
/* entry.S sensitive area start */
__u8 pad10[0xd80-0xd50]; /* 0xd64 */
struct cpuinfo_S390 cpu_data; /* 0xd80 */
/* SMP info area: defined by DJB */
__u64 jiffy_timer_cc; /* 0xdc0 */
__u64 ext_call_fast; /* 0xdc8 */
- __u64 ext_call_queue; /* 0xdd0 */
- __u64 ext_call_count; /* 0xdd8 */
-
- __u8 pad12[0xe00-0xde0]; /* 0xde0 */
+ __u8 pad12[0xe00-0xdd0]; /* 0xdd0 */
/* 0xe00 is used as indicator for dump tools */
/* whether the kernel died with panic() or not */
+++ /dev/null
-/*
- * arch/s390/kernel/mathemu.h
- * IEEE floating point emulation.
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- */
-
-#ifndef __MATHEMU__
-#define __MATHEMU__
-
-extern int math_emu_b3(__u8 *, struct pt_regs *);
-extern int math_emu_ed(__u8 *, struct pt_regs *);
-extern void math_emu_ldr(__u8 *);
-extern void math_emu_ler(__u8 *);
-extern void math_emu_std(__u8 *, struct pt_regs *);
-extern void math_emu_ld(__u8 *, struct pt_regs *);
-extern void math_emu_ste(__u8 *, struct pt_regs *);
-extern void math_emu_le(__u8 *, struct pt_regs *);
-extern int math_emu_lfpc(__u8 *, struct pt_regs *);
-extern int math_emu_stfpc(__u8 *, struct pt_regs *);
-extern int math_emu_srnm(__u8 *, struct pt_regs *);
-
-
-extern __u64 __adddf3(__u64,__u64);
-extern __u64 __subdf3(__u64,__u64);
-extern __u64 __muldf3(__u64,__u64);
-extern __u64 __divdf3(__u64,__u64);
-extern long __cmpdf2(__u64,__u64);
-extern __u64 __negdf2(__u64);
-extern __u64 __absdf2(__u64);
-extern __u32 __addsf3(__u32,__u32);
-extern __u32 __subsf3(__u32,__u32);
-extern __u32 __mulsf3(__u32,__u32);
-extern __u32 __divsf3(__u32,__u32);
-extern __u32 __negsf2(__u32);
-extern __u32 __abssf2(__u32);
-extern long __cmpsf2(__u32,__u32);
-extern __u32 __truncdfsf2(__u64);
-extern __u32 __fixsfsi(__u32);
-extern __u32 __fixdfsi(__u64);
-extern __u64 __floatsidf(__u32);
-extern __u32 __floatsisf(__u32);
-extern __u64 __extendsfdf2(__u32);
-
-#endif /* __MATHEMU__ */
-
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-/*
- *
- *
- */
-
#define __PAGE_OFFSET 0x0UL
#define PAGE_OFFSET 0x0UL
#define __pa(x) (unsigned long)(x)
#ifndef HZ
#define HZ 100
+#ifdef __KERNEL__
+#define hz_to_std(a) (a)
+#endif
#endif
#define EXEC_PAGESIZE 4096
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
#endif /* !__ASSEMBLY__ */
-/*
- * Certain architectures need to do special things when PTEs
- * within a page table are directly modified. Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-
/*
* PMD_SHIFT determines the size of the area a second-level page
* table can map
/* Bits in the page table entry */
#define _PAGE_PRESENT 0x001 /* Software */
+#define _PAGE_MKCLEAR 0x002 /* Software */
#define _PAGE_RO 0x200 /* HW read-only */
#define _PAGE_INVALID 0x400 /* HW invalid */
*/
#define _REGION_THIRD 0x4
#define _REGION_THIRD_LEN 0x3
-#define _REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN|0x40)
+#define _REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN|0x40|0x100)
+#define _KERN_REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN)
/* Bits in the storage key */
#define _PAGE_CHANGED 0x02 /* HW changed bit */
#define __S110 PAGE_SHARED
#define __S111 PAGE_SHARED
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
+ */
+extern inline void set_pte(pte_t *pteptr, pte_t pteval)
+{
+ if ((pte_val(pteval) & (_PAGE_MKCLEAR|_PAGE_INVALID))
+ == _PAGE_MKCLEAR)
+ {
+ pte_val(pteval) &= ~_PAGE_MKCLEAR;
+
+ asm volatile ("sske %0,%1"
+ : : "d" (0), "a" (pte_val(pteval)));
+ }
+
+ *pteptr = pteval;
+}
+
/*
* Permanent address of a page.
*/
extern inline pte_t pte_mkclean(pte_t pte)
{
- /* We can't clear the changed bit atomically. The iske/and/sske
- * sequence has a race condition with the page referenced bit.
- * At the moment pte_mkclean is always followed by a pte_mkold.
- * So its safe to ignore the problem for now. Hope this will
- * never change ... */
- asm volatile ("sske %0,%1"
- : : "d" (0), "a" (pte_val(pte)));
+ /* The only user of pte_mkclean is the fork() code.
+ We must *not* clear the *physical* page dirty bit
+ just because fork() wants to clear the dirty bit in
+ *one* of the page's mappings. So we just do nothing. */
return pte;
}
asm volatile ("sske %0,%1"
: : "d" (_PAGE_CHANGED|_PAGE_REFERENCED),
"a" (pte_val(pte)));
+
+ pte_val(pte) &= ~_PAGE_MKCLEAR;
return pte;
}
pte_val(__pte) = physpage + pgprot_val(pgprot);
return __pte;
}
-#define mk_pte(page,pgprot) mk_pte_phys(__pa(((page)-mem_map)<<PAGE_SHIFT),pgprot)
+
+#define mk_pte(pg, pgprot) \
+({ \
+ struct page *__page = (pg); \
+ unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT); \
+ pte_t __pte = mk_pte_phys(__physpage, (pgprot)); \
+ \
+ if (__page != ZERO_PAGE(__physpage)) { \
+ int __users = page_count(__page); \
+ __users -= !!__page->buffers + !!__page->mapping; \
+ \
+ if (__users == 1) \
+ pte_val(__pte) |= _PAGE_MKCLEAR; \
+ } \
+ \
+ __pte; \
+})
#define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
#define PageSkip(page) (0)
#define kern_addr_valid(addr) (1)
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init() do { } while (0)
+
#endif /* _S390_PAGE_H */
ec_restart,
ec_halt,
ec_power_off,
+ ec_call_function,
ec_bit_last
} ec_bit_sig;
-/* Signals which come with a parameter area */
-typedef enum
-{
- ec_callback_sync,
- ec_callback_async
-} ec_cmd_sig;
-
-/* state information for signals */
-typedef enum
-{
- ec_pending,
- ec_executing,
- ec_done
-} ec_state;
-
-/* header for the queuing of callbacks */
-typedef struct ec_ext_call
-{
- ec_cmd_sig cmd;
- atomic_t status;
- struct ec_ext_call *next;
- void (*func)(void *info);
- void *info;
-} ec_ext_call;
/*
* Signal processor
__u16 cpu;
} sigp_info;
+extern unsigned long cpu_online_map;
+
#define NO_PROC_ID 0xFF /* No processor magic marker */
/*
void smp_local_timer_interrupt(struct pt_regs * regs);
-sigp_ccode smp_ext_call(int cpu, void (*cb)(void *info), void *info, int wait);
-void smp_ext_call_others(void (*cb)(void *info), void *info, int wait);
-sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig);
-void smp_ext_bitcall_others(ec_bit_sig sig);
-
-int smp_signal_others(sigp_order_code order_code,__u32 parameter,
- int spin,sigp_info *info);
#endif
#endif
#include <asm/lowcore.h>
#define __cpu_bh_enable(cpu) \
- do { barrier(); local_bh_count(cpu)--; } while (0)
+ do { barrier(); local_bh_count(cpu)--; } while (0)
#define cpu_bh_disable(cpu) \
- do { local_bh_count(cpu)++; barrier(); } while (0)
+ do { local_bh_count(cpu)++; barrier(); } while (0)
#define local_bh_disable() cpu_bh_disable(smp_processor_id())
#define __local_bh_enable() __cpu_bh_enable(smp_processor_id())
#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
+extern void do_call_softirq(void);
+
#define local_bh_enable() \
do { \
- unsigned int *ptr = &local_bh_count(smp_processor_id()); \
- barrier(); \
- if (!--*ptr) \
+ unsigned int *ptr = &local_bh_count(smp_processor_id()); \
+ barrier(); \
+ if (!--*ptr) \
if (softirq_pending(smp_processor_id())) \
- do_softirq(); \
+ /* Use the async. stack for softirq */ \
+ do_call_softirq(); \
} while (0)
#endif /* __ASM_SOFTIRQ_H */
__asm__ __volatile(" bras 1,1f\n"
"0: # diag 0,0,68\n"
"1: slr 0,0\n"
- " cs 0,1,%1\n"
+ " cs 0,1,0(%0)\n"
" jl 0b\n"
- : "=m" (lp->lock)
- : "0" (lp->lock) : "0", "1", "cc" );
+ : : "a" (&lp->lock) : "0", "1", "cc", "memory" );
}
extern inline int spin_trylock(spinlock_t *lp)
{
unsigned int result;
- __asm__ __volatile(" slr %1,%1\n"
+ __asm__ __volatile(" slr %0,%0\n"
" basr 1,0\n"
- "0: cs %1,1,%0"
- : "=m" (lp->lock), "=&d" (result)
- : "0" (lp->lock) : "1", "cc" );
+ "0: cs %0,1,0(%1)"
+ : "=&d" (result)
+ : "a" (&lp->lock) : "1", "cc", "memory" );
return !result;
}
{
__asm__ __volatile(" xc 0(4,%0),0(%0)\n"
" bcr 15,0"
- : /* no output */ : "a" (lp) : "memory", "cc" );
+ : : "a" (&lp->lock) : "memory", "cc" );
}
/*
#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
#define read_lock(rw) \
- asm volatile(" la 1,%0\n" \
- " lg 2,0(1)\n" \
+ asm volatile(" lg 2,0(%0)\n" \
" j 1f\n" \
"0: # diag 0,0,68\n" \
"1: nihh 2,0x7fff\n" /* clear high (=write) bit */ \
" la 3,1(2)\n" /* one more reader */ \
- " csg 2,3,0(1)\n" /* try to write new value */ \
+ " csg 2,3,0(%0)\n" /* try to write new value */ \
" jl 0b" \
- : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#define read_unlock(rw) \
- asm volatile(" la 1,%0\n" \
- " lg 2,0(1)\n" \
+ asm volatile(" lg 2,0(%0)\n" \
" j 1f\n" \
"0: # diag 0,0,68\n" \
"1: lgr 3,2\n" \
" bctgr 3,0\n" /* one less reader */ \
- " csg 2,3,0(1)\n" \
+ " csg 2,3,0(%0)\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#define write_lock(rw) \
- asm volatile(" la 1,%0\n" \
- " llihh 3,0x8000\n" /* new lock value = 0x80...0 */ \
+ asm volatile(" llihh 3,0x8000\n" /* new lock value = 0x80...0 */ \
" j 1f\n" \
"0: # diag 0,0,68\n" \
"1: slgr 2,2\n" /* old lock value must be 0 */ \
- " csg 2,3,0(1)\n" \
+ " csg 2,3,0(%0)\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#define write_unlock(rw) \
- asm volatile(" la 1,%0\n" \
- " slgr 3,3\n" /* new lock value = 0 */ \
+ asm volatile(" slgr 3,3\n" /* new lock value = 0 */ \
" j 1f\n" \
"0: # diag 0,0,68\n" \
"1: llihh 2,0x8000\n" /* old lock value must be 0x8..0 */\
- " csg 2,3,0(1)\n" \
+ " csg 2,3,0(%0)\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+ : : "a" (&(rw)->lock) : "2", "3", "cc", "memory" );
#endif /* __ASM_SPINLOCK_H */
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
+ _sigregs uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
- struct sigcontext *sc; /* Added for pthread support */
};
-
-
#endif /* !_ASM_S390_UCONTEXT_H */
#define __NR_capset 185
#define __NR_sigaltstack 186
#define __NR_sendfile 187
+#define __NR_getpmsg 188
+#define __NR_putpmsg 189
#define __NR_vfork 190
#define __NR_getrlimit 191 /* SuS compliant getrlimit */
#define __NR_lchown 198
long __res; \
__asm__ __volatile__ ( \
" svc %b1\n" \
- " lr %0,2" \
+ " lgr %0,2" \
: "=d" (__res) \
: "i" (__NR_##name) \
: _svc_clobber ); \
long __res; \
__asm__ __volatile__ ( \
" svc %b1\n" \
- " lr %0,2" \
+ " lgr %0,2" \
: "=d" (__res) \
: "i" (__NR_##name), \
"d" (__arg1) \
long __res; \
__asm__ __volatile__ ( \
" svc %b1\n" \
- " lr %0,2" \
+ " lgr %0,2" \
: "=d" (__res) \
: "i" (__NR_##name), \
"d" (__arg1), \
long __res; \
__asm__ __volatile__ ( \
" svc %b1\n" \
- " lr %0,2" \
+ " lgr %0,2" \
: "=d" (__res) \
: "i" (__NR_##name), \
"d" (__arg1), \
long __res; \
__asm__ __volatile__ ( \
" svc %b1\n" \
- " lr %0,2" \
+ " lgr %0,2" \
: "=d" (__res) \
: "i" (__NR_##name), \
"d" (__arg1), \
long __res; \
__asm__ __volatile__ ( \
" svc %b1\n" \
- " lr %0,2" \
+ " lgr %0,2" \
: "=d" (__res) \
: "i" (__NR_##name), \
"d" (__arg1), \
-/*
- * $Id: b1lli.h,v 1.8.8.2 2001/05/17 20:41:52 kai Exp $
+/* $Id: b1lli.h,v 1.8.8.3 2001/09/23 22:25:05 kai Exp $
*
* ISDN lowlevel-module for AVM B1-card.
*
* Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
*
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
*/
#ifndef _B1LLI_H_
-/*
- * $Id: b1pcmcia.h,v 1.1.8.1 2001/05/17 20:41:52 kai Exp $
+/* $Id: b1pcmcia.h,v 1.1.8.2 2001/09/23 22:25:05 kai Exp $
*
* Exported functions of module b1pcmcia to be called by
* avm_cs card services module.
*
* Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
*/
#ifndef _B1PCMCIA_H_
#define blk_finished_io(nsects) do { } while (0)
#define blk_started_io(nsects) do { } while (0)
+static inline unsigned int blksize_bits(unsigned int size)
+{
+ unsigned int bits = 8;
+ do {
+ bits++;
+ size >>= 1;
+ } while (size > 256);
+ return bits;
+}
+
+static inline unsigned int block_size(kdev_t dev)
+{
+ int retval = BLOCK_SIZE;
+ int major = MAJOR(dev);
+
+ if (blksize_size[major]) {
+ int minor = MINOR(dev);
+ if (blksize_size[major][minor])
+ retval = blksize_size[major][minor];
+ }
+ return retval;
+}
+
#endif
unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
unsigned char vc_utf_count;
int vc_utf_char;
- unsigned int vc_tab_stop[5]; /* Tab stops. 160 columns. */
+ unsigned int vc_tab_stop[8]; /* Tab stops. 256 columns. */
unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */
unsigned short * vc_translate;
unsigned char vc_G0_charset;
unsigned int block_group,
struct buffer_head ** bh);
-/* bitmap.c */
-extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
-
/* dir.c */
-
-/* file.c */
-extern int ext2_read (struct inode *, struct file *, char *, int);
-extern int ext2_write (struct inode *, struct file *, char *, int);
+extern int ext2_add_link (struct dentry *, struct inode *);
+extern ino_t ext2_inode_by_name(struct inode *, struct dentry *);
+extern int ext2_make_empty(struct inode *, struct inode *);
+extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct dentry *, struct page **);
+extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *);
+extern int ext2_empty_dir (struct inode *);
+extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
+extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *);
/* fsync.c */
extern int ext2_sync_file (struct file *, struct dentry *, int);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
+extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
/* inode.c */
-
-extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
-extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
-
extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *, int);
extern void ext2_put_inode (struct inode *);
extern void ext2_delete_inode (struct inode *);
extern int ext2_sync_inode (struct inode *);
extern void ext2_discard_prealloc (struct inode *);
+extern void ext2_truncate (struct inode *);
/* ioctl.c */
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
unsigned long);
-/* namei.c */
-extern struct inode_operations ext2_dir_inode_operations;
-
/* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern int ext2_statfs (struct super_block *, struct statfs *);
-/* truncate.c */
-extern void ext2_truncate (struct inode *);
-
/*
* Inodes and files operations
*/
/* dir.c */
extern struct file_operations ext2_dir_operations;
-extern int ext2_add_link (struct dentry *, struct inode *);
-extern ino_t ext2_inode_by_name(struct inode *, struct dentry *);
-extern int ext2_make_empty(struct inode *, struct inode *);
-extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct dentry *, struct page **);
-extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *);
-extern int ext2_empty_dir (struct inode *);
-extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
-extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *);
/* file.c */
extern struct inode_operations ext2_file_inode_operations;
extern struct file_operations ext2_file_operations;
+/* inode.c */
+extern struct address_space_operations ext2_aops;
+
+/* namei.c */
+extern struct inode_operations ext2_dir_inode_operations;
+
/* symlink.c */
extern struct inode_operations ext2_fast_symlink_inode_operations;
-extern struct address_space_operations ext2_aops;
-
#endif /* __KERNEL__ */
#endif /* _LINUX_EXT2_FS_H */
extern int posix_lock_file(struct file *, struct file_lock *, unsigned int);
extern void posix_block_lock(struct file_lock *, struct file_lock *);
extern void posix_unblock_lock(struct file_lock *);
+extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
extern int __get_lease(struct inode *inode, unsigned int flags);
extern time_t lease_get_mtime(struct inode *);
extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: i2c-dev.h,v 1.8 2000/08/12 16:37:15 mds Exp $ */
+/* $Id: i2c-dev.h,v 1.9 2001/08/15 03:04:58 mds Exp $ */
#ifndef I2C_DEV_H
#define I2C_DEV_H
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-elektor.h,v 1.4 2000/01/18 23:54:07 frodo Exp $ */
+/* $Id: i2c-elektor.h,v 1.5 2001/06/05 01:46:33 mds Exp $ */
#ifndef I2C_PCF_ELEKTOR_H
#define I2C_PCF_ELEKTOR_H 1
/*
- * This struct contains the hw-dependent functions of PCF8584 adapters to
- * manipulate the registers, and to init any hw-specific features.
- */
+ * This struct contains the hw-dependent functions of PCF8584 adapters to
+ * manipulate the registers, and to init any hw-specific features.
+ * vdovikin: removed: this module in real supports only one device,
+ * due to missing arguments in some functions, called from the algo-pcf module.
+ * Sometimes it's need to be rewriten -
+ * but for now just remove this for simpler reading */
+/*
struct i2c_pcf_isa {
int pi_base;
int pi_irq;
int pi_clock;
int pi_own;
};
-
+*/
#endif /* PCF_ELEKTOR_H */
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
-/* $Id: i2c-id.h,v 1.25 2000/10/12 07:27:29 simon Exp $ */
+/* $Id: i2c-id.h,v 1.35 2001/08/12 17:22:20 mds Exp $ */
#ifndef I2C_ID_H
#define I2C_ID_H
#define I2C_DRIVERID_BT829 19 /* pc to tv encoder */
#define I2C_DRIVERID_TDA9850 20 /* audio mixer */
#define I2C_DRIVERID_TDA9855 21 /* audio mixer */
-#define I2C_DRIVERID_SAA7110 22 /* */
+#define I2C_DRIVERID_SAA7110 22 /* video decoder */
#define I2C_DRIVERID_MGATVO 23 /* Matrox TVOut */
#define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */
#define I2C_DRIVERID_PCF8583 25 /* real time clock */
#define I2C_DRIVERID_VES1820 37 /* VLSI DVB-C decoder */
#define I2C_DRIVERID_SAA7113 38 /* video decoder */
#define I2C_DRIVERID_TDA8444 39 /* octuple 6-bit DAC */
-
+#define I2C_DRIVERID_BT819 40 /* video decoder */
+#define I2C_DRIVERID_BT856 41 /* video encoder */
+#define I2C_DRIVERID_VPX32XX 42 /* video decoder+vbi/vtxt */
+#define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */
+#define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
+#define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
#define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
#define I2C_DRIVERID_EXP1 0xF1
#define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_I2CPROC 901
+/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
+ These were originally in sensors.h in the lm_sensors package */
+#define I2C_DRIVERID_LM78 1002
+#define I2C_DRIVERID_LM75 1003
+#define I2C_DRIVERID_GL518 1004
+#define I2C_DRIVERID_EEPROM 1005
+#define I2C_DRIVERID_W83781D 1006
+#define I2C_DRIVERID_LM80 1007
+#define I2C_DRIVERID_ADM1021 1008
+#define I2C_DRIVERID_ADM9240 1009
+#define I2C_DRIVERID_LTC1710 1010
+#define I2C_DRIVERID_SIS5595 1011
+#define I2C_DRIVERID_ICSPLL 1012
+#define I2C_DRIVERID_BT869 1013
+#define I2C_DRIVERID_MAXILIFE 1014
+#define I2C_DRIVERID_MATORB 1015
+#define I2C_DRIVERID_GL520 1016
+#define I2C_DRIVERID_THMC50 1017
+#define I2C_DRIVERID_DDCMON 1018
+#define I2C_DRIVERID_VIA686A 1019
+#define I2C_DRIVERID_ADM1025 1020
+#define I2C_DRIVERID_LM87 1021
+#define I2C_DRIVERID_PCF8574 1022
+#define I2C_DRIVERID_MTP008 1023
+#define I2C_DRIVERID_DS1621 1024
+#define I2C_DRIVERID_ADM1024 1025
+#define I2C_DRIVERID_IT87 1026
+#define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
+
/*
* ---- Adapter types ----------------------------------------------------
*
#define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */
#define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */
#define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */
-#define I2C_ALGO_IIC 0x080000 /* ITE IIC bus */
#define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
#define I2C_HW_B_G400 0x09 /* Matrox G400 */
#define I2C_HW_B_I810 0x0a /* Intel I810 */
#define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
+#define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
#define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
#define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
+#define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
/* --- PCF 8584 based algorithms */
#define I2C_HW_P_LP 0x00 /* Parallel port interface */
/* --- MPC8xx PowerPC adapters */
#define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */
-/* --- ITE based algorithms */
-#define I2C_HW_I_IIC 0x00 /* controller on the ITE */
-
/* --- SMBus only adapters */
#define I2C_HW_SMBUS_PIIX4 0x00
#define I2C_HW_SMBUS_ALI15X3 0x01
--- /dev/null
+/*
+ sensors.h - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef SENSORS_SENSORS_H
+#define SENSORS_SENSORS_H
+
+#ifdef __KERNEL__
+
+/* Next two must be included before sysctl.h can be included, in 2.0 kernels */
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/sysctl.h>
+
+/* The type of callback functions used in sensors_{proc,sysctl}_real */
+typedef void (*i2c_real_callback) (struct i2c_client * client,
+ int operation, int ctl_name,
+ int *nrels_mag, long *results);
+
+/* Values for the operation field in the above function type */
+#define SENSORS_PROC_REAL_INFO 1
+#define SENSORS_PROC_REAL_READ 2
+#define SENSORS_PROC_REAL_WRITE 3
+
+/* These funcion reads or writes a 'real' value (encoded by the combination
+ of an integer and a magnitude, the last is the power of ten the value
+ should be divided with) to a /proc/sys directory. To use these functions,
+ you must (before registering the ctl_table) set the extra2 field to the
+ client, and the extra1 field to a function of the form:
+ void func(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+ This last function can be called for three values of operation. If
+ operation equals SENSORS_PROC_REAL_INFO, the magnitude should be returned
+ in nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
+ be read into results. nrels_mag should return the number of elements
+ read; the maximum number is put in it on entry. Finally, if operation
+ equals SENSORS_PROC_REAL_WRITE, the values in results should be
+ written to the chip. nrels_mag contains on entry the number of elements
+ found.
+ In all cases, client points to the client we wish to interact with,
+ and ctl_name is the SYSCTL id of the file we are accessing. */
+extern int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
+ void *oldval, size_t * oldlenp,
+ void *newval, size_t newlen,
+ void **context);
+extern int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
+ void *buffer, size_t * lenp);
+
+
+
+/* These rather complex functions must be called when you want to add or
+ delete an entry in /proc/sys/dev/sensors/chips (not yet implemented). It
+ also creates a new directory within /proc/sys/dev/sensors/.
+ ctl_template should be a template of the newly created directory. It is
+ copied in memory. The extra2 field of each file is set to point to client.
+ If any driver wants subdirectories within the newly created directory,
+ these functions must be updated! */
+extern int i2c_register_entry(struct i2c_client *client,
+ const char *prefix,
+ ctl_table * ctl_template,
+ struct module *controlling_mod);
+
+extern void i2c_deregister_entry(int id);
+
+
+/* A structure containing detect information.
+ Force variables overrule all other variables; they force a detection on
+ that place. If a specific chip is given, the module blindly assumes this
+ chip type is present; if a general force (kind == 0) is given, the module
+ will still try to figure out what type of chip is present. This is useful
+ if for some reasons the detect for SMBus or ISA address space filled
+ fails.
+ probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+ A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second is the address.
+ kind: The kind of chip. 0 equals any chip.
+*/
+struct i2c_force_data {
+ unsigned short *force;
+ unsigned short kind;
+};
+
+/* A structure containing the detect information.
+ normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
+ A list of I2C addresses which should normally be examined.
+ normal_i2c_range: filled in by the module writer. Terminated by
+ SENSORS_I2C_END
+ A list of pairs of I2C addresses, each pair being an inclusive range of
+ addresses which should normally be examined.
+ normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
+ A list of ISA addresses which should normally be examined.
+ normal_isa_range: filled in by the module writer. Terminated by
+ SENSORS_ISA_END
+ A list of triples. The first two elements are ISA addresses, being an
+ range of addresses which should normally be examined. The third is the
+ modulo parameter: only addresses which are 0 module this value relative
+ to the first address of the range are actually considered.
+ probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+ A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second is the address. These
+ addresses are also probed, as if they were in the 'normal' list.
+ probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END
+ values.
+ A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second and third are addresses.
+ These form an inclusive range of addresses that are also probed, as
+ if they were in the 'normal' list.
+ ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+ A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second is the I2C address. These
+ addresses are never probed. This parameter overrules 'normal' and
+ 'probe', but not the 'force' lists.
+ ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END
+ values.
+ A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second and third are addresses.
+ These form an inclusive range of I2C addresses that are never probed.
+ This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+ force_data: insmod parameters. A list, ending with an element of which
+ the force field is NULL.
+*/
+struct i2c_address_data {
+ unsigned short *normal_i2c;
+ unsigned short *normal_i2c_range;
+ unsigned int *normal_isa;
+ unsigned int *normal_isa_range;
+ unsigned short *probe;
+ unsigned short *probe_range;
+ unsigned short *ignore;
+ unsigned short *ignore_range;
+ struct i2c_force_data *forces;
+};
+
+/* Internal numbers to terminate lists */
+#define SENSORS_I2C_END 0xfffe
+#define SENSORS_ISA_END 0xfffefffe
+
+/* The numbers to use to set an ISA or I2C bus address */
+#define SENSORS_ISA_BUS 9191
+#define SENSORS_ANY_I2C_BUS 0xffff
+
+/* The length of the option lists */
+#define SENSORS_MAX_OPTS 48
+
+/* Default fill of many variables */
+#define SENSORS_DEFAULTS {SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END}
+
+/* This is ugly. We need to evaluate SENSORS_MAX_OPTS before it is
+ stringified */
+#define SENSORS_MODPARM_AUX1(x) "1-" #x "h"
+#define SENSORS_MODPARM_AUX(x) SENSORS_MODPARM_AUX1(x)
+#define SENSORS_MODPARM SENSORS_MODPARM_AUX(SENSORS_MAX_OPTS)
+
+/* SENSORS_MODULE_PARM creates a module parameter, and puts it in the
+ module header */
+#define SENSORS_MODULE_PARM(var,desc) \
+ static unsigned short var[SENSORS_MAX_OPTS] = SENSORS_DEFAULTS; \
+ MODULE_PARM(var,SENSORS_MODPARM); \
+ MODULE_PARM_DESC(var,desc)
+
+/* SENSORS_MODULE_PARM creates a 'force_*' module parameter, and puts it in
+ the module header */
+#define SENSORS_MODULE_PARM_FORCE(name) \
+ SENSORS_MODULE_PARM(force_ ## name, \
+ "List of adapter,address pairs which are unquestionably" \
+ " assumed to contain a `" # name "' chip")
+
+
+/* This defines several insmod variables, and the addr_data structure */
+#define SENSORS_INSMOD \
+ SENSORS_MODULE_PARM(probe, \
+ "List of adapter,address pairs to scan additionally"); \
+ SENSORS_MODULE_PARM(probe_range, \
+ "List of adapter,start-addr,end-addr triples to scan " \
+ "additionally"); \
+ SENSORS_MODULE_PARM(ignore, \
+ "List of adapter,address pairs not to scan"); \
+ SENSORS_MODULE_PARM(ignore_range, \
+ "List of adapter,start-addr,end-addr triples not to " \
+ "scan"); \
+ static struct i2c_address_data addr_data = \
+ {normal_i2c, normal_i2c_range, \
+ normal_isa, normal_isa_range, \
+ probe, probe_range, \
+ ignore, ignore_range, \
+ forces}
+
+/* The following functions create an enum with the chip names as elements.
+ The first element of the enum is any_chip. These are the only macros
+ a module will want to use. */
+
+#define SENSORS_INSMOD_0 \
+ enum chips { any_chip }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ static struct i2c_force_data forces[] = {{force,any_chip},{NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_1(chip1) \
+ enum chips { any_chip, chip1 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ static struct i2c_force_data forces[] = {{force,any_chip},\
+ {force_ ## chip1,chip1}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_2(chip1,chip2) \
+ enum chips { any_chip, chip1, chip2 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_3(chip1,chip2,chip3) \
+ enum chips { any_chip, chip1, chip2, chip3 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_4(chip1,chip2,chip3,chip4) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_5(chip1,chip2,chip3,chip4,chip5) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_6(chip1,chip2,chip3,chip4,chip5,chip6) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ SENSORS_MODULE_PARM_FORCE(chip6); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {force_ ## chip6,chip6}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_7(chip1,chip2,chip3,chip4,chip5,chip6,chip7) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ SENSORS_MODULE_PARM_FORCE(chip6); \
+ SENSORS_MODULE_PARM_FORCE(chip7); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {force_ ## chip6,chip6}, \
+ {force_ ## chip7,chip7}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
+ int addr, unsigned short flags,
+ int kind);
+
+/* Detect function. It iterates over all possible addresses itself. For
+ SMBus addresses, it will only call found_proc if some client is connected
+ to the SMBus (unless a 'force' matched); for ISA detections, this is not
+ done. */
+extern int i2c_detect(struct i2c_adapter *adapter,
+ struct i2c_address_data *address_data,
+ i2c_found_addr_proc * found_proc);
+
+
+/* This macro is used to scale user-input to sensible values in almost all
+ chip drivers. */
+extern inline int SENSORS_LIMIT(long value, long low, long high)
+{
+ if (value < low)
+ return low;
+ else if (value > high)
+ return high;
+ else
+ return value;
+}
+
+#endif /* def __KERNEL__ */
+
+
+/* The maximum length of the prefix */
+#define SENSORS_PREFIX_MAX 20
+
+/* Sysctl IDs */
+#ifdef DEV_HWMON
+#define DEV_SENSORS DEV_HWMON
+#else /* ndef DEV_HWMOM */
+#define DEV_SENSORS 2 /* The id of the lm_sensors directory within the
+ dev table */
+#endif /* def DEV_HWMON */
+
+#define SENSORS_CHIPS 1
+struct i2c_chips_data {
+ int sysctl_id;
+ char name[SENSORS_PREFIX_MAX + 13];
+};
+
+#endif /* def SENSORS_SENSORS_H */
+
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c.h,v 1.42 2000/09/06 20:14:06 frodo Exp $ */
+/* $Id: i2c.h,v 1.46 2001/08/31 00:04:07 phil Exp $ */
#ifndef I2C_H
#define I2C_H
+#define I2C_DATE "20010830"
+#define I2C_VERSION "2.6.1"
+
#include <linux/i2c-id.h> /* id values of adapters et. al. */
#include <linux/types.h>
char name[32]; /* textual description */
unsigned int id;
- /* If a adapter algorithm can't to I2C-level access, set master_xfer
+ /* If an adapter algorithm can't to I2C-level access, set master_xfer
to NULL. If an adapter algorithm can do SMBus access, set
smbus_xfer. If set to NULL, the SMBus protocol is simulated
using common I2C messages */
you can cheat by simply not registering. Not recommended, of course! */
extern int i2c_check_addr (struct i2c_adapter *adapter, int addr);
-/* Detect function. It itterates over all possible addresses itself.
+/* Detect function. It iterates over all possible addresses itself.
* It will only call found_proc if some client is connected at the
* specific address (unless a 'force' matched);
*/
extern int i2c_control(struct i2c_client *,unsigned int, unsigned long);
/* This call returns a unique low identifier for each registered adapter,
- * or -1 if the adapter was not regisitered.
+ * or -1 if the adapter was not registered.
*/
extern int i2c_adapter_id(struct i2c_adapter *adap);
* corresponding header files.
*/
/* -> bit-adapter specific ioctls */
-#define I2C_RETRIES 0x0701 /* number times a device address should */
- /* be polled when not acknowledging */
+#define I2C_RETRIES 0x0701 /* number of times a device address */
+ /* should be polled when not */
+ /* acknowledging */
#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */
ignore, ignore_range, \
force}
+/* Detect whether we are on the isa bus. If this returns true, all i2c
+ access will fail! */
+#define i2c_is_isa_client(clientptr) \
+ ((clientptr)->adapter->algo->id == I2C_ALGO_ISA)
+#define i2c_is_isa_adapter(adapptr) \
+ ((adapptr)->algo->id == I2C_ALGO_ISA)
+
#endif /* def __KERNEL__ */
#endif /* I2C_H */
#define I2OLCTGET _IOWR(I2O_MAGIC_NUMBER,2,struct i2o_cmd_hrtlct)
#define I2OPARMSET _IOWR(I2O_MAGIC_NUMBER,3,struct i2o_cmd_psetget)
#define I2OPARMGET _IOWR(I2O_MAGIC_NUMBER,4,struct i2o_cmd_psetget)
-#define I2OSWDL _IOWR(I2O_MAGIC_NUMBER,5,struct i2o_sw_xfer)
-#define I2OSWUL _IOWR(I2O_MAGIC_NUMBER,6,struct i2o_sw_xfer)
+#define I2OSWDL _IOWR(I2O_MAGIC_NUMBER,5,struct i2o_sw_xfer)
+#define I2OSWUL _IOWR(I2O_MAGIC_NUMBER,6,struct i2o_sw_xfer)
#define I2OSWDEL _IOWR(I2O_MAGIC_NUMBER,7,struct i2o_sw_xfer)
#define I2OVALIDATE _IOR(I2O_MAGIC_NUMBER,8,u32)
-#define I2OHTML _IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
+#define I2OHTML _IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
#define I2OEVTREG _IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
#define I2OEVTGET _IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
void *buf; /* Pointer to software buffer */
unsigned int *swlen; /* Length of software data */
unsigned int *maxfrag; /* Maximum fragment count */
- unsigned int *curfrag; /* Current fragment count */
+ unsigned int *curfrag; /* Current fragment count */
};
struct i2o_html
{
struct i2o_evt_id id;
unsigned char evt_data[I2O_EVT_DATA_SIZE];
- unsigned int data_size;
+ unsigned int data_size;
};
struct i2o_evt_get
#define I2O_BUS_PCI 4
#define I2O_BUS_PCMCIA 5
#define I2O_BUS_NUBUS 6
-#define I2O_BUS_CARDBUS 7
-#define I2O_BUS_UNKNOWN 0x80
+#define I2O_BUS_CARDBUS 7
+#define I2O_BUS_UNKNOWN 0x80
#ifndef __KERNEL__
#endif /* __KERNEL__ */
-typedef struct _i2o_pci_bus {
- u8 PciFunctionNumber;
- u8 PciDeviceNumber;
- u8 PciBusNumber;
- u8 reserved;
- u16 PciVendorID;
- u16 PciDeviceID;
+typedef struct _i2o_pci_bus
+{
+ u8 PciFunctionNumber;
+ u8 PciDeviceNumber;
+ u8 PciBusNumber;
+ u8 reserved;
+ u16 PciVendorID;
+ u16 PciDeviceID;
} i2o_pci_bus;
-typedef struct _i2o_local_bus {
- u16 LbBaseIOPort;
- u16 reserved;
- u32 LbBaseMemoryAddress;
+typedef struct _i2o_local_bus
+{
+ u16 LbBaseIOPort;
+ u16 reserved;
+ u32 LbBaseMemoryAddress;
} i2o_local_bus;
-typedef struct _i2o_isa_bus {
- u16 IsaBaseIOPort;
- u8 CSN;
- u8 reserved;
- u32 IsaBaseMemoryAddress;
+typedef struct _i2o_isa_bus
+{
+ u16 IsaBaseIOPort;
+ u8 CSN;
+ u8 reserved;
+ u32 IsaBaseMemoryAddress;
} i2o_isa_bus;
-typedef struct _i2o_eisa_bus_info {
- u16 EisaBaseIOPort;
- u8 reserved;
- u8 EisaSlotNumber;
- u32 EisaBaseMemoryAddress;
+typedef struct _i2o_eisa_bus_info
+{
+ u16 EisaBaseIOPort;
+ u8 reserved;
+ u8 EisaSlotNumber;
+ u32 EisaBaseMemoryAddress;
} i2o_eisa_bus;
-typedef struct _i2o_mca_bus {
- u16 McaBaseIOPort;
- u8 reserved;
- u8 McaSlotNumber;
- u32 McaBaseMemoryAddress;
+typedef struct _i2o_mca_bus
+{
+ u16 McaBaseIOPort;
+ u8 reserved;
+ u8 McaSlotNumber;
+ u32 McaBaseMemoryAddress;
} i2o_mca_bus;
-typedef struct _i2o_other_bus {
+typedef struct _i2o_other_bus
+{
u16 BaseIOPort;
u16 reserved;
u32 BaseMemoryAddress;
} i2o_other_bus;
-typedef struct _i2o_hrt_entry {
- u32 adapter_id;
- u32 parent_tid:12;
- u32 state:4;
- u32 bus_num:8;
- u32 bus_type:8;
- union {
- i2o_pci_bus pci_bus;
- i2o_local_bus local_bus;
- i2o_isa_bus isa_bus;
- i2o_eisa_bus eisa_bus;
- i2o_mca_bus mca_bus;
- i2o_other_bus other_bus;
+typedef struct _i2o_hrt_entry
+{
+ u32 adapter_id;
+ u32 parent_tid:12;
+ u32 tate:4;
+ u32 bus_num:8;
+ u32 bus_type:8;
+ union
+ {
+ i2o_pci_bus pci_bus;
+ i2o_local_bus local_bus;
+ i2o_isa_bus isa_bus;
+ i2o_eisa_bus eisa_bus;
+ i2o_mca_bus mca_bus;
+ i2o_other_bus other_bus;
} bus;
} i2o_hrt_entry;
-typedef struct _i2o_hrt {
- u16 num_entries;
- u8 entry_len;
- u8 hrt_version;
- u32 change_ind;
+typedef struct _i2o_hrt
+{
+ u16 num_entries;
+ u8 entry_len;
+ u8 hrt_version;
+ u32 change_ind;
i2o_hrt_entry hrt_entry[1];
} i2o_hrt;
-typedef struct _i2o_lct_entry {
- u32 entry_size:16;
- u32 tid:12;
- u32 reserved:4;
- u32 change_ind;
- u32 device_flags;
- u32 class_id:12;
- u32 version:4;
- u32 vendor_id:16;
- u32 sub_class;
- u32 user_tid:12;
- u32 parent_tid:12;
- u32 bios_info:8;
- u8 identity_tag[8];
- u32 event_capabilities;
+typedef struct _i2o_lct_entry
+{
+ u32 entry_size:16;
+ u32 tid:12;
+ u32 reserved:4;
+ u32 change_ind;
+ u32 device_flags;
+ u32 class_id:12;
+ u32 version:4;
+ u32 vendor_id:16;
+ u32 sub_class;
+ u32 user_tid:12;
+ u32 parent_tid:12;
+ u32 bios_info:8;
+ u8 identity_tag[8];
+ u32 event_capabilities;
} i2o_lct_entry;
-typedef struct _i2o_lct {
- u32 table_size:16;
- u32 boot_tid:12;
- u32 lct_ver:4;
- u32 iop_flags;
- u32 change_ind;
+typedef struct _i2o_lct
+{
+ u32 table_size:16;
+ u32 boot_tid:12;
+ u32 lct_ver:4;
+ u32 iop_flags;
+ u32 change_ind;
i2o_lct_entry lct_entry[1];
} i2o_lct;
-typedef struct _i2o_status_block {
- u16 org_id;
- u16 reserved;
- u16 iop_id:12;
- u16 reserved1:4;
- u16 host_unit_id;
- u16 segment_number:12;
- u16 i2o_version:4;
- u8 iop_state;
- u8 msg_type;
- u16 inbound_frame_size;
- u8 init_code;
- u8 reserved2;
- u32 max_inbound_frames;
- u32 cur_inbound_frames;
- u32 max_outbound_frames;
- char product_id[24];
- u32 expected_lct_size;
- u32 iop_capabilities;
- u32 desired_mem_size;
- u32 current_mem_size;
- u32 current_mem_base;
- u32 desired_io_size;
- u32 current_io_size;
- u32 current_io_base;
- u32 reserved3:24;
- u32 cmd_status:8;
+typedef struct _i2o_status_block
+{
+ u16 org_id;
+ u16 reserved;
+ u16 iop_id:12;
+ u16 reserved1:4;
+ u16 host_unit_id;
+ u16 segment_number:12;
+ u16 i2o_version:4;
+ u8 iop_state;
+ u8 msg_type;
+ u16 inbound_frame_size;
+ u8 init_code;
+ u8 reserved2;
+ u32 max_inbound_frames;
+ u32 cur_inbound_frames;
+ u32 max_outbound_frames;
+ char product_id[24];
+ u32 expected_lct_size;
+ u32 iop_capabilities;
+ u32 desired_mem_size;
+ u32 current_mem_size;
+ u32 current_mem_base;
+ u32 desired_io_size;
+ u32 current_io_size;
+ u32 current_io_base;
+ u32 reserved3:24;
+ u32 cmd_status:8;
} i2o_status_block;
-
+
/* Event indicator mask flags */
#define I2O_EVT_IND_STATE_CHANGE 0x80000000
#define I2O_EVT_IND_GENERAL_WARNING 0x40000000
#define I2O_EVT_IND_EXEC_ADAPTER_FAULT 0x00000004
#define I2O_EVT_IND_EXEC_POWER_FAIL 0x00000008
#define I2O_EVT_IND_EXEC_RESET_PENDING 0x00000010
-#define I2O_EVT_IND_EXEC_RESET_IMMINENT 0x00000020
+#define I2O_EVT_IND_EXEC_RESET_IMMINENT 0x00000020
#define I2O_EVT_IND_EXEC_HW_FAIL 0x00000040
#define I2O_EVT_IND_EXEC_XCT_CHANGE 0x00000080
#define I2O_EVT_IND_EXEC_NEW_LCT_ENTRY 0x00000100
#define I2O_EVT_IND_BSA_VOLUME_LOAD 0x00000001
#define I2O_EVT_IND_BSA_VOLUME_UNLOAD 0x00000002
#define I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ 0x00000004
-#define I2O_EVT_IND_BSA_CAPACITY_CHANGE 0x00000008
+#define I2O_EVT_IND_BSA_CAPACITY_CHANGE 0x00000008
#define I2O_EVT_IND_BSA_SCSI_SMART 0x00000010
/* Event data for generic events */
#define I2O_EVT_STATE_CHANGE_NORMAL 0x00
#define I2O_EVT_STATE_CHANGE_SUSPENDED 0x01
#define I2O_EVT_STATE_CHANGE_RESTART 0x02
-#define I2O_EVT_STATE_CHANGE_NA_RECOVER 0x03
+#define I2O_EVT_STATE_CHANGE_NA_RECOVER 0x03
#define I2O_EVT_STATE_CHANGE_NA_NO_RECOVER 0x04
#define I2O_EVT_STATE_CHANGE_QUIESCE_REQUEST 0x05
#define I2O_EVT_STATE_CHANGE_FAILED 0x10
#define I2O_EVT_GEN_WARNING_NORMAL 0x00
#define I2O_EVT_GEN_WARNING_ERROR_THRESHOLD 0x01
-#define I2O_EVT_GEN_WARNING_MEDIA_FAULT 0x02
+#define I2O_EVT_GEN_WARNING_MEDIA_FAULT 0x02
#define I2O_EVT_CAPABILITY_OTHER 0x01
#define I2O_EVT_CAPABILITY_CHANGED 0x02
/* Class ID and Code Assignments
* (LCT.ClassID.Version field)
*/
-#define I2O_CLASS_VERSION_10 0x00
-#define I2O_CLASS_VERSION_11 0x01
+#define I2O_CLASS_VERSION_10 0x00
+#define I2O_CLASS_VERSION_11 0x01
/* Class code names
* (from v1.5 Table 6-1 Class Code Assignments.)
*/
-
-#define I2O_CLASS_EXECUTIVE 0x000
-#define I2O_CLASS_DDM 0x001
-#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010
-#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011
-#define I2O_CLASS_LAN 0x020
-#define I2O_CLASS_WAN 0x030
-#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040
-#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041
-#define I2O_CLASS_SCSI_PERIPHERAL 0x051
-#define I2O_CLASS_ATE_PORT 0x060
-#define I2O_CLASS_ATE_PERIPHERAL 0x061
-#define I2O_CLASS_FLOPPY_CONTROLLER 0x070
-#define I2O_CLASS_FLOPPY_DEVICE 0x071
-#define I2O_CLASS_BUS_ADAPTER_PORT 0x080
-#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
-#define I2O_CLASS_PEER_TRANSPORT 0x091
+
+#define I2O_CLASS_EXECUTIVE 0x000
+#define I2O_CLASS_DDM 0x001
+#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010
+#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011
+#define I2O_CLASS_LAN 0x020
+#define I2O_CLASS_WAN 0x030
+#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040
+#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041
+#define I2O_CLASS_SCSI_PERIPHERAL 0x051
+#define I2O_CLASS_ATE_PORT 0x060
+#define I2O_CLASS_ATE_PERIPHERAL 0x061
+#define I2O_CLASS_FLOPPY_CONTROLLER 0x070
+#define I2O_CLASS_FLOPPY_DEVICE 0x071
+#define I2O_CLASS_BUS_ADAPTER_PORT 0x080
+#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
+#define I2O_CLASS_PEER_TRANSPORT 0x091
/*
* Rest of 0x092 - 0x09f reserved for peer-to-peer classes
*/
-
-#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff
+
+#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff
/*
* Subclasses
*/
-#define I2O_SUBCLASS_i960 0x001
-#define I2O_SUBCLASS_HDM 0x020
-#define I2O_SUBCLASS_ISM 0x021
-
+#define I2O_SUBCLASS_i960 0x001
+#define I2O_SUBCLASS_HDM 0x020
+#define I2O_SUBCLASS_ISM 0x021
+
/* Operation functions */
-#define I2O_PARAMS_FIELD_GET 0x0001
-#define I2O_PARAMS_LIST_GET 0x0002
-#define I2O_PARAMS_MORE_GET 0x0003
-#define I2O_PARAMS_SIZE_GET 0x0004
-#define I2O_PARAMS_TABLE_GET 0x0005
-#define I2O_PARAMS_FIELD_SET 0x0006
-#define I2O_PARAMS_LIST_SET 0x0007
-#define I2O_PARAMS_ROW_ADD 0x0008
-#define I2O_PARAMS_ROW_DELETE 0x0009
-#define I2O_PARAMS_TABLE_CLEAR 0x000A
+#define I2O_PARAMS_FIELD_GET 0x0001
+#define I2O_PARAMS_LIST_GET 0x0002
+#define I2O_PARAMS_MORE_GET 0x0003
+#define I2O_PARAMS_SIZE_GET 0x0004
+#define I2O_PARAMS_TABLE_GET 0x0005
+#define I2O_PARAMS_FIELD_SET 0x0006
+#define I2O_PARAMS_LIST_SET 0x0007
+#define I2O_PARAMS_ROW_ADD 0x0008
+#define I2O_PARAMS_ROW_DELETE 0x0009
+#define I2O_PARAMS_TABLE_CLEAR 0x000A
/*
* I2O serial number conventions / formats
* (circa v1.5)
*/
-#define I2O_SNFORMAT_UNKNOWN 0
-#define I2O_SNFORMAT_BINARY 1
-#define I2O_SNFORMAT_ASCII 2
-#define I2O_SNFORMAT_UNICODE 3
-#define I2O_SNFORMAT_LAN48_MAC 4
-#define I2O_SNFORMAT_WAN 5
+#define I2O_SNFORMAT_UNKNOWN 0
+#define I2O_SNFORMAT_BINARY 1
+#define I2O_SNFORMAT_ASCII 2
+#define I2O_SNFORMAT_UNICODE 3
+#define I2O_SNFORMAT_LAN48_MAC 4
+#define I2O_SNFORMAT_WAN 5
/*
* Plus new in v2.0 (Yellowstone pdf doc)
*/
-#define I2O_SNFORMAT_LAN64_MAC 6
-#define I2O_SNFORMAT_DDM 7
-#define I2O_SNFORMAT_IEEE_REG64 8
-#define I2O_SNFORMAT_IEEE_REG128 9
-#define I2O_SNFORMAT_UNKNOWN2 0xff
+#define I2O_SNFORMAT_LAN64_MAC 6
+#define I2O_SNFORMAT_DDM 7
+#define I2O_SNFORMAT_IEEE_REG64 8
+#define I2O_SNFORMAT_IEEE_REG128 9
+#define I2O_SNFORMAT_UNKNOWN2 0xff
/*
* I2O Get Status State values
*/
-#define ADAPTER_STATE_INITIALIZING 0x01
-#define ADAPTER_STATE_RESET 0x02
-#define ADAPTER_STATE_HOLD 0x04
-#define ADAPTER_STATE_READY 0x05
-#define ADAPTER_STATE_OPERATIONAL 0x08
-#define ADAPTER_STATE_FAILED 0x10
-#define ADAPTER_STATE_FAULTED 0x11
-
+#define ADAPTER_STATE_INITIALIZING 0x01
+#define ADAPTER_STATE_RESET 0x02
+#define ADAPTER_STATE_HOLD 0x04
+#define ADAPTER_STATE_READY 0x05
+#define ADAPTER_STATE_OPERATIONAL 0x08
+#define ADAPTER_STATE_FAILED 0x10
+#define ADAPTER_STATE_FAULTED 0x11
+
#endif /* _I2O_DEV_H */
#ifndef _I2O_H
#define _I2O_H
-#ifdef __KERNEL__ /* This file to be included by kernel only */
+
+#ifdef __KERNEL__ /* This file to be included by kernel only */
#include <linux/i2o-dev.h>
-/* How many different OSM's are we allowing */
+/* How many different OSM's are we allowing */
#define MAX_I2O_MODULES 64
/* How many OSMs can register themselves for device status updates? */
#define I2O_MAX_MANAGERS 4
-#include <asm/semaphore.h> /* Needed for MUTEX init macros */
+#include <asm/semaphore.h> /* Needed for MUTEX init macros */
#include <linux/config.h>
#include <linux/notifier.h>
-#include <linux/ioport.h>
#include <asm/atomic.h>
/*
- * message structures
+ * Message structures
*/
struct i2o_message
{
u16 size;
u32 target_tid:12;
u32 init_tid:12;
- u32 function:8;
+ u32 function:8;
u32 initiator_context;
/* List follows */
};
*/
struct i2o_device
{
- i2o_lct_entry lct_data; /* Device LCT information */
- u32 flags;
- int i2oversion; /* I2O version supported. Actually there
- * should be high and low version */
+ i2o_lct_entry lct_data; /* Device LCT information */
+ u32 flags;
+ int i2oversion; /* I2O version supported. Actually
+ * there should be high and low
+ * version */
- struct proc_dir_entry* proc_entry; /* /proc dir */
+ struct proc_dir_entry *proc_entry; /* /proc dir */
/* Primary user */
struct i2o_handler *owner;
/* Management users */
- struct i2o_handler *managers[I2O_MAX_MANAGERS];
+ struct i2o_handler *managers[I2O_MAX_MANAGERS];
int num_managers;
struct i2o_controller *controller; /* Controlling IOP */
/*
* Resource data for each PCI I2O controller
- */
+ */
struct i2o_pci
{
- struct pci_dev *pdev; /* PCI device */
- int irq;
- int queue_buggy:1; /* Don't send a lot of messages */
- int short_req:1; /* Use small block sizes */
- int dpt:1; /* Don't quiesce */
+ int irq;
+ int queue_buggy:1; /* Don't send a lot of messages */
+ int short_req:1; /* Use small block sizes */
+ int dpt:1; /* Don't quiesce */
#ifdef CONFIG_MTRR
- int mtrr_reg0;
- int mtrr_reg1;
+ int mtrr_reg0;
+ int mtrr_reg1;
#endif
};
/*
* Transport types supported by I2O stack
*/
-#define I2O_TYPE_PCI 0x01 /* PCI I2O controller */
+#define I2O_TYPE_PCI 0x01 /* PCI I2O controller */
/*
*/
struct i2o_controller
{
+ struct pci_dev *pdev; /* PCI device */
+
char name[16];
int unit;
int type;
u32 mem_offset; /* MFA offset */
u32 mem_phys; /* MFA physical */
-
+
int battery:1; /* Has a battery backup */
int io_alloc:1; /* An I/O resource was allocated */
int mem_alloc:1; /* A memory resource was allocated */
-
+
struct resource io_resource; /* I/O resource allocated to the IOP */
struct resource mem_resource; /* Mem resource allocated to the IOP */
- struct proc_dir_entry* proc_entry; /* /proc dir */
+ struct proc_dir_entry *proc_entry; /* /proc dir */
- union
- { /* Bus information */
+ union { /* Bus information */
struct i2o_pci pci;
} bus;
/* Bus specific destructor */
- void (*destructor)(struct i2o_controller *);
+ void (*destructor)(struct i2o_controller *);
/* Bus specific attach/detach */
- int (*bind)(struct i2o_controller *, struct i2o_device *);
+ int (*bind)(struct i2o_controller *, struct i2o_device *);
/* Bus specific initiator */
int (*unbind)(struct i2o_controller *, struct i2o_device *);
/* Bus specific enable/disable */
- void (*bus_enable)(struct i2o_controller *c);
- void (*bus_disable)(struct i2o_controller *c);
+ void (*bus_enable)(struct i2o_controller *);
+ void (*bus_disable)(struct i2o_controller *);
- void *page_frame; /* Message buffers */
+ void *page_frame; /* Message buffers */
+ dma_addr_t page_frame_map; /* Cache map */
};
/*
struct i2o_handler
{
/* Message reply handler */
- void (*reply)(struct i2o_handler *, struct i2o_controller *, struct i2o_message *);
+ void (*reply)(struct i2o_handler *, struct i2o_controller *,
+ struct i2o_message *);
/* New device notification handler */
void (*new_dev_notify)(struct i2o_controller *, struct i2o_device *);
void (*reboot_notify)(void);
char *name; /* OSM name */
- int context; /* Low 8 bits of the transaction info */
+ int context; /* Low 8 bits of the transaction info */
u32 class; /* I2O classes that this driver handles */
/* User data follows */
};
{
int (*install)(struct i2o_controller *);
int (*activate)(struct i2o_controller *);
- struct i2o_controller* (*find)(int);
+ struct i2o_controller *(*find)(int);
void (*unlock)(struct i2o_controller *);
- void (*run_queue)(struct i2o_controller *c);
+ void (*run_queue)(struct i2o_controller * c);
int (*delete)(struct i2o_controller *);
};
-#endif // MODULE
+#endif /* MODULE */
/*
* I2O System table entry
u32 iop_id:12;
u32 reserved2:20;
u16 seg_num:12;
- u16 i2o_version:4;
- u8 iop_state;
- u8 msg_type;
+ u16 i2o_version:4;
+ u8 iop_state;
+ u8 msg_type;
u16 frame_size;
u16 reserved3;
u32 last_changed;
struct i2o_sys_tbl
{
- u8 num_entries;
- u8 version;
- u16 reserved1;
+ u8 num_entries;
+ u8 version;
+ u16 reserved1;
u32 change_ind;
u32 reserved2;
u32 reserved3;
struct i2o_sys_tbl_entry iops[0];
-};
+};
/*
* Messenger inlines
static inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 Val)
{
- *c->reply_port= Val;
+ *c->reply_port = Val;
}
-
+
static inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
{
static inline void i2o_post_message(struct i2o_controller *c, u32 m)
{
/* The second line isnt spurious - thats forcing PCI posting */
- I2O_POST_WRITE32(c,m);
+ I2O_POST_WRITE32(c, m);
(void) I2O_IRQ_READ32(c);
}
static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
{
- I2O_REPLY_WRITE32(c,m);
+ I2O_REPLY_WRITE32(c, m);
}
extern struct i2o_controller *i2o_find_controller(int);
extern int i2o_claim_device(struct i2o_device *, struct i2o_handler *);
extern int i2o_release_device(struct i2o_device *, struct i2o_handler *);
extern int i2o_device_notify_on(struct i2o_device *, struct i2o_handler *);
-extern int i2o_device_notify_off(struct i2o_device *, struct i2o_handler *);
+extern int i2o_device_notify_off(struct i2o_device *,
+ struct i2o_handler *);
extern int i2o_post_this(struct i2o_controller *, u32 *, int);
extern int i2o_post_wait(struct i2o_controller *, u32 *, int, int);
-extern int i2o_post_wait_mem(struct i2o_controller *, u32 *, int, int, void *, void *);
-
-extern int i2o_query_scalar(struct i2o_controller *, int, int, int, void *, int);
-extern int i2o_set_scalar(struct i2o_controller *, int, int, int, void *, int);
-extern int i2o_query_table(int, struct i2o_controller *, int, int, int, void *,
- int, void *, int);
-extern int i2o_clear_table(struct i2o_controller *, int, int);
-extern int i2o_row_add_table(struct i2o_controller *, int, int, int, void *,
- int);
-extern int i2o_issue_params(int, struct i2o_controller *, int, void *,
- int, void *, int);
-
-extern int i2o_event_register(struct i2o_controller *, u32, u32, u32, u32);
+extern int i2o_post_wait_mem(struct i2o_controller *, u32 *, int, int,
+ void *, void *);
+
+extern int i2o_query_scalar(struct i2o_controller *, int, int, int, void *,
+ int);
+extern int i2o_set_scalar(struct i2o_controller *, int, int, int, void *,
+ int);
+extern int i2o_query_table(int, struct i2o_controller *, int, int, int,
+ void *, int, void *, int);
+extern int i2o_clear_table(struct i2o_controller *, int, int);
+extern int i2o_row_add_table(struct i2o_controller *, int, int, int,
+ void *, int);
+extern int i2o_issue_params(int, struct i2o_controller *, int, void *, int,
+ void *, int);
+
+extern int i2o_event_register(struct i2o_controller *, u32, u32, u32, u32);
extern int i2o_event_ack(struct i2o_controller *, u32 *);
extern void i2o_report_status(const char *, const char *, u32 *);
/*
* Executive Class
- */
+ */
#define I2O_CMD_ADAPTER_ASSIGN 0xB3
#define I2O_CMD_ADAPTER_READ 0xB2
#define I2O_CMD_ADAPTER_RELEASE 0xB5
#define I2O_CLAIM_MANAGEMENT 0x02000000
#define I2O_CLAIM_AUTHORIZED 0x03000000
#define I2O_CLAIM_SECONDARY 0x04000000
-
+
/* Message header defines for VersionOffset */
#define I2OVER15 0x0001
#define I2OVER20 0x0002
#define PCI_DEVICE_ID_INTEL_82801BA_9 0x244b
#define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c
#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e
+#define PCI_DEVICE_ID_INTEL_82801CA_0 0x2480
+#define PCI_DEVICE_ID_INTEL_82801CA_2 0x2482
+#define PCI_DEVICE_ID_INTEL_82801CA_3 0x2483
+#define PCI_DEVICE_ID_INTEL_82801CA_4 0x2484
+#define PCI_DEVICE_ID_INTEL_82801CA_5 0x2485
+#define PCI_DEVICE_ID_INTEL_82801CA_6 0x2486
+#define PCI_DEVICE_ID_INTEL_82801CA_7 0x2487
+#define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a
+#define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b
+#define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c
#define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120
#define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121
#define PCI_DEVICE_ID_INTEL_82810_MC3 0x7122
#define SONYPI_EVENT_FNKEY_S 29
#define SONYPI_EVENT_FNKEY_B 30
#define SONYPI_EVENT_BLUETOOTH_PRESSED 31
-#define SONYPI_EVENT_PKEY_P1 32
-#define SONYPI_EVENT_PKEY_P2 33
-#define SONYPI_EVENT_PKEY_P3 34
+#define SONYPI_EVENT_PKEY_P1 32
+#define SONYPI_EVENT_PKEY_P2 33
+#define SONYPI_EVENT_PKEY_P3 34
+#define SONYPI_EVENT_BACK_PRESSED 35
+#define SONYPI_EVENT_LID_CLOSED 36
+#define SONYPI_EVENT_LID_OPENED 37
/* brightness etc. ioctls */
#define write_unlock_irqrestore(lock, flags) do { write_unlock(lock); local_irq_restore(flags); } while (0)
#define write_unlock_irq(lock) do { write_unlock(lock); local_irq_enable(); } while (0)
#define write_unlock_bh(lock) do { write_unlock(lock); local_bh_enable(); } while (0)
+#define spin_trylock_bh(lock) ({ int __r; local_bh_disable();\
+ __r = spin_trylock(lock); \
+ if (!__r) local_bh_enable(); \
+ __r; })
#ifdef CONFIG_SMP
#include <asm/spinlock.h>
#define UDF_PREALLOCATE
#define UDF_DEFAULT_PREALLOC_BLOCKS 8
-#define UDFFS_DATE "2001/06/13"
-#define UDFFS_VERSION "0.9.4.1"
+#define UDFFS_DATE "2001/10/10"
+#define UDFFS_VERSION "0.9.5"
#if !defined(UDFFS_RW)
#if !defined(_LINUX_UDF_FS_SB_H)
#define _LINUX_UDF_FS_SB_H
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
#pragma pack(1)
#define UDF_MAX_BLOCK_LOADED 8
__u16 s_partition;
/* Sector headers */
- __u32 s_session;
+ __s32 s_session;
__u32 s_anchor[4];
__u32 s_lastblock;
{
__u32 x,y; /* Offsets into image */
__u32 width, height; /* Area to capture */
- __u16 decimation; /* Decimation divder */
+ __u16 decimation; /* Decimation divider */
__u16 flags; /* Flags for capture */
#define VIDEO_CAPTURE_ODD 0 /* Temporal */
#define VIDEO_CAPTURE_EVEN 1
#define VID_HARDWARE_MEYE 32 /* Sony Vaio MotionEye cameras */
#define VID_HARDWARE_CPIA2 33
-/*
- * Initialiser list
- */
-
-struct video_init
-{
- char *name;
- int (*init)(struct video_init *);
-};
-
#endif
#include <sys/types.h>
#endif
-typedef u_short socket_t;
+#ifdef __arm__
+typedef u_int ioaddr_t;
+#else
typedef u_short ioaddr_t;
+#endif
+
+typedef u_short socket_t;
typedef u_int event_t;
typedef u_char cisdata_t;
typedef u_short page_t;
#ifndef _LINUX_SS_H
#define _LINUX_SS_H
+#include <pcmcia/cs_types.h>
+
/* Definitions for card status flags for GetStatus */
#define SS_WRPROT 0x0001
#define SS_CARDLOCK 0x0002
u_int features;
u_int irq_mask;
u_int map_size;
+ ioaddr_t io_offset;
u_char pci_irq;
struct pci_dev *cb_dev;
struct bus_operations *bus;
u_char map;
u_char flags;
u_short speed;
- u_short start, stop;
+ ioaddr_t start, stop;
} pccard_io_map;
typedef struct pccard_mem_map {
#include <linux/init.h>
#include <linux/unistd.h>
#include <linux/signal.h>
+#include <linux/completion.h>
static DECLARE_TASK_QUEUE(tq_context);
static DECLARE_WAIT_QUEUE_HEAD(context_task_wq);
return ret;
}
-static int context_thread(void *dummy)
+static int context_thread(void *startup)
{
struct task_struct *curtask = current;
DECLARE_WAITQUEUE(wait, curtask);
recalc_sigpending(curtask);
spin_unlock_irq(&curtask->sigmask_lock);
+ complete((struct completion *)startup);
+
/* Install a handler so SIGCLD is delivered */
sa.sa.sa_handler = SIG_IGN;
sa.sa.sa_flags = 0;
int start_context_thread(void)
{
- kernel_thread(context_thread, NULL, CLONE_FS | CLONE_FILES);
+ static struct completion startup __initdata = COMPLETION_INITIALIZER(startup);
+
+ kernel_thread(context_thread, &startup, CLONE_FS | CLONE_FILES);
+ wait_for_completion(&startup);
return 0;
}
EXPORT_SYMBOL(posix_test_lock);
EXPORT_SYMBOL(posix_block_lock);
EXPORT_SYMBOL(posix_unblock_lock);
+EXPORT_SYMBOL(posix_locks_deadlock);
EXPORT_SYMBOL(locks_mandatory_area);
EXPORT_SYMBOL(dput);
EXPORT_SYMBOL(have_submounts);
#include <linux/types.h>
#include <linux/string.h>
#include <linux/ctype.h>
+#include <linux/kernel.h>
#include <asm/div64.h>
int num = 0;
int qualifier;
int base;
- unsigned int field_width;
+ int field_width = -1;
int is_sign = 0;
- for (; *fmt; fmt++) {
+ while(*fmt && *str) {
/* skip any white space in format */
+ /* white space in format matchs any amount of
+ * white space, including none, in the input.
+ */
if (isspace(*fmt)) {
- continue;
+ while (isspace(*fmt))
+ ++fmt;
+ while (isspace(*str))
+ ++str;
}
/* anything that is not a conversion must match exactly */
- if (*fmt != '%') {
+ if (*fmt != '%' && *fmt) {
if (*fmt++ != *str++)
- return num;
+ break;
continue;
}
+
+ if (!*fmt)
+ break;
++fmt;
/* skip this conversion.
* advance both strings to next white space
*/
if (*fmt == '*') {
- while (!isspace(*fmt))
+ while (!isspace(*fmt) && *fmt)
fmt++;
- while(!isspace(*str))
+ while (!isspace(*str) && *str)
str++;
continue;
}
/* get field width */
- field_width = 0xffffffffUL;
if (isdigit(*fmt))
field_width = skip_atoi(&fmt);
base = 10;
is_sign = 0;
- switch(*fmt) {
+ if (!*fmt || !*str)
+ break;
+
+ switch(*fmt++) {
case 'c':
{
char *s = (char *) va_arg(args,char*);
+ if (field_width == -1)
+ field_width = 1;
do {
*s++ = *str++;
- } while(field_width-- > 0);
+ } while(field_width-- > 0 && *str);
num++;
}
continue;
case 's':
{
char *s = (char *) va_arg(args, char *);
+ if(field_width == -1)
+ field_width = INT_MAX;
/* first, skip leading white space in buffer */
while (isspace(*str))
str++;
/* now copy until next white space */
- while (!isspace(*str) && field_width--) {
+ while (*str && !isspace(*str) && field_width--) {
*s++ = *str++;
}
*s = '\0';
while (isspace(*str))
str++;
+ if (!*str || !isdigit(*str))
+ break;
+
switch(qualifier) {
case 'h':
if (is_sign) {
static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
static int page_cache_read(struct file * file, unsigned long offset)
{
- struct inode *inode = file->f_dentry->d_inode;
- struct address_space *mapping = inode->i_mapping;
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
struct page **hash = page_hash(mapping, offset);
struct page *page;
{
int error;
struct file *file = area->vm_file;
- struct inode *inode = file->f_dentry->d_inode;
- struct address_space *mapping = inode->i_mapping;
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+ struct inode *inode = mapping->host;
struct page *page, **hash, *old_page;
unsigned long size, pgoff;
int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+ struct inode *inode = mapping->host;
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
- if (!inode->i_mapping->a_ops->writepage)
+ if (!mapping->a_ops->writepage)
return -EINVAL;
}
- if (!inode->i_sb || !S_ISREG(inode->i_mode))
- return -EACCES;
- if (!inode->i_mapping->a_ops->readpage)
+ if (!mapping->a_ops->readpage)
return -ENOEXEC;
UPDATE_ATIME(inode);
vma->vm_ops = &generic_file_vm_ops;
*/
/* This is used by platforms which might be able to set the ipconfig
- * variabled using firmware environment vars. If this is set, it will
+ * variables using firmware environment vars. If this is set, it will
* ignore such firmware variables.
*/
int ic_set_manually __initdata = 0; /* IPconfig parameters set manually */
/*
* We give RPC the same get_free_pages priority as NFS
*/
-#define GFP_RPC GFP_NFS
+#define GFP_RPC GFP_NOFS
static void __rpc_default_timer(struct rpc_task *task);
static void rpciod_killall(void);
* for readahead):
*
* sync user requests: GFP_KERNEL
- * async requests: GFP_RPC (== GFP_NFS)
+ * async requests: GFP_RPC (== GFP_NOFS)
* swap requests: GFP_ATOMIC (or new GFP_SWAPPER)
*/
void *
strcpy(current->comm, "rpciod");
- current->flags |= PF_MEMALLOC;
-
dprintk("RPC: rpciod starting (pid %d)\n", rpciod_pid);
while (rpciod_users) {
if (signalled()) {
rpc_proc_exit();
}
#endif
+MODULE_LICENSE("GPL");