diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Mon Jan 13 10:18:06 2003 +++ b/CREDITS Mon Jan 13 10:18:06 2003 @@ -2884,8 +2884,7 @@ S: Australia N: Stephen Smalley -E: sds@tislabs.com -E: ssmalley@nai.com +E: sds@epoch.ncsc.mil D: portions of the Linux Security Module (LSM) framework and security modules N: Chris Smith diff -Nru a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/arm/00-INDEX Mon Jan 13 10:18:07 2003 @@ -0,0 +1,20 @@ +00-INDEX + - this file +Booting + - requirements for booting +Interrupts + - ARM Interrupt subsystem documentation +Netwinder + - Netwinder specific documentation +README + - General ARM documentation +SA1100 + - SA1100 documentation +XScale + - XScale documentation +empeg + - Empeg documentation +mem_alignment + - alignment abort handler documentation +nwfpe + - NWFPE floating point emulator documentation diff -Nru a/Documentation/arm/Booting b/Documentation/arm/Booting --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/arm/Booting Mon Jan 13 10:18:07 2003 @@ -0,0 +1,137 @@ + Booting ARM Linux + ================= + +Author: Russell King +Date : 18 May 2002 + +The following documentation is relevant to 2.4.18-rmk6 and beyond. + +In order to boot ARM Linux, you require a boot loader, which is a small +program that runs before the main kernel. The boot loader is expected +to initialise various devices, and eventually call the Linux kernel, +passing information to the kernel. + +Essentially, the boot loader should provide (as a minimum) the +following: + +1. Setup and initialise the RAM. +2. Initialise one serial port. +3. Detect the machine type. +4. Setup the kernel tagged list. +5. Call the kernel image. + + +1. Setup and initialise RAM +--------------------------- + +Existing boot loaders: MANDATORY +New boot loaders: MANDATORY + +The boot loader is expected to find and initialise all RAM that the +kernel will use for volatile data storage in the system. It performs +this in a machine dependent manner. (It may use internal algorithms +to automatically locate and size all RAM, or it may use knowledge of +the RAM in the machine, or any other method the boot loader designer +sees fit.) + + +2. Initialise one serial port +----------------------------- + +Existing boot loaders: OPTIONAL, RECOMMENDED +New boot loaders: OPTIONAL, RECOMMENDED + +The boot loader should initialise and enable one serial port on the +target. This allows the kernel serial driver to automatically detect +which serial port it should use for the kernel console (generally +used for debugging purposes, or communication with the target.) + +As an alternative, the boot loader can pass the relevant 'console=' +option to the kernel via the tagged lists specifing the port, and +serial format options as described in + + linux/Documentation/kernel-parameters.txt. + + +3. Detect the machine type +-------------------------- + +Existing boot loaders: OPTIONAL +New boot loaders: MANDATORY + +The boot loader should detect the machine type its running on by some +method. Whether this is a hard coded value or some algorithm that +looks at the connected hardware is beyond the scope of this document. +The boot loader must ultimately be able to provide a MACH_TYPE_xxx +value to the kernel. (see linux/arch/arm/tools/mach-types). + + +4. Setup the kernel tagged list +------------------------------- + +Existing boot loaders: OPTIONAL, HIGHLY RECOMMENDED +New boot loaders: MANDATORY + +The boot loader must create and initialise the kernel tagged list. +A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE. +The ATAG_CORE tag may or may not be empty. An empty ATAG_CORE tag +has the size field set to '2' (0x00000002). The ATAG_NONE must set +the size field to zero. + +Any number of tags can be placed in the list. It is undefined +whether a repeated tag appends to the information carried by the +previous tag, or whether it replaces the information in its +entirety; some tags behave as the former, others the latter. + +The boot loader must pass at a minimum the size and location of +the system memory, and root filesystem location. Therefore, the +minimum tagged list should look: + + +-----------+ +base -> | ATAG_CORE | | + +-----------+ | + | ATAG_MEM | | increasing address + +-----------+ | + | ATAG_NONE | | + +-----------+ v + +The tagged list should be stored in system RAM. + +The tagged list must be placed in a region of memory where neither +the kernel decompressor nor initrd 'bootp' program will overwrite +it. The recommended placement is in the first 16KiB of RAM. + +5. Calling the kernel image +--------------------------- + +Existing boot loaders: MANDATORY +New boot loaders: MANDATORY + +There are two options for calling the kernel zImage. If the zImage +is stored in flash, and is linked correctly to be run from flash, +then it is legal for the boot loader to call the zImage in flash +directly. + +The zImage may also be placed in system RAM (at any location) and +called there. Note that the kernel uses 16K of RAM below the image +to store page tables. The recommended placement is 32KiB into RAM. + +In either case, the following conditions must be met: + +- CPU register settings + r0 = 0, + r1 = machine type number discovered in (3) above. + r2 = physical address of tagged list in system RAM. + +- CPU mode + All forms of interrupts must be disabled (IRQs and FIQs) + The CPU must be in SVC mode. (A special exception exists for Angel) + +- Caches, MMUs + The MMU must be off. + Instruction cache may be on or off. + Data cache must be off. + +- The boot loader is expected to call the kernel image by jumping + directly to the first instruction of the kernel image. + diff -Nru a/Documentation/arm/SA1100/DMA b/Documentation/arm/SA1100/DMA --- a/Documentation/arm/SA1100/DMA Mon Jan 13 10:18:05 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,248 +0,0 @@ -Support functions for the SA11x0 internal DMA channels -====================================================== - -Nicolas Pitre -Last updated: 2001/07/15 - - -The DMA controller consists of six independent DMA channels. Each channel -can be configured to service any of the serial controllers. Two channels -are required to service a full-duplex serial controller. The DMA -controller is intended to relieve the processor of the interrupt overhead -in servicing these ports with programmed I/ O. - -If desired, any or all peripherals (except the UDC) may be serviced with -programmed I/ O instead of DMA. Each peripheral is capable of requesting -processor service through its own interrupt lines or through a DMA -request. - -A set of functions is provided to support drivers working with DMA buffers -through a generic interface for (wishfully) all DMA usages. Those -functions will take care of buffer queueing and splitting, DMA register -management, interrupt handling, etc. - - -SA11x0 DMA API --------------- - -Here is the description for the DMA API. - - -int sa1100_request_dma( dmach_t *channel, const char *device_id, - dma_device_t device ); - -This function will search for a free DMA channel and returns the channel -number in '*channel'. 'device_id' should point to a string identifying -the DMA usage or device (mainly for /proc). 'device' is the SA11x0 -peripheral's ports. Note that reading from a port and writing to the -same port are actually considered as two different streams requiring -two DMA channels with their own device type. All possible dma_device_t -are defined in include/asm-arm/arch-sa1100/dma.h. If no channel is -available, or if the desired device is already in use by another DMA -channel, then an error code is returned. This function must be called -before any other DMA calls. - - -int sa1100_dma_queue_buffer( dmach_t channel, void *buf_id, - dma_addr_t data, int size ); - -This function enqueue the specified buffer for DMA processing. The buffer -will be transmitted or filled with incoming data depending on the channel -configuration made through sa1100_dma_set_device(). If the queue is -empty, DMA starts immediately on the given buffer. - -Arguments are: - -dmach_t channel: the channel number. -void *buf_id: a buffer identification known by the caller. -dma_addr_t data: the buffer's physical address. -int size: the buffer size in bytes. - -Note here the dma_addr_t which is not the same as the virtual address as -returned by kmalloc() and friends. The DMA controller must be given a -physical address to a buffer which is not cached bye the CPU data cache. -To get such address, the DMA mapping functions (see -Documentation/DMA-mapping.txt) are recommended. The only relevant -functions are pci_alloc_consistent(), pci_map_single() and their unmap -counterparts. The PCI dev argument is NULL of course. - -There is no restriction on the buffer size. The DMA code will split it up -internally to acommodate the DMA controller as needed. If the buffer -can't be enqueued the appropriate error code is returned. - - -int sa1100_dma_set_callback( dmach_t channel, dma_callback_t cb ); - -As soon as the DMa completes with a buffer, a callback function is used to -notify the driver which would have registered one. The callback function -is prototyped as: - -void dma_callback( void *buf_id, int size ); - -The 'buf_id' argument is the buffer identifier as passed to -sa1100_dma_queue_buffer(). The 'size' argument is the number of bytes the -DMA processed (should be the same as the buffer size). - -Note that this callback function is called while in interrupt context. -So it has to be small and efficient while posponing more complex -processing to a bottom-half function or similar. All -restrictions for interrupt handlers still apply. - - -int sa1100_dma_get_current( dmach_t channel, void **buf_id, - dma_addr_t *addr ); - -This returns the buffer ID and the DMA address pointer within the buffer -currently being processed. If no such buffer is currently processed, an -error code is returned. This is useful for mmap()'ed buffers like in -audio drivers. - - -int sa1100_dma_stop( dmach_t channel ); - -This call stops any DMA transfer on the given channel. - - -int sa1100_dma_resume( dmach_t channel ); - -This call resumes a DMA transfer which would have been stopped through -sa1100_dma_stop(). - - -int sa1100_dma_flush_all( dmach_t channel ); - -This completely flushes all queued buffers and on-going DMA transfers on a -given channel. The next enqueued buffer following this call will be -processed right away. - - -int sa1100_dma_set_spin( dmach_t channel, dma_addr_t addr, int size ); - -Because there is at least one device out there that uses its receive -signal for its transmit clock reference, we need a mecanism to make the -DMA "spin" on a certain buffer for when there is no more actual buffer to -process. The 'addr' argument is the physical memory address to use, and -the 'size' argument determines the spin DMA chunk. This size can't be -larger than 8191 (if so, it is clamped to 4096). When the size is 0, -the spin function is turned off. - -When activated, DMA will "spin" until there is any buffer in the queue. -The current DMA chunk will terminate before a newly queued buffer is -processed. The spin buffer will only be reused when there is no more -acctual buffer to process. - -It is important not to choose a too small 'size' value since it will -greatly increase the interrupt load required to restart the spin. Since -this feature will typically be used on transmit DMAs, and because a buffer -full of zeros is probably the best thing to spin out, the 'addr' argument -may well be used with FLUSH_BASE_PHYS for which no allocation nor memory -bus request are needed. - -The spinning DMA is affected by sa1100_dma_stop() and sa1100_dma_resume() -but not bu sa1100_dma_flush_all(). - - -void sa1100_free_dma( dmach_t channel ); - -This clears all activities on a given DMA channel and releases it for -future requests. - - -Buffer allocation ------------------ - -Like mentionned above, it is the driver's responsibility to allocate, free -and keep track of buffer space with dma_addr_t type addresses. However the -driver must not change the state of any buffer after it has been sent to -sa1100-dma_queue_buffer(). When that function has been called, the buffer -becomes the DMA's ownership until one of these events occur: - -- The callback function is called by the DMA code with a buffer ID to - indicate that DMA processing terminated on that buffer. Then the - driver owns the buffer again. -- The sa1100-dma_flush_all() function is called by the driver at which - point *all* queued buffers are owned by the driver again. -- The sa1100-free_dma() does the same as sa1100-dma_flush_all(). - -This doesn't mean that you can't change the content of a queued buffer in -conjonction with the usage of pci_map_consistent() and -sa1100_dma_get_current()... but then you must be sure you know what you're -doing (this doesn't work with pci_map_single()). - - -Examples --------- - -A real example of audio ring buffers is implemented in the -drivers/sound/sa1100-audio.c driver. The SA1110 USB client and the -SA11x0 FIR drivers are also using this interface to implement packetized -DMA. - -A transmit DMA for network packets could look like this (largely simplified): - -struct sk_buff *tx_ring_skb[RING_SIZE]; -dma_addr_t tx_ring_dma[RING_SIZE]; -int cur_tx; -... - -transmit function: - - tx_ring_skb[cur_tx] = skb; - tx_ring_dma[cur_tx] = pci_map_single(NULL, skb->data, skb->len, - PCI_DMA_TODEVICE); - sa1100_dma_queue_buffer(channel, (void*)cur_tx, - tx_ring_dma[cur_tx], skb->len); - cur_tx++; cur_tx %= RING_SIZE; - ... - -and the callback function: - -void tx_done_callback( void *buf_id, int size ) { - int done_tx = (int) buf_id; - struct sk_buff *skb = tx_ring_skb[done_tx]; - pci_unmap_single(NULL, tx_ring_dma[done_tx], skb->len, - PCI_DMA_TODEVICE); - stats.tx_packets++; - stats.tx_bytes += size; - dev_kfree_skb_irq(skb); - tx_ring_skb[done_tx] = NULL; -} - - -For drivers expecting variable length packets i.e. USB client, it is -necessary to register the appropriate IRQ to be notified when the receiver -is idle, the packet is complete, etc. We could use one buffer at a time -with its ID being the virtual address of the buffer. - -Then the sequence: - - /* be sure DMA won't continue under our feet */ - sa1100_dma_stop(channel); - /* get the actual DMA length */ - sa1100_get_current(channel, &data, &dma_ptr); - /* acquire ownership for the buffer */ - sa1100_dma_flush_all(channel); - /* unmap the DMA buffer (actually doing cache coherency on ARM) */ - pci_unmap_single (NULL, dma_addr, MAX_PKT_SIZE, PCI_DMA_FROMDEVICE); - /* get remaining bytes from the fifo */ - ptr = data + dma_ptr - dma_addr; - while (fifo_not_empty) - *ptr++ = get_byte_from_fifo; - /* feed another free buffer for the next packet */ - dma_addr2 = pci_map_single(NULL, data2, MAX_PKT_SIZE, - PCI_DMA_FROMDEVICE); - sa1100_dma_queue_buffer(channel, data2, dma_addr2, MAX_PKT_SIZE); - /* process the current packet */ - ... - -might do the trick. This looks a bit ugly but that's a starting point for -improvements. - - -TODO ----- - -- Create kernel-doc comments in the source to document the API and - let the documentation be generated automatically. - - diff -Nru a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt --- a/Documentation/driver-model/binding.txt Mon Jan 13 10:18:06 2003 +++ b/Documentation/driver-model/binding.txt Mon Jan 13 10:18:06 2003 @@ -60,7 +60,7 @@ driver's list of devices. -driverfs +sysfs ~~~~~~~~ A symlink is created in the bus's 'devices' directory that points to @@ -71,7 +71,7 @@ A directory for the device is created in the class's directory. A symlink is created in that directory that points to the device's -physical location in the driverfs tree. +physical location in the sysfs tree. A symlink can be created (though this isn't done yet) in the device's physical directory to either its class directory, or the class's diff -Nru a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt --- a/Documentation/driver-model/bus.txt Mon Jan 13 10:18:06 2003 +++ b/Documentation/driver-model/bus.txt Mon Jan 13 10:18:06 2003 @@ -131,7 +131,7 @@ lock is not held when calling the callback. -driverfs +sysfs ~~~~~~~~ There is a top-level directory named 'bus'. @@ -184,7 +184,7 @@ static bus_attribute bus_attr_debug; This can then be used to add and remove the attribute from the bus's -driverfs directory using: +sysfs directory using: int bus_create_file(struct bus_type *, struct bus_attribute *); void bus_remove_file(struct bus_type *, struct bus_attribute *); diff -Nru a/Documentation/driver-model/class.txt b/Documentation/driver-model/class.txt --- a/Documentation/driver-model/class.txt Mon Jan 13 10:18:05 2003 +++ b/Documentation/driver-model/class.txt Mon Jan 13 10:18:05 2003 @@ -91,9 +91,9 @@ the struct device_driver::devclass field. -driverfs directory structure +sysfs directory structure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There is a top-level driverfs directory named 'class'. +There is a top-level sysfs directory named 'class'. Each class gets a directory in the class directory, along with two default subdirectories: @@ -143,13 +143,13 @@ static devclass_attribute devclass_attr_debug; The bus driver can add and remove the attribute from the class's -driverfs directory using: +sysfs directory using: int devclass_create_file(struct device_class *, struct devclass_attribute *); void devclass_remove_file(struct device_class *, struct devclass_attribute *); In the example above, the file will be named 'debug' in placed in the -class's directory in driverfs. +class's directory in sysfs. Interfaces diff -Nru a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt --- a/Documentation/driver-model/device.txt Mon Jan 13 10:18:06 2003 +++ b/Documentation/driver-model/device.txt Mon Jan 13 10:18:06 2003 @@ -64,7 +64,7 @@ bus: Pointer to struct bus_type that device belongs to. -dir: Device's driverfs directory. +dir: Device's sysfs directory. driver: Pointer to struct device_driver that controls the device. @@ -125,8 +125,8 @@ Attributes of devices can be exported via drivers using a simple procfs-like interface. -Please see Documentation/filesystems/driverfs.txt for more information -on how driverfs works. +Please see Documentation/filesystems/sysfs.txt for more information +on how sysfs works. Attributes are declared using a macro called DEVICE_ATTR: diff -Nru a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt --- a/Documentation/driver-model/driver.txt Mon Jan 13 10:18:06 2003 +++ b/Documentation/driver-model/driver.txt Mon Jan 13 10:18:06 2003 @@ -147,10 +147,10 @@ accesses it. -driverfs +sysfs ~~~~~~~~ -When a driver is registered, a driverfs directory is created in its +When a driver is registered, a sysfs directory is created in its bus's directory. In this directory, the driver can export an interface to userspace to control operation of the driver on a global basis; e.g. toggling debugging output in the driver. @@ -268,7 +268,7 @@ ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off); }; -Device drivers can export attributes via their driverfs directories. +Device drivers can export attributes via their sysfs directories. Drivers can declare attributes using a DRIVER_ATTR macro that works identically to the DEVICE_ATTR macro. diff -Nru a/Documentation/driver-model/interface.txt b/Documentation/driver-model/interface.txt --- a/Documentation/driver-model/interface.txt Mon Jan 13 10:18:06 2003 +++ b/Documentation/driver-model/interface.txt Mon Jan 13 10:18:06 2003 @@ -81,7 +81,7 @@ Devices are enumerated within the interface. This happens in interface_add_data() and the enumerated value is stored in the struct intf_data for that device. -driverfs +sysfs ~~~~~~~~ Each interface is given a directory in the directory of the device class it belongs to: diff -Nru a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt --- a/Documentation/driver-model/overview.txt Mon Jan 13 10:18:05 2003 +++ b/Documentation/driver-model/overview.txt Mon Jan 13 10:18:05 2003 @@ -80,17 +80,17 @@ By virtue of having a complete hierarchical view of all the devices in the system, exporting a complete hierarchical view to userspace becomes relatively easy. This has been accomplished by implementing a special purpose virtual -file system named driverfs. It is hence possible for the user to mount the -whole driverfs filesystem anywhere in userspace. +file system named sysfs. It is hence possible for the user to mount the +whole sysfs filesystem anywhere in userspace. This can be done permanently by providing the following entry into the /etc/fstab (under the provision that the mount point does exist, of course): -none /devices driverfs defaults 0 0 +none /devices sysfs defaults 0 0 Or by hand on the command line: -~: mount -t driverfs none /devices +~: mount -t sysfs none /devices Whenever a device is inserted into the tree, a directory is created for it. This directory may be populated at each layer of discovery - the global layer, @@ -108,7 +108,7 @@ A device-specific driver may also export files in its directory to expose device-specific data or tunable interfaces. -More information about the driverfs directory layout can be found in +More information about the sysfs directory layout can be found in the other documents in this directory and in the file -Documentation/filesystems/driverfs.txt. +Documentation/filesystems/sysfs.txt. diff -Nru a/Documentation/driver-model/porting.txt b/Documentation/driver-model/porting.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/driver-model/porting.txt Mon Jan 13 10:18:07 2003 @@ -0,0 +1,445 @@ + +Porting Drivers to the New Driver Model + +Patrick Mochel + +7 January 2003 + + +Overview + +Please refer to Documentation/driver-model/*.txt for definitions of +various driver types and concepts. + +Most of the work of porting devices drivers to the new model happens +at the bus driver layer. This was intentional, to minimize the +negative effect on kernel drivers, and to allow a gradual transition +of bus drivers. + +In a nutshell, the driver model consists of a set of objects that can +be embedded in larger, bus-specific objects. Fields in these generic +objects can replace fields in the bus-specific objects. + +The generic objects must be registered with the driver model core. By +doing so, they will exported via the sysfs filesystem. sysfs can be +mounted by doing + + # mount -t sysfs sysfs /sys + + + +The Process + +Step 0: Read include/linux/device.h for object and function definitions. + +Step 1: Registering the bus driver. + + +- Define a struct bus_type for the bus driver. + +struct bus_type pci_bus_type = { + .name = "pci", +}; + + +- Register the bus type. + This should be done in the initialization function for the bus type, + which is usually the module_init(), or equivalent, function. + +static int __init pci_driver_init(void) +{ + return bus_register(&pci_bus_type); +} + +subsys_initcall(pci_driver_init); + + + The bus type may be unregistered (if the bus driver may be compiled + as a module) by doing: + + bus_unregister(&pci_bus_type); + + +- Export the bus type for others to use. + + Other code may wish to reference the bus type, so declare it in a + shared header file and export the symbol. + +From include/linux/pci.h: + +extern struct bus_type pci_bus_type; + + +From file the above code appears in: + +EXPORT_SYMBOL(pci_bus_type); + + + +- This will cause the bus to show up in /sys/bus/pci/ with two + subdirectories: 'devices' and 'drivers'. + +# tree -d /sys/bus/pci/ +/sys/bus/pci/ +|-- devices +`-- drivers + + + +Step 2: Registering Devices. + +struct device represents a single device. It mainly contains metadata +describing the relationship the device has to other entities. + + +- Embedd a struct device in the bus-specific device type. + + +struct pci_dev { + ... + struct device dev; /* Generic device interface */ + ... +}; + + It is recommended that the generic device not be the first item in + the struct to discourage programmers from doing mindless casts + between the object types. Instead macros, or inline functions, + should be created to convert from the generic object type. + + +#define to_pci_dev(n) container_of(n, struct pci_dev, dev) + +or + +static inline struct pci_dev * to_pci_dev(struct kobject * kobj) +{ + return container_of(n, struct pci_dev, dev); +} + + This allows the compiler to verify type-safety of the operations + that are performed (which is Good). + + +- Initialize the device on registration. + + When devices are discovered or registered with the bus type, the + bus driver should initialize the generic device. The most important + things to initialize are the bus_id, parent, and bus fields. + + The bus_id is an ASCII string that contains the device's address on + the bus. The format of this string is bus-specific. This is + necessary for representing device in sysfs. + + parent is the physical parent of the device. It is important that + the bus driver sets this field correctly. + + The driver model maintains an ordered list of devices that it uses + for power management. This list must be in order to guarantee that + devices are shutdown before their physical parents, and vice versa. + The order of this list is determined by the parent of registered + devices. + + Also, the location of the device's sysfs directory depends on a + device's parent. sysfs exports a directory structure that mirrors + the device hierarchy. Accurately setting the parent guarantees that + sysfs will accurately represent the hierarchy. + + The device's bus field is a pointer to the bus type the device + belongs to. This should be set to the bus_type that was declared + and initialized before. + + Optionally, the bus driver may set the device's name and release + fields. + + The name field is an ASCII string describing the device, like + + "ATI Technologies Inc Radeon QD" + + The release field is a callback that the driver model core calls + when the device has been removed, and all references to it have + been released. More on this in a moment. + + +- Register the device. + + Once the generic device has been initialized, it can be registered + with the driver model core by doing: + + device_register(&dev->dev); + + It can later be unregistered by doing: + + device_unregister(&dev->dev); + + This should happen on buses that support hotpluggable devices. + If a bus driver unregisters a device, it should not immediately free + it. It should instead wait for the driver model core to call the + device's release method, then free the bus-specific object. + (There may be other code that is currently referencing the device + structure, and it would be rude to free the device while that is + happening). + + + When the device is registered, a directory in sysfs is created. + The PCI tree in sysfs looks like: + +/sys/devices/pci0/ +|-- 00:00.0 +|-- 00:01.0 +| `-- 01:00.0 +|-- 00:02.0 +| `-- 02:1f.0 +| `-- 03:00.0 +|-- 00:1e.0 +| `-- 04:04.0 +|-- 00:1f.0 +|-- 00:1f.1 +| |-- ide0 +| | |-- 0.0 +| | `-- 0.1 +| `-- ide1 +| `-- 1.0 +|-- 00:1f.2 +|-- 00:1f.3 +`-- 00:1f.5 + + Also, symlinks are created in the bus's 'devices' directory + that point to the device's directory in the physical hierarchy. + +/sys/bus/pci/devices/ +|-- 00:00.0 -> ../../../devices/pci0/00:00.0 +|-- 00:01.0 -> ../../../devices/pci0/00:01.0 +|-- 00:02.0 -> ../../../devices/pci0/00:02.0 +|-- 00:1e.0 -> ../../../devices/pci0/00:1e.0 +|-- 00:1f.0 -> ../../../devices/pci0/00:1f.0 +|-- 00:1f.1 -> ../../../devices/pci0/00:1f.1 +|-- 00:1f.2 -> ../../../devices/pci0/00:1f.2 +|-- 00:1f.3 -> ../../../devices/pci0/00:1f.3 +|-- 00:1f.5 -> ../../../devices/pci0/00:1f.5 +|-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0 +|-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0 +|-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0 +`-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0 + + + +Step 3: Registering Drivers. + +struct device_driver is a simple driver structure that contains a set +of operations that the driver model core may call. + + +- Embed a struct device_driver in the bus-specific driver. + + Just like with devices, do something like: + +struct pci_driver { + ... + struct device_driver driver; +}; + + +- Initialize the generic driver structure. + + When the driver registers with the bus (e.g. doing pci_register_driver()), + initialize the necessary fields of the driver: the name and bus + fields. + + +- Register the driver. + + After the generic driver has been initialized, call + + driver_register(&drv->driver); + + to register the driver with the core. + + When the driver is unregistered from the bus, unregister it from the + core by doing: + + driver_unregister(&drv->driver); + + Note that this will block until all references to the driver have + gone away. Normally, there will not be any. + + +- Sysfs representation. + + Drivers are exported via sysfs in their bus's 'driver's directory. + For example: + +/sys/bus/pci/drivers/ +|-- 3c59x +|-- Ensoniq AudioPCI +|-- agpgart-amdk7 +|-- e100 +`-- serial + + +Step 4: Define Generic Methods for Drivers. + +struct device_driver defines a set of operations that the driver model +core calls. Most of these operations are probably similar to +operations the bus already defines for drivers, but taking different +parameters. + +It would be difficult and tedious to force every driver on a bus to +simultaneously convert their drivers to generic format. Instead, the +bus driver should define single instances of the generic methods that +forward calls to the bus-specific drivers. For instance: + + +static int pci_device_remove(struct device * dev) +{ + struct pci_dev * pci_dev = to_pci_dev(dev); + struct pci_driver * drv = pci_dev->driver; + + if (drv) { + if (drv->remove) + drv->remove(pci_dev); + pci_dev->driver = NULL; + } + return 0; +} + + +The generic driver should be initialized with these methods before it +is registered. + + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = &pci_bus_type; + drv->driver.probe = pci_device_probe; + drv->driver.resume = pci_device_resume; + drv->driver.suspend = pci_device_suspend; + drv->driver.remove = pci_device_remove; + + /* register with core */ + driver_register(&drv->driver); + + +Ideally, the bus should only initialize the fields if they are not +already set. This allows the drivers to implement their own generic +methods. + + +Step 5: Support generic driver binding. + +The model assumes that a device or driver can be dynamically +registered with the bus at any time. When registration happens, +devices must be bound to a driver, or drivers must be bound to all +devices that it supports. + +Drivers typically contain a list of device IDs that it supports. The +bus driver compares this ID to the ID of devices registered with it. +The format of the device IDs, and the semantics for comparing them are +bus-specific, so the generic model does attempt to generalize them. + +Instead, a bus may supply a method in struct bus_type that does the +comparison: + + int (*match)(struct device * dev, struct device_driver * drv); + +match should return '1' if the driver supports the device, and '0' +otherwise. + +When a device is registered, the bus's list of drivers is iterated +over. bus->match() is called for each one until a match is found. + +When a driver is registered, the bus's list of devices is iterated +over. bus->match() is called for each device that is not already +claimed by a driver. + +When a device is successfully bound to a device, device->driver is +set, the device is added to a per-driver list of devices, and a +symlink is created in the driver's sysfs directory that points to the +device's physical directory: + +/sys/bus/pci/drivers/ +|-- 3c59x +| `-- 00:0b.0 -> ../../../../devices/pci0/00:0b.0 +|-- Ensoniq AudioPCI +|-- agpgart-amdk7 +| `-- 00:00.0 -> ../../../../devices/pci0/00:00.0 +|-- e100 +| `-- 00:0c.0 -> ../../../../devices/pci0/00:0c.0 +`-- serial + + +This driver binding should replace the existing driver binding +mechanism the bus currently uses. + + +Step 6: Supply a hotplug callback. + +Whenever a device is registered with the driver model core, the +userspace program /sbin/hotplug is called to notify userspace. +Users can define actions to perform when a device is inserted or +removed. + +The driver model core passes several arguments to userspace via +environment variables, including + +- ACTION: set to 'add' or 'remove' +- DEVPATH: set to the device's physical path in sysfs. + +A bus driver may also supply additional parameters for userspace to +consume. To do this, a bus must implement the 'hotplug' method in +struct bus_type: + + int (*hotplug) (struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size); + +This is called immediately before /sbin/hotplug is executed. + + +Step 7: Cleaning up the bus driver. + +The generic bus, device, and driver structures provide several fields +that can replace those define privately to the bus driver. + +- Device list. + +struct bus_type contains a list of all devices registered with the bus +type. This includes all devices on all instances of that bus type. +An internal list that the bus uses may be removed, in favor of using +this one. + +The core provides an iterator to access these devices. + +int bus_for_each_dev(struct bus_type * bus, struct device * start, + void * data, int (*fn)(struct device *, void *)); + + +- Driver list. + +struct bus_type also contains a list of all drivers registered with +it. An internal list of drivers that the bus driver maintains may +be removed in favor of using the generic one. + +The drivers may be iterated over, like devices: + +int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, + void * data, int (*fn)(struct device_driver *, void *)); + + +Please see drivers/base/bus.c for more information. + + +- rwsem + +struct bus_type contains an rwsem that protects all core accesses to +the device and driver lists. This can be used by the bus driver +internally, and should be used when accessing the device or driver +lists the bus maintains. + + +- Device and driver fields. + +Some of the fields in struct device and struct device_driver duplicate +fields in the bus-specific representations of these objects. Feel free +to remove the bus-specific ones and favor the generic ones. Note +though, that this will likely mean fixing up all the drivers that +reference the bus-specific fields (though those should all be 1-line +changes). + diff -Nru a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt --- a/Documentation/filesystems/sysfs.txt Mon Jan 13 10:18:05 2003 +++ b/Documentation/filesystems/sysfs.txt Mon Jan 13 10:18:05 2003 @@ -3,10 +3,10 @@ Patrick Mochel -17 October 2002 +10 January 2003 -Note (17 Oct 2002): the name has just been changed from driverfs to +Note (17 Oct 2002): the name has just been changed from sysfs to sysfs. Updates to the documentation will come soon; after the conversion to use it is completely finished. @@ -14,216 +14,274 @@ What it is: ~~~~~~~~~~~ -driverfs is a ram-based filesystem. It was created by copying -ramfs/inode.c to driverfs/inode.c and doing a little search-and-replace. -driverfs is a means to export kernel data structures, their -attributes, and the linkages between them to userspace. +sysfs is a ram-based filesystem initially based on ramfs. It provides +a means to export kernel data structures, their attributes, and the +linkages between them to userspace. -driverfs provides a unified interface for exporting attributes to -userspace. Currently, this interface is available only to device and -bus drivers. +sysfs is tied inherently to the kobject infrastructure. Please read +Documentation/kobject.txt for more information concerning the kobject +interface. -Using driverfs -~~~~~~~~~~~~~~ -driverfs is always compiled in. You can access it by doing something like: +Using sysfs +~~~~~~~~~~~ - mount -t driverfs driverfs /devices +sysfs is always compiled in. You can access it by doing: + mount -t sysfs sysfs /sys -Top Level Directory Layout -~~~~~~~~~~~~~~~~~~~~~~~~~~ -The driverfs directory arrangement exposes the relationship of kernel -data structures. -The top level driverfs diretory looks like: +Directory Creation +~~~~~~~~~~~~~~~~~~ -bus/ -root/ +For every kobject that is registered with the system, a directory is +created for it in sysfs. That directory is created as a subdirectory +of the kobject's parent, expressing internal object hierarchies to +userspace. Top-level directories in sysfs represent the common +ancestors of object hierarchies; i.e. the subsystems the objects +belong to. + +Sysfs internally stores the kobject that owns the directory in the +->d_fsdata pointer of the directory's dentry. This allows sysfs to do +reference counting directly on the kobject when the file is opened and +closed. -root/ contains a filesystem representation of the device tree. It maps -directly to the internal kernel device tree, which is a hierarchy of -struct device. -bus/ contains flat directory layout of the various bus types in the -kernel. Each bus's directory contains two subdirectories: +Attributes +~~~~~~~~~~ - devices/ - drivers/ +Attributes can be exported for kobjects in the form of regular files in +the filesystem. Sysfs forwards file I/O operations to methods defined +for the attributes, providing a means to read and write kernel +attributes. + +Attributes should be ASCII text files, preferably with only one value +per file. It is noted that it may not be efficient to contain only +value per file, so it is socially acceptable to express an array of +values of the same type. + +Mixing types, expressing mulitple lines of data, and doing fancy +formatting of data is heavily frowned upon. Doing these things may get +you publically humiliated and your code rewritten without notice. -devices/ contains symlinks for each device discovered in the system -that point to the device's directory under root/. -drivers/ contains a directory for each device driver that is loaded -for devices on that particular bus (this assmumes that drivers do not -span multiple bus types). +An attriubte definition is simply: +struct attribute { + char * name; + mode_t mode; +}; -More information can device-model specific features can be found in -Documentation/device-model/. +int sysfs_create_file(struct kobject * kobj, struct attribute * attr); +void sysfs_remove_file(struct kobject * kobj, struct attribute * attr); -Directory Contents -~~~~~~~~~~~~~~~~~~ -Each object that is represented in driverfs gets a directory, rather -than a file, to make it simple to export attributes of that object. -Attributes are exported via ASCII text files. The programming -interface is discussed below. -Instead of having monolithic files that are difficult to parse, all -files are intended to export one attribute. The name of the attribute -is the name of the file. The value of the attribute are the contents -of the file. +A bare attribute contains no means to read or write the value of the +attribute. Subsystems are encouraged to define their own attribute +structure and wrapper functions for adding and removing attributes for +a specific object type. -There should be few, if any, exceptions to this rule. You should not -violate it, for fear of public humilation. +For example, the driver model defines struct device_attribute like: +struct device_attribute { + struct attribute attr; + ssize_t (*show)(struct device * dev, char * buf); + ssize_t (*store)(struct device * dev, const char * buf); +}; -The Two-Tier Model -~~~~~~~~~~~~~~~~~~ +int device_create_file(struct device *, struct device_attribute *); +void device_remove_file(struct device *, struct device_attribute *); -driverfs is a very simple, low-level interface. In order for kernel -objects to use it, there must be an intermediate layer in place for -each object type. +It also defines this helper for defining device attributes: -All calls in driverfs are intended to be as type-safe as possible. -In order to extend driverfs to support multiple data types, a layer of -abstraction was required. This intermediate layer converts between the -generic calls and data structures of the driverfs core to the -subsystem-specific objects and calls. +#define DEVICE_ATTR(_name,_mode,_show,_store) \ +struct device_attribute dev_attr_##_name = { \ + .attr = {.name = __stringify(_name) , .mode = _mode }, \ + .show = _show, \ + .store = _store, \ +}; +For example, declaring -The Subsystem Interface -~~~~~~~~~~~~~~~~~~~~~~~ +static DEVICE_ATTR(foo,0644,show_foo,store_foo); -The subsystems bear the responsibility of implementing driverfs -extensions for the objects they control. Fortunately, it's intended to -be really easy to do so. +is equivalent to doing: -It's divided into three sections: directories, files, and operations. +static struct device_attribute dev_attr_foo = { + .attr = { + .name = "foo", + .mode = 0644, + }, + .show = show_foo, + .store = store_foo, +}; -Directories -~~~~~~~~~~~ +Subsystem-Specific Callbacks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -struct driver_dir_entry { - char * name; - struct dentry * dentry; - mode_t mode; - struct driverfs_ops * ops; +When a subsystem defines a new attribute type, they must implement a +set of sysfs operations for forwarding read and write calls to the +show and store methods of the attribute owners. + +struct sysfs_ops { + ssize_t (*show)(struct kobject *, struct attribute *,char *); + ssize_t (*store)(struct kobject *,struct attribute *,const char *); }; +[ Subsystems should have already defined a struct kobj_type as a +descriptor for this type, which is where the sysfs_ops pointer is +stored. See the kobject documentation for more information. ] -int -driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *); +When a file is read or written, sysfs calls the appropriate method +for the type. The method then translates the generic struct kobject +and struct attribute pointers to the appropriate pointer types, and +calls the associated methods. -void -driverfs_remove_dir(struct driver_dir_entry * entry); -The directory structure should be statically allocated, and reside in -a subsystem-specific data structure: +To illustrate: -struct device { - ... - struct driver_dir_entry dir; -}; +#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr) +#define to_dev(d) container_of(d, struct device, kobj) -The subsystem is responsible for initializing the name, mode, and ops -fields of the directory entry. (More on struct driverfs_ops later) +static ssize_t +dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) +{ + struct device_attribute * dev_attr = to_dev_attr(attr); + struct device * dev = to_dev(kobj); + ssize_t ret = 0; + if (dev_attr->show) + ret = dev_attr->show(dev,buf); + return ret; +} -Files -~~~~~ -struct attribute { - char * name; - mode_t mode; -}; +Reading/Writing Attribute Data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -int -driverfs_create_file(struct attribute * attr, struct driver_dir_entry * parent); +To read or write attributes, show() or store() methods must be +specified when declaring the attribute. The method types should be as +simple as those defined for device attributes: -void -driverfs_remove_file(struct driver_dir_entry *, const char * name); + ssize_t (*show)(struct device * dev, char * buf); + ssize_t (*store)(struct device * dev, const char * buf); +IOW, they should take only an object and a buffer as parameters. -The attribute structure is a simple, common token that the driverfs -core handles. It has little use on its own outside of the -core. Objects cannot use a plain struct attribute to export -attributes, since there are no callbacks for reading and writing data. -Therefore, the subsystem is required to define a data structure that -encapsulates the attribute structure, and provides type-safe callbacks -for reading and writing data. +sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the +method. Sysfs will call the method exactly once for each read or +write. This forces the following behavior on the method +implementations: -An example looks like this: +- On read(2), the show() method should fill the entire buffer. + Recall that an attribute should only be exporting one value, or an + array of similar values, so this shouldn't be that expensive. -struct device_attribute { - struct attribute attr; - ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off); - ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off); -}; + This allows userspace to do partial reads and seeks arbitrarily over + the entire file at will. +- On write(2), sysfs expects the entire buffer to be passed during the + first write. Sysfs then passes the entire buffer to the store() + method. + + When writing sysfs files, userspace processes should first read the + entire file, modify the values it wishes to change, then write the + entire buffer back. -Note that there is a struct attribute embedded in the structure. In -order to relieve pain in declaring attributes, the subsystem should -also define a macro, like: + Attribute method implementations should operate on an identical + buffer when reading and writing values. -#define DEVICE_ATTR(_name,_mode,_show,_store) \ -struct device_attribute dev_attr_##_name = { \ - .attr = {.name = __stringify(_name) , .mode = _mode }, \ - .show = _show, \ - .store = _store, \ -}; +Other notes: -This hides the initialization of the embedded struct, and in general, -the internals of each structure. It yields a structure by the name of -dev_attr_. +- The buffer will always be PAGE_SIZE bytes in length. On i386, this + is 4096. -In order for objects to create files, the subsystem should create -wrapper functions, like this: +- show() methods should return the number of bytes printed into the + buffer. This is the return value of snprintf(). -int device_create_file(struct device *device, struct device_attribute * entry); -void device_remove_file(struct device * dev, struct device_attribute * attr); +- show() should always use snprintf(). -..and forward the call on to the driverfs functions. +- store() should return the number of bytes used from the buffer. This + can be done using strlen(). -Note that there is no unique information in the attribute structures, -so the same structure can be used to describe files of several -different object instances. +- show() or store() can always return errors. If a bad value comes + through, be sure and return an error. +- The object passed to the methods will be pinned in memory via sysfs + referencing counting its embedded object. However, the physical + entity (e.g. device) the object represents may not be present. Be + sure to have a way to check this, if necessary. -Operations -~~~~~~~~~~ -struct driverfs_ops { - int (*open)(struct driver_dir_entry *); - int (*close)(struct driver_dir_entry *); - ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t); - ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t); -}; +A very simple (and naive) implementation of a device attribute is: +static ssize_t show_name(struct device * dev, char * buf) +{ + return sprintf(buf,"%s\n",dev->name); +} -Subsystems are required to implement this set of callbacks. Their -purpose is to translate the generic data structures into the specific -objects, and operate on them. This can be done by defining macros like -this: +static ssize_t store_name(struct device * dev, const char * buf) +{ + sscanf(buf,"%20s",dev->name); + return strlen(buf); +} -#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr) +static DEVICE_ATTR(name,S_IRUGO,show_name,store_name); + + +(Note that the real implementation doesn't allow userspace to set the +name for a device). + + +Top Level Directory Layout +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The sysfs directory arrangement exposes the relationship of kernel +data structures. + +The top level sysfs diretory looks like: + +block/ +bus/ +class/ +devices/ +firmware/ +net/ + +devices/ contains a filesystem representation of the device tree. It maps +directly to the internal kernel device tree, which is a hierarchy of +struct device. + +bus/ contains flat directory layout of the various bus types in the +kernel. Each bus's directory contains two subdirectories: -#define to_device(d) container_of(d, struct device, dir) + devices/ + drivers/ +devices/ contains symlinks for each device discovered in the system +that point to the device's directory under root/. + +drivers/ contains a directory for each device driver that is loaded +for devices on that particular bus (this assmumes that drivers do not +span multiple bus types). + + +More information can device-model specific features can be found in +Documentation/device-model/. + + +TODO: Finish this section. -Since the directories are statically allocated in the object, you can -derive the pointer to the object that owns the file. Ditto for the -attribute structures. Current Interfaces ~~~~~~~~~~~~~~~~~~ -The following interface layers currently exist in driverfs: +The following interface layers currently exist in sysfs: - devices (include/linux/device.h) @@ -232,8 +290,8 @@ struct device_attribute { struct attribute attr; - ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off); - ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off); + ssize_t (*show)(struct device * dev, char * buf); + ssize_t (*store)(struct device * dev, const char * buf); }; Declaring: @@ -242,7 +300,7 @@ Creation/Removal: -int device_create_file(struct device *device, struct device_attribute * entry); +int device_create_file(struct device *device, struct device_attribute * attr); void device_remove_file(struct device * dev, struct device_attribute * attr); @@ -252,8 +310,8 @@ struct bus_attribute { struct attribute attr; - ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off); - ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off); + ssize_t (*show)(struct bus_type *, char * buf); + ssize_t (*store)(struct bus_type *, const char * buf); }; Declaring: @@ -273,8 +331,8 @@ struct driver_attribute { struct attribute attr; - ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off); - ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off); + ssize_t (*show)(struct device_driver *, char * buf); + ssize_t (*store)(struct device_driver *, const char * buf); }; Declaring: @@ -286,57 +344,4 @@ int driver_create_file(struct device_driver *, struct driver_attribute *); void driver_remove_file(struct device_driver *, struct driver_attribute *); - -Reading/Writing Data -~~~~~~~~~~~~~~~~~~~~ -The callback functionality is similar to the way procfs works. When a -user performs a read(2) or write(2) on the file, it first calls a -driverfs function. This calls to the subsystem, which then calls to -the object's show() or store() function. - -The buffer pointer, offset, and length should be passed to each -function. The downstream callback should fill the buffer and return -the number of bytes read/written. - - -What driverfs is not: -~~~~~~~~~~~~~~~~~~~~~ -It is not a replacement for either devfs or procfs. - -It does not handle device nodes, like devfs is intended to do. I think -this functionality is possible, but indeed think that integration of -the device nodes and control files should be done. Whether driverfs or -devfs, or something else, is the place to do it, I don't know. - -It is not intended to be a replacement for all of the procfs -functionality. I think that many of the driver files should be moved -out of /proc (and maybe a few other things as well ;). - - - -Limitations: -~~~~~~~~~~~~ -The driverfs functions assume that at most a page is being either read -or written each time. - -There is a race condition that is really, really hard to fix; if not -impossible. There exists a race between a driverfs file being opened -and the object that owns the file going away. During the driverfs -open() callback, the reference count for the owning object needs to be -incremented. - -For drivers, we can put a struct module * owner in struct driver_dir_entry -and do try_inc_mod_count() when we open a file. However, this won't -work for devices, that aren't tied to a module. And, it is still not -guaranteed to solve the race. - -I'm looking into fixing this, but it may not be doable without making -a separate filesystem instance for each object. It's fun stuff. Please -mail me with creative ideas that you know will work. - - -Possible bugs: -~~~~~~~~~~~~~~ -It may not deal with offsets and/or seeks very well, especially if -they cross a page boundary. diff -Nru a/Documentation/rpc-cache.txt b/Documentation/rpc-cache.txt --- a/Documentation/rpc-cache.txt Mon Jan 13 10:18:05 2003 +++ b/Documentation/rpc-cache.txt Mon Jan 13 10:18:05 2003 @@ -148,7 +148,7 @@ added to the channel but instead all looks that do not find a valid entry will fail. This is partly for backward compatability: The previous nfs exports table was deemed to be authoritative and a -failed lookup meant a definate 'no'. +failed lookup meant a definite 'no'. request/response format ----------------------- diff -Nru a/Documentation/vm/locking b/Documentation/vm/locking --- a/Documentation/vm/locking Mon Jan 13 10:18:05 2003 +++ b/Documentation/vm/locking Mon Jan 13 10:18:05 2003 @@ -66,10 +66,9 @@ expand_stack(), it is hard to come up with a destructive scenario without having the vmlist protection in this case. -The page_table_lock nests with the inode i_shared_lock and the kmem cache -c_spinlock spinlocks. This is okay, since code that holds i_shared_lock -never asks for memory, and the kmem code asks for pages after dropping -c_spinlock. The page_table_lock also nests with pagecache_lock and +The page_table_lock nests with the inode i_shared_sem and the kmem cache +c_spinlock spinlocks. This is okay, since the kmem code asks for pages after +dropping c_spinlock. The page_table_lock also nests with pagecache_lock and pagemap_lru_lock spinlocks, and no code asks for memory with these locks held. diff -Nru a/Makefile b/Makefile --- a/Makefile Mon Jan 13 10:18:05 2003 +++ b/Makefile Mon Jan 13 10:18:05 2003 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 56 +SUBLEVEL = 57 EXTRAVERSION = # *DOCUMENTATION* diff -Nru a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c --- a/arch/alpha/mm/init.c Mon Jan 13 10:18:07 2003 +++ b/arch/alpha/mm/init.c Mon Jan 13 10:18:07 2003 @@ -34,7 +34,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; extern void die_if_kernel(char *,struct pt_regs *,long); diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S --- a/arch/alpha/vmlinux.lds.S Mon Jan 13 10:18:06 2003 +++ b/arch/alpha/vmlinux.lds.S Mon Jan 13 10:18:06 2003 @@ -32,6 +32,13 @@ __stop___ksymtab = .; } + /* Kernel symbol table: GPL only */ + __gpl_ksymtab ALIGN(8) : { + __start___gpl_ksymtab = .; + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + } + /* All kernel symbols */ __kallsyms ALIGN(8) : { __start___kallsyms = .; diff -Nru a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S --- a/arch/arm/boot/compressed/head.S Mon Jan 13 10:18:07 2003 +++ b/arch/arm/boot/compressed/head.S Mon Jan 13 10:18:07 2003 @@ -366,9 +366,12 @@ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs mrc p15, 0, r0, c1, c0, 0 @ read control reg - orr r0, r0, #0x1000 @ I-cache enable + orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x0030 - b __common_cache_on + bl __common_cache_on + mov r0, #0 + mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs + mov pc, r12 __arm6_cache_on: mov r12, lr @@ -377,6 +380,11 @@ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 mov r0, #0x30 + bl __common_cache_on + mov r0, #0 + mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 + mov pc, r12 + __common_cache_on: #ifndef DEBUG orr r0, r0, #0x000d @ Write buffer, mmu @@ -385,7 +393,7 @@ mcr p15, 0, r3, c2, c0, 0 @ load page table pointer mcr p15, 0, r1, c3, c0, 0 @ load domain access control mcr p15, 0, r0, c1, c0, 0 @ load control register - mov pc, r12 + mov pc, lr /* * All code following this line is relocatable. It is relocated by @@ -567,11 +575,12 @@ __armv4_cache_flush: bic r1, pc, #31 add r2, r1, #65536 @ 2x the largest dcache size -1: ldr r12, [r1], #32 @ s/w flush D cache +1: ldr r3, [r1], #32 @ s/w flush D cache teq r1, r2 bne 1b - mcr p15, 0, r1, c7, c7, 0 @ flush I cache + mcr p15, 0, r1, c7, c5, 0 @ flush I cache + mcr p15, 0, r1, c7, c6, 0 @ flush D cache mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c --- a/arch/arm/kernel/ecard.c Mon Jan 13 10:18:07 2003 +++ b/arch/arm/kernel/ecard.c Mon Jan 13 10:18:07 2003 @@ -978,6 +978,8 @@ strcpy(ec->dev.name, "fixme!"); ec->dev.parent = NULL; ec->dev.bus = &ecard_bus_type; + ec->dev.dma_mask = &ec->dma_mask; + ec->dma_mask = (u64)0xffffffff; device_register(&ec->dev); diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c --- a/arch/arm/kernel/setup.c Mon Jan 13 10:18:06 2003 +++ b/arch/arm/kernel/setup.c Mon Jan 13 10:18:06 2003 @@ -81,7 +81,7 @@ unsigned long phys_initrd_size __initdata = 0; static struct meminfo meminfo __initdata = { 0, }; -static struct proc_info_item proc_info; +static const char *cpu_name; static const char *machine_name; static char command_line[COMMAND_LINE_SIZE]; @@ -275,7 +275,7 @@ while (1); } - proc_info = *list->info; + cpu_name = list->cpu_name; #ifdef MULTI_CPU processor = *list->proc; @@ -287,9 +287,9 @@ cpu_user = *list->user; #endif - printk("CPU: %s %s revision %d (ARMv%s)\n", - proc_info.manufacturer, proc_info.cpu_name, - (int)processor_id & 15, proc_arch[cpu_architecture()]); + printk("CPU: %s [%08x] revision %d (ARMv%s)\n", + cpu_name, processor_id, (int)processor_id & 15, + proc_arch[cpu_architecture()]); dump_cpu_info(); @@ -723,9 +723,8 @@ { int i; - seq_printf(m, "Processor\t: %s %s rev %d (%s)\n", - proc_info.manufacturer, proc_info.cpu_name, - (int)processor_id & 15, elf_platform); + seq_printf(m, "Processor\t: %s rev %d (%s)\n", + cpu_name, (int)processor_id & 15, elf_platform); seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", loops_per_jiffy / (500000/HZ), diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c --- a/arch/arm/mach-integrator/cpu.c Mon Jan 13 10:18:06 2003 +++ b/arch/arm/mach-integrator/cpu.c Mon Jan 13 10:18:06 2003 @@ -97,18 +97,43 @@ return 0; } -static void do_set_policy(int cpu, struct cpufreq_policy *policy) +static int integrator_set_policy(struct cpufreq_policy *policy) { - struct vco vco = freq_to_vco(policy->max, 1); + unsigned long cpus_allowed; + int cpu = policy->cpu; + struct vco vco; + struct cpufreq_freqs freqs; u_int cm_osc; /* + * Save this threads cpus_allowed mask. + */ + cpus_allowed = current->cpus_allowed; + + /* * Bind to the specified CPU. When this call returns, * we should be running on the right CPU. */ set_cpus_allowed(current, 1 << cpu); BUG_ON(cpu != smp_processor_id()); + /* get current setting */ + cm_osc = __raw_readl(CM_OSC); + vco.od = (cm_osc >> 8) & 7; + vco.vdw = cm_osc & 255; + + freqs.old = vco_to_freq(vco, 1); + freqs.new = target_freq; + freqs.cpu = policy->cpu; + + if (freqs.old == freqs.new) { + set_cpus_allowed(current, cpus_allowed); + return 0; + } + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + vco = freq_to_vco(policy->max, 1); + cm_osc = __raw_readl(CM_OSC); cm_osc &= 0xfffff800; cm_osc |= vco.vdw | vco.od << 8; @@ -116,32 +141,14 @@ __raw_writel(0xa05f, CM_LOCK); __raw_writel(cm_osc, CM_OSC); __raw_writel(0, CM_LOCK); -} - -static int integrator_set_policy(struct cpufreq_policy *policy) -{ - unsigned long cpus_allowed; - int cpu; - - /* - * Save this threads cpus_allowed mask. - */ - cpus_allowed = current->cpus_allowed; - - if (policy->cpu == CPUFREQ_ALL_CPUS) { - for (cpu = 0; cpu < NR_CPUS; cpu++) { - if (!cpu_online(cpu)) - continue; - do_set_policy(cpu, policy); - } - } else - do_set_policy(policy->cpu, policy); /* * Restore the CPUs allowed mask. */ set_cpus_allowed(current, cpus_allowed); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + return 0; } @@ -149,8 +156,8 @@ .cpu = 0, .policy = CPUFREQ_POLICY_POWERSAVE, .cpuinfo = { - .max_cpu_freq = 160000, - .min_cpu_freq = 12000, + .max_freq = 160000, + .min_freq = 12000, .transition_latency = CPUFREQ_ETERNAL, }, }; @@ -168,7 +175,7 @@ unsigned long cpus_allowed; int cpu; - policies = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS, + policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS, GFP_KERNEL); if (!policies) { printk(KERN_ERR "CPU: unable to allocate policies structure\n"); diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c --- a/arch/arm/mach-sa1100/cpu-sa1100.c Mon Jan 13 10:18:05 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Mon Jan 13 10:18:05 2003 @@ -183,7 +183,7 @@ freqs.old = cur; freqs.new = policy->max; - freqs.cpu = CPUFREQ_ALL_CPUS; + freqs.cpu = 0; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c Mon Jan 13 10:18:05 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Mon Jan 13 10:18:05 2003 @@ -242,7 +242,7 @@ freqs.old = sa11x0_getspeed(); freqs.new = policy->max; - freqs.cpu = CPUFREQ_ALL_CPUS; + freqs.cpu = 0; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c --- a/arch/arm/mm/consistent.c Mon Jan 13 10:18:07 2003 +++ b/arch/arm/mm/consistent.c Mon Jan 13 10:18:07 2003 @@ -1,48 +1,156 @@ /* * linux/arch/arm/mm/consistent.c * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 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. * - * Dynamic DMA mapping support. + * DMA uncached mapping support. */ #include #include #include +#include #include -#include #include #include -#include +#include #include +#include +#include #include #include #include +#include + +#define CONSISTENT_BASE (0xffc00000) +#define CONSISTENT_END (0xffe00000) +#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) /* - * This allocates one page of cache-coherent memory space and returns - * both the virtual and a "dma" address to that space. + * This is the page table (2MB) covering uncached, DMA consistent allocations + */ +static pte_t *consistent_pte; +static spinlock_t consistent_lock = SPIN_LOCK_UNLOCKED; + +/* + * VM region handling support. * - * We should allow this function to be called from interrupt context. - * However, we call ioremap, which needs to fiddle around with various - * things (like the vmlist_lock, and allocating page tables). These - * things aren't interrupt safe (yet). + * This should become something generic, handling VM region allocations for + * vmalloc and similar (ioremap, module space, etc). * - * Note that this does *not* zero the allocated area! + * I envisage vmalloc()'s supporting vm_struct becoming: + * + * struct vm_struct { + * struct vm_region region; + * unsigned long flags; + * struct page **pages; + * unsigned int nr_pages; + * unsigned long phys_addr; + * }; + * + * get_vm_area() would then call vm_region_alloc with an appropriate + * struct vm_region head (eg): + * + * struct vm_region vmalloc_head = { + * .vm_list = LIST_HEAD_INIT(vmalloc_head.vm_list), + * .vm_start = VMALLOC_START, + * .vm_end = VMALLOC_END, + * }; + * + * However, vmalloc_head.vm_start is variable (typically, it is dependent on + * the amount of RAM found at boot time.) I would imagine that get_vm_area() + * would have to initialise this each time prior to calling vm_region_alloc(). */ -void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) +struct vm_region { + struct list_head vm_list; + unsigned long vm_start; + unsigned long vm_end; +}; + +static struct vm_region consistent_head = { + .vm_list = LIST_HEAD_INIT(consistent_head.vm_list), + .vm_start = CONSISTENT_BASE, + .vm_end = CONSISTENT_END, +}; + +#if 0 +static void vm_region_dump(struct vm_region *head, char *fn) { - struct page *page, *end, *free; - unsigned long order; - void *ret; + struct vm_region *c; - /* FIXME */ - if (in_interrupt()) - BUG(); + printk("Consistent Allocation Map (%s):\n", fn); + list_for_each_entry(c, &head->list, vm_list) { + printk(" %p: %08lx - %08lx (0x%08x)\n", c, + c->vm_start, c->vm_end, c->vm_end - c->vm_start); + } +} +#else +#define vm_region_dump(head,fn) do { } while(0) +#endif + +static int vm_region_alloc(struct vm_region *head, struct vm_region *new, size_t size) +{ + unsigned long addr = head->vm_start, end = head->vm_end - size; + struct vm_region *c; + + list_for_each_entry(c, &head->vm_list, vm_list) { + if ((addr + size) < addr) + goto out; + if ((addr + size) <= c->vm_start) + goto found; + addr = c->vm_end; + if (addr > end) + goto out; + } + + found: + /* + * Insert this entry _before_ the one we found. + */ + list_add_tail(&new->vm_list, &c->vm_list); + new->vm_start = addr; + new->vm_end = addr + size; + + return 0; + + out: + return -ENOMEM; +} + +static struct vm_region *vm_region_find(struct vm_region *head, unsigned long addr) +{ + struct vm_region *c; + + list_for_each_entry(c, &head->vm_list, vm_list) { + if (c->vm_start == addr) + goto out; + } + c = NULL; + out: + return c; +} + +/* + * This allocates one page of cache-coherent memory space and returns + * both the virtual and a "dma" address to that space. + */ +void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, + unsigned long cache_flags) +{ + struct page *page; + struct vm_region *c; + unsigned long order, flags; + void *ret = NULL; + + if (!consistent_pte) { + printk(KERN_ERR "consistent_alloc: not initialised\n"); + dump_stack(); + return NULL; + } size = PAGE_ALIGN(size); order = get_order(size); @@ -51,75 +159,177 @@ if (!page) goto no_page; - *dma_handle = page_to_bus(page); - ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, 0, - PAGE_SIZE << order); - if (!ret) + /* + * Invalidate any data that might be lurking in the + * kernel direct-mapped region. + */ + { + unsigned long kaddr = (unsigned long)page_address(page); + invalidate_dcache_range(kaddr, kaddr + size); + } + + /* + * Our housekeeping doesn't need to come from DMA, + * but it must not come from highmem. + */ + c = kmalloc(sizeof(struct vm_region), + gfp & ~(__GFP_DMA | __GFP_HIGHMEM)); + if (!c) goto no_remap; -#if 0 /* ioremap_does_flush_cache_all */ - { - void *virt = page_address(page); + spin_lock_irqsave(&consistent_lock, flags); + vm_region_dump(&consistent_head, "before alloc"); + + /* + * Attempt to allocate a virtual address in the + * consistent mapping region. + */ + if (!vm_region_alloc(&consistent_head, c, size)) { + pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start); + struct page *end = page + (1 << order); + pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | + L_PTE_DIRTY | L_PTE_WRITE | + cache_flags); /* - * we need to ensure that there are no cachelines in use, or - * worse dirty in this area. Really, we don't need to do - * this since __ioremap does a flush_cache_all() anyway. --rmk + * Set the "dma handle" */ - invalidate_dcache_range(virt, virt + size); - } -#endif + *handle = page_to_bus(page); - /* - * free wasted pages. We skip the first page since we know - * that it will have count = 1 and won't require freeing. - * We also mark the pages in use as reserved so that - * remap_page_range works. - */ - free = page + (size >> PAGE_SHIFT); - end = page + (1 << order); + do { + BUG_ON(!pte_none(*pte)); - for (; page < end; page++) { - set_page_count(page, 1); - if (page >= free) - __free_page(page); - else + set_page_count(page, 1); SetPageReserved(page); + set_pte(pte, mk_pte(page, prot)); + page++; + pte++; + } while (size -= PAGE_SIZE); + + /* + * Free the otherwise unused pages. + */ + while (page < end) { + set_page_count(page, 1); + __free_page(page); + page++; + } + + ret = (void *)c->vm_start; } - return ret; -no_remap: - __free_pages(page, order); -no_page: - return NULL; + vm_region_dump(&consistent_head, "after alloc"); + spin_unlock_irqrestore(&consistent_lock, flags); + + no_remap: + if (ret == NULL) { + kfree(c); + __free_pages(page, order); + } + no_page: + return ret; } /* - * free a page as defined by the above mapping. We expressly forbid - * calling this from interrupt context. + * free a page as defined by the above mapping. */ void consistent_free(void *vaddr, size_t size, dma_addr_t handle) { - struct page *page, *end; + struct vm_region *c; + unsigned long flags; + pte_t *ptep; - if (in_interrupt()) - BUG(); - - /* - * More messing around with the MM internals. This is - * sick, but then so is remap_page_range(). - */ size = PAGE_ALIGN(size); - page = virt_to_page(bus_to_virt(handle)); - end = page + (size >> PAGE_SHIFT); - for (; page < end; page++) - ClearPageReserved(page); + spin_lock_irqsave(&consistent_lock, flags); + vm_region_dump(&consistent_head, "before free"); - __iounmap(vaddr); + c = vm_region_find(&consistent_head, (unsigned long)vaddr); + if (!c) + goto no_area; + + if ((c->vm_end - c->vm_start) != size) { + printk(KERN_ERR "consistent_free: wrong size (%ld != %d)\n", + c->vm_end - c->vm_start, size); + dump_stack(); + size = c->vm_end - c->vm_start; + } + + ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start); + do { + pte_t pte = ptep_get_and_clear(ptep); + unsigned long pfn; + + ptep++; + + if (!pte_none(pte) && pte_present(pte)) { + pfn = pte_pfn(pte); + + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); + ClearPageReserved(page); + + __free_page(page); + continue; + } + } + + printk(KERN_CRIT "consistent_free: bad page in kernel page " + "table\n"); + } while (size -= PAGE_SIZE); + + flush_tlb_kernel_range(c->vm_start, c->vm_end); + + list_del(&c->vm_list); + + vm_region_dump(&consistent_head, "after free"); + spin_unlock_irqrestore(&consistent_lock, flags); + + kfree(c); + return; + + no_area: + spin_unlock_irqrestore(&consistent_lock, flags); + printk(KERN_ERR "consistent_free: trying to free " + "invalid area: %p\n", vaddr); + dump_stack(); } /* + * Initialise the consistent memory allocation. + */ +static int __init consistent_init(void) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + do { + pgd = pgd_offset(&init_mm, CONSISTENT_BASE); + pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE); + if (!pmd) { + printk(KERN_ERR "consistent_init: out of pmd tables\n"); + return -ENOMEM; + } + if (!pmd_none(*pmd)) { + printk(KERN_ERR "consistent_init: PMD already allocated\n"); + return -EINVAL; + } + pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE); + if (!pte) { + printk(KERN_ERR "consistent_init: out of pte tables\n"); + return -ENOMEM; + } + + consistent_pte = pte; + } while (0); + + return 0; +} + +core_initcall(consistent_init); + +/* * make an area consistent. */ void consistent_sync(void *vaddr, size_t size, int direction) @@ -128,16 +338,16 @@ unsigned long end = start + size; switch (direction) { - case PCI_DMA_NONE: - BUG(); - case PCI_DMA_FROMDEVICE: /* invalidate only */ + case DMA_FROM_DEVICE: /* invalidate only */ invalidate_dcache_range(start, end); break; - case PCI_DMA_TODEVICE: /* writeback only */ + case DMA_TO_DEVICE: /* writeback only */ clean_dcache_range(start, end); break; - case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */ + case DMA_BIDIRECTIONAL: /* writeback and invalidate */ flush_dcache_range(start, end); break; + default: + BUG(); } } diff -Nru a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c --- a/arch/arm/mm/extable.c Mon Jan 13 10:18:06 2003 +++ b/arch/arm/mm/extable.c Mon Jan 13 10:18:06 2003 @@ -1,19 +1,13 @@ /* * linux/arch/arm/mm/extable.c */ - #include -#include -#include #include -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) { while (first <= last) { const struct exception_table_entry *mid; @@ -22,44 +16,11 @@ mid = (last - first) / 2 + first; diff = mid->insn - value; if (diff == 0) - return mid->fixup; + return mid; else if (diff < 0) first = mid+1; else last = mid-1; } - return 0; -} - -extern spinlock_t modlist_lock; - -unsigned long -search_exception_table(unsigned long addr) -{ - unsigned long ret; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); -#else - unsigned long flags; - struct list_head *l; - - ret = 0; - /* The kernel is the last "module" -- no need to treat it special. */ - spin_lock_irqsave(&modlist_lock, flags); - list_for_each(l, &extables) { - struct exception_table *ex - = list_entry(l, struct exception_table, list); - if (ex->num_entries == 0) - continue; - ret = search_one_table(ex->entry, - ex->entry + ex->num_entries - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); -#endif - - return ret; + return NULL; } diff -Nru a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c --- a/arch/arm/mm/fault-common.c Mon Jan 13 10:18:06 2003 +++ b/arch/arm/mm/fault-common.c Mon Jan 13 10:18:06 2003 @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include @@ -102,23 +103,25 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct pt_regs *regs) { - unsigned long fixup; + const struct exception_table_entry *fixup; /* * Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) { + fixup = search_exception_tables(instruction_pointer(regs)); + if (fixup) { #ifdef DEBUG printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", - current->comm, regs->ARM_pc, addr, fixup); + current->comm, regs->ARM_pc, addr, fixup->fixup); #endif - regs->ARM_pc = fixup; + regs->ARM_pc = fixup->fixup; return; } /* * No handler, we'll have to terminate things with extreme prejudice. */ + bust_spinlocks(1); printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", (addr < PAGE_SIZE) ? "NULL pointer dereference" : @@ -126,6 +129,7 @@ show_pte(mm, addr); die("Oops", regs, fsr); + bust_spinlocks(0); do_exit(SIGKILL); } diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c --- a/arch/arm/mm/init.c Mon Jan 13 10:18:05 2003 +++ b/arch/arm/mm/init.c Mon Jan 13 10:18:05 2003 @@ -47,7 +47,7 @@ #define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(pte_t)) -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern char _stext, _text, _etext, _end, __init_begin, __init_end; diff -Nru a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S --- a/arch/arm/mm/proc-arm1020.S Mon Jan 13 10:18:05 2003 +++ b/arch/arm/mm/proc-arm1020.S Mon Jan 13 10:18:05 2003 @@ -420,8 +420,6 @@ mov pc, lr -cpu_manu_name: - .asciz "ARM/VLSI" ENTRY(cpu_arm1020_name) .ascii "Arm1020" #ifndef CONFIG_CPU_ICACHE_DISABLE @@ -518,15 +516,9 @@ .size arm1020_processor_functions, . - arm1020_processor_functions - .type cpu_arm1020_info, #object -cpu_arm1020_info: - .long cpu_manu_name - .long cpu_arm1020_name - .size cpu_arm1020_info, . - cpu_arm1020_info - .type cpu_arch_name, #object cpu_arch_name: - .asciz "armv4" + .asciz "armv4t" .size cpu_arch_name, . - cpu_arch_name .type cpu_elf_name, #object @@ -546,7 +538,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB - .long cpu_arm1020_info + .long cpu_arm1020_name .long arm1020_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns diff -Nru a/arch/arm/mm/proc-arm2_3.S b/arch/arm/mm/proc-arm2_3.S --- a/arch/arm/mm/proc-arm2_3.S Mon Jan 13 10:18:06 2003 +++ b/arch/arm/mm/proc-arm2_3.S Mon Jan 13 10:18:06 2003 @@ -276,10 +276,12 @@ _arm2_3_check_bugs: bics pc, lr, #0x04000000 @ Clear FIQ disable bit -armvlsi_name: .asciz "ARM/VLSI" -_arm2_name: .asciz "ARM 2" -_arm250_name: .asciz "ARM 250" -_arm3_name: .asciz "ARM 3" +cpu_arm2_name: + .asciz "ARM 2" +cpu_arm250_name: + .asciz "ARM 250" +cpu_arm3_name: + .asciz "ARM 3" __INIT /* @@ -295,10 +297,6 @@ .word _arm2_xchg_1 .word _arm2_xchg_4 -cpu_arm2_info: - .long armvlsi_name - .long _arm2_name - .globl arm250_processor_functions arm250_processor_functions: .word _arm2_3_check_bugs @@ -308,10 +306,6 @@ .word _arm3_xchg_1 .word _arm3_xchg_4 -cpu_arm250_info: - .long armvlsi_name - .long _arm250_name - .globl arm3_processor_functions arm3_processor_functions: .word _arm2_3_check_bugs @@ -321,10 +315,6 @@ .word _arm3_xchg_1 .word _arm3_xchg_4 -cpu_arm3_info: - .long armvlsi_name - .long _arm3_name - arm2_arch_name: .asciz "armv1" arm3_arch_name: .asciz "armv2" arm2_elf_name: .asciz "v1" @@ -340,7 +330,7 @@ .long arm2_arch_name .long arm2_elf_name .long 0 - .long cpu_arm2_info + .long cpu_arm2_name .long arm2_processor_functions .long 0 .long 0 @@ -352,7 +342,7 @@ .long arm3_arch_name .long arm3_elf_name .long 0 - .long cpu_arm250_info + .long cpu_arm250_name .long arm250_processor_functions .long 0 .long 0 @@ -364,7 +354,7 @@ .long arm3_arch_name .long arm3_elf_name .long 0 - .long cpu_arm3_info + .long cpu_arm3_name .long arm3_processor_functions .long 0 .long 0 diff -Nru a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S --- a/arch/arm/mm/proc-arm6_7.S Mon Jan 13 10:18:07 2003 +++ b/arch/arm/mm/proc-arm6_7.S Mon Jan 13 10:18:07 2003 @@ -287,14 +287,12 @@ mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc mov pc, r0 -cpu_armvlsi_name: - .asciz "ARM/VLSI" -cpu_arm6_name: .asciz "ARM 6" +cpu_arm6_name: .asciz "ARM6" cpu_arm610_name: - .asciz "ARM 610" -cpu_arm7_name: .asciz "ARM 7" + .asciz "ARM610" +cpu_arm7_name: .asciz "ARM7" cpu_arm710_name: - .asciz "ARM 710" + .asciz "ARM710" .align __INIT @@ -387,30 +385,6 @@ .size arm7_processor_functions, . - arm7_processor_functions - .type cpu_arm6_info, #object -cpu_arm6_info: - .long cpu_armvlsi_name - .long cpu_arm6_name - .size cpu_arm6_info, . - cpu_arm6_info - - .type cpu_arm610_info, #object -cpu_arm610_info: - .long cpu_armvlsi_name - .long cpu_arm610_name - .size cpu_arm610_info, . - cpu_Arm610_info - - .type cpu_arm7_info, #object -cpu_arm7_info: - .long cpu_armvlsi_name - .long cpu_arm7_name - .size cpu_arm7_info, . - cpu_arm7_info - - .type cpu_arm710_info, #object -cpu_arm710_info: - .long cpu_armvlsi_name - .long cpu_arm710_name - .size cpu_arm710_info, . - cpu_arm710_info - .type cpu_arch_name, #object cpu_arch_name: .asciz "armv3" .size cpu_arch_name, . - cpu_arch_name @@ -431,7 +405,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_26BIT - .long cpu_arm6_info + .long cpu_arm6_name .long arm6_processor_functions .long v3_tlb_fns .long v3_user_fns @@ -446,7 +420,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_26BIT - .long cpu_arm610_info + .long cpu_arm610_name .long arm6_processor_functions .long v3_tlb_fns .long v3_user_fns @@ -461,7 +435,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_26BIT - .long cpu_arm7_info + .long cpu_arm7_name .long arm7_processor_functions .long v3_tlb_fns .long v3_user_fns @@ -476,7 +450,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_26BIT - .long cpu_arm710_info + .long cpu_arm710_name .long arm7_processor_functions .long v3_tlb_fns .long v3_user_fns diff -Nru a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S --- a/arch/arm/mm/proc-arm720.S Mon Jan 13 10:18:06 2003 +++ b/arch/arm/mm/proc-arm720.S Mon Jan 13 10:18:06 2003 @@ -168,8 +168,6 @@ mov pc, r0 -cpu_armvlsi_name: - .asciz "ARM" cpu_arm720_name: .asciz "ARM720T" .align @@ -223,14 +221,8 @@ .size arm720_processor_functions, . - arm720_processor_functions - .type cpu_arm720_info, #object -cpu_arm720_info: - .long cpu_armvlsi_name - .long cpu_arm720_name - .size cpu_arm720_info, . - cpu_arm720_info - .type cpu_arch_name, #object -cpu_arch_name: .asciz "armv4" +cpu_arch_name: .asciz "armv4t" .size cpu_arch_name, . - cpu_arch_name .type cpu_elf_name, #object @@ -253,7 +245,7 @@ .long cpu_arch_name @ arch_name .long cpu_elf_name @ elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB @ elf_hwcap - .long cpu_arm720_info @ info + .long cpu_arm720_name @ name .long arm720_processor_functions .long v4_tlb_fns .long v4wt_user_fns diff -Nru a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S --- a/arch/arm/mm/proc-arm920.S Mon Jan 13 10:18:05 2003 +++ b/arch/arm/mm/proc-arm920.S Mon Jan 13 10:18:05 2003 @@ -419,8 +419,6 @@ mov pc, lr -cpu_manu_name: - .asciz "ARM/CIRRUS" ENTRY(cpu_arm920_name) .ascii "Arm920T" #ifndef CONFIG_CPU_ICACHE_DISABLE @@ -506,15 +504,9 @@ .size arm920_processor_functions, . - arm920_processor_functions - .type cpu_arm920_info, #object -cpu_arm920_info: - .long cpu_manu_name - .long cpu_arm920_name - .size cpu_arm920_info, . - cpu_arm920_info - .type cpu_arch_name, #object cpu_arch_name: - .asciz "armv4" + .asciz "armv4t" .size cpu_arch_name, . - cpu_arch_name .type cpu_elf_name, #object @@ -534,7 +526,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB - .long cpu_arm920_info + .long cpu_arm920_name .long arm920_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns diff -Nru a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S --- a/arch/arm/mm/proc-arm922.S Mon Jan 13 10:18:07 2003 +++ b/arch/arm/mm/proc-arm922.S Mon Jan 13 10:18:07 2003 @@ -418,8 +418,6 @@ mov pc, lr -cpu_manu_name: - .asciz "ARM/ALTERA" ENTRY(cpu_arm922_name) .ascii "Arm922T" #ifndef CONFIG_CPU_ICACHE_DISABLE @@ -505,15 +503,9 @@ .size arm922_processor_functions, . - arm922_processor_functions - .type cpu_arm922_info, #object -cpu_arm922_info: - .long cpu_manu_name - .long cpu_arm922_name - .size cpu_arm922_info, . - cpu_arm922_info - .type cpu_arch_name, #object cpu_arch_name: - .asciz "armv4" + .asciz "armv4t" .size cpu_arch_name, . - cpu_arch_name .type cpu_elf_name, #object @@ -533,7 +525,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB - .long cpu_arm922_info + .long cpu_arm922_name .long arm922_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns diff -Nru a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S --- a/arch/arm/mm/proc-arm926.S Mon Jan 13 10:18:06 2003 +++ b/arch/arm/mm/proc-arm926.S Mon Jan 13 10:18:06 2003 @@ -403,8 +403,6 @@ mov pc, lr -cpu_manu_name: - .asciz "ARM" ENTRY(cpu_arm926_name) .ascii "ARM926EJ-S" #ifndef CONFIG_CPU_ICACHE_DISABLE @@ -503,12 +501,6 @@ .size arm926_processor_functions, . - arm926_processor_functions - .type cpu_arm926_info, #object -cpu_arm926_info: - .long cpu_manu_name - .long cpu_arm926_name - .size cpu_arm926_info, . - cpu_arm926_info - .type cpu_arch_name, #object cpu_arch_name: .asciz "armv5tej" @@ -532,7 +524,7 @@ .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \ HWCAP_FAST_MULT | HWCAP_JAVA - .long cpu_arm926_info + .long cpu_arm926_name .long arm926_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns diff -Nru a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S --- a/arch/arm/mm/proc-sa110.S Mon Jan 13 10:18:06 2003 +++ b/arch/arm/mm/proc-sa110.S Mon Jan 13 10:18:06 2003 @@ -473,8 +473,6 @@ mov pc, lr -cpu_manu_name: - .asciz "Intel" cpu_sa110_name: .asciz "StrongARM-110" cpu_sa1100_name: @@ -547,13 +545,6 @@ .size sa110_processor_functions, . - sa110_processor_functions - .type cpu_sa110_info, #object -cpu_sa110_info: - .long cpu_manu_name - .long cpu_sa110_name - .size cpu_sa110_info, . - cpu_sa110_info - - /* * SA1100 and SA1110 share the same function calls */ @@ -587,16 +578,6 @@ .size sa1100_processor_functions, . - sa1100_processor_functions -cpu_sa1100_info: - .long cpu_manu_name - .long cpu_sa1100_name - .size cpu_sa1100_info, . - cpu_sa1100_info - -cpu_sa1110_info: - .long cpu_manu_name - .long cpu_sa1110_name - .size cpu_sa1110_info, . - cpu_sa1110_info - .type cpu_arch_name, #object cpu_arch_name: .asciz "armv4" @@ -620,7 +601,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT - .long cpu_sa110_info + .long cpu_sa110_name .long sa110_processor_functions .long v4wb_tlb_fns .long v4wb_user_fns @@ -637,7 +618,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT - .long cpu_sa1100_info + .long cpu_sa1100_name .long sa1100_processor_functions .long v4wb_tlb_fns .long v4_mc_user_fns @@ -652,7 +633,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT - .long cpu_sa1110_info + .long cpu_sa1110_name .long sa1100_processor_functions .long v4wb_tlb_fns .long v4_mc_user_fns diff -Nru a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S --- a/arch/arm/mm/proc-xscale.S Mon Jan 13 10:18:07 2003 +++ b/arch/arm/mm/proc-xscale.S Mon Jan 13 10:18:07 2003 @@ -651,9 +651,6 @@ .ltorg -cpu_manu_name: - .asciz "Intel" - cpu_80200_name: .asciz "XScale-80200" @@ -723,24 +720,6 @@ .word cpu_xscale_set_pte .size xscale_processor_functions, . - xscale_processor_functions - .type cpu_80200_info, #object -cpu_80200_info: - .long cpu_manu_name - .long cpu_80200_name - .size cpu_80200_info, . - cpu_80200_info - - .type cpu_pxa250_info, #object -cpu_pxa250_info: - .long cpu_manu_name - .long cpu_pxa250_name - .size cpu_pxa250_info, . - cpu_pxa250_info - - .type cpu_pxa210_info, #object -cpu_pxa210_info: - .long cpu_manu_name - .long cpu_pxa210_name - .size cpu_pxa210_info, . - cpu_pxa210_info - .type cpu_arch_name, #object cpu_arch_name: .asciz "armv5te" @@ -763,7 +742,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP - .long cpu_80200_info + .long cpu_80200_name .long xscale_processor_functions .long v4wbi_tlb_fns .long xscale_mc_user_fns @@ -778,7 +757,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP - .long cpu_pxa250_info + .long cpu_pxa250_name .long xscale_processor_functions .long v4wbi_tlb_fns .long xscale_mc_user_fns @@ -793,7 +772,7 @@ .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP - .long cpu_pxa210_info + .long cpu_pxa210_name .long xscale_processor_functions .long v4wbi_tlb_fns .long xscale_mc_user_fns diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in --- a/arch/arm/vmlinux-armo.lds.in Mon Jan 13 10:18:07 2003 +++ b/arch/arm/vmlinux-armo.lds.in Mon Jan 13 10:18:07 2003 @@ -78,6 +78,12 @@ __stop___ksymtab = .; } + __gpl_ksymtab : { /* Kernel symbol table: GPL-only */ + __start___gpl_ksymtab = .; + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + } + .data : { /* * The cacheline aligned data diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in --- a/arch/arm/vmlinux-armv.lds.in Mon Jan 13 10:18:05 2003 +++ b/arch/arm/vmlinux-armv.lds.in Mon Jan 13 10:18:05 2003 @@ -75,6 +75,12 @@ __stop___ex_table = .; } + __gpl_ksymtab : { /* GPL Kernel symbol table */ + __start___gpl_ksymtab = .; + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + } + __ksymtab : { /* Kernel symbol table */ __start___ksymtab = .; *(__ksymtab) diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S --- a/arch/cris/vmlinux.lds.S Mon Jan 13 10:18:06 2003 +++ b/arch/cris/vmlinux.lds.S Mon Jan 13 10:18:06 2003 @@ -43,6 +43,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + . = ALIGN (4); ___data_start = . ; __Sdata = . ; diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Mon Jan 13 10:18:05 2003 +++ b/arch/i386/Kconfig Mon Jan 13 10:18:05 2003 @@ -117,10 +117,10 @@ (time stamp counter) register. - "Pentium-Classic" for the Intel Pentium. - "Pentium-MMX" for the Intel Pentium MMX. - - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. - - "Pentium-III" for the Intel Pentium III - and Celerons based on the Coppermine core. - - "Pentium-4" for the Intel Pentium 4. + - "Pentium-Pro" for the Intel Pentium Pro. + - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron. + - "Pentium-III" for the Intel Pentium III or Coppermine Celeron. + - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron. - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). - "Crusoe" for the Transmeta Crusoe series. @@ -159,25 +159,37 @@ extended instructions. config M686 - bool "Pentium-Pro/Celeron/Pentium-II" + bool "Pentium-Pro" help - Select this for a Pro/Celeron/Pentium II. This enables the use of + Select this for Intel Pentium Pro chips. This enables the use of Pentium Pro extended instructions, and disables the init-time guard against the f00f bug found in earlier Pentiums. +config MPENTIUMII + bool "Pentium-II/Celeron(pre-Coppermine)" + help + Select this for Intel chips based on the Pentium-II and + pre-Coppermine Celeron core. This option enables an unaligned + copy optimization, compiles the kernel with optimization flags + tailored for the chip, and applies any applicable Pentium Pro + optimizations. + config MPENTIUMIII bool "Pentium-III/Celeron(Coppermine)" help Select this for Intel chips based on the Pentium-III and - Celeron-Coppermine core. Enables use of some extended prefetch - instructions, in addition to the Pentium II extensions. + Celeron-Coppermine core. This option enables use of some + extended prefetch instructions in addition to the Pentium II + extensions. config MPENTIUM4 - bool "Pentium-4" + bool "Pentium-4/Celeron(P4-based)" help - Select this for Intel Pentium 4 chips. Presently these are - treated almost like Pentium IIIs, but with a different cache - shift. + Select this for Intel Pentium 4 chips. This includes both + the Pentium 4 and P4-based Celeron chips. This option + enables compile flags optimized for the chip, uses the + correct cache shift, and applies any applicable Pentium III + optimizations. config MK6 bool "K6/K6-II/K6-III" @@ -258,7 +270,7 @@ config X86_L1_CACHE_SHIFT int - default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || M686 || M586MMX || M586TSC || M586 + default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 default "4" if MELAN || M486 || M386 default "6" if MK7 || MK8 default "7" if MPENTIUM4 @@ -310,22 +322,22 @@ config X86_TSC bool - depends on MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || M586TSC || MK8 + depends on MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 default y config X86_GOOD_APIC bool - depends on MK7 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || MK8 + depends on MK7 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 default y config X86_INTEL_USERCOPY bool - depends on MPENTIUM4 || MPENTIUMIII || M586MMX + depends on MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M586MMX default y config X86_USE_PPRO_CHECKSUM bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || MK8 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || MK8 default y config X86_USE_3DNOW diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Mon Jan 13 10:18:05 2003 +++ b/arch/i386/Makefile Mon Jan 13 10:18:05 2003 @@ -34,6 +34,7 @@ cflags-$(CONFIG_M586TSC) += -march=i586 cflags-$(CONFIG_M586MMX) += $(call check_gcc,-march=pentium-mmx,-march=i586) cflags-$(CONFIG_M686) += -march=i686 +cflags-$(CONFIG_MPENTIUMII) += $(call check_gcc,-march=pentium2,-march=i686) cflags-$(CONFIG_MPENTIUMIII) += $(call check_gcc,-march=pentium3,-march=i686) cflags-$(CONFIG_MPENTIUM4) += $(call check_gcc,-march=pentium4,-march=i686) cflags-$(CONFIG_MK6) += $(call check_gcc,-march=k6,-march=i586) diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c Mon Jan 13 10:18:05 2003 +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c Mon Jan 13 10:18:05 2003 @@ -61,6 +61,18 @@ {99000, 0x01, 0x05} }; +static struct cpufreq_frequency_table elanfreq_table[] = { + {0, 1000}, + {1, 2000}, + {2, 4000}, + {3, 8000}, + {4, 16000}, + {5, 33000}, + {6, 66000}, + {7, 99000}, + {0, CPUFREQ_TABLE_END}, +}; + /** * elanfreq_get_cpu_frequency: determine current cpu speed @@ -172,63 +184,17 @@ static int elanfreq_verify (struct cpufreq_policy *policy) { - unsigned int number_states = 0; - unsigned int i; - - if (!policy || !max_freq) - return -EINVAL; - - policy->cpu = 0; - - cpufreq_verify_within_limits(policy, 1000, max_freq); - - for (i=7; i>=0; i--) - if ((elan_multiplier[i].clock >= policy->min) && - (elan_multiplier[i].clock <= policy->max)) - number_states++; - - if (number_states) - return 0; - - for (i=7; i>=0; i--) - if (elan_multiplier[i].clock < policy->max) - break; - - policy->max = elan_multiplier[i+1].clock; - - cpufreq_verify_within_limits(policy, 1000, max_freq); - - return 0; + return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]); } static int elanfreq_setpolicy (struct cpufreq_policy *policy) { - unsigned int i; - unsigned int optimal = 8; - - if (!elanfreq_driver) - return -EINVAL; + unsigned int newstate = 0; - for (i=0; i<8; i++) { - if ((elan_multiplier[i].clock > policy->max) || - (elan_multiplier[i].clock < policy->min)) - continue; - switch(policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - if (optimal == 8) - optimal = i; - break; - case CPUFREQ_POLICY_PERFORMANCE: - optimal = i; - break; - default: - return -EINVAL; - } - } - if ((optimal == 8) || (elan_multiplier[optimal].clock > max_freq)) + if (cpufreq_frequency_table_setpolicy(policy, &elanfreq_table[0], &newstate)) return -EINVAL; - elanfreq_set_cpu_state(optimal); + elanfreq_set_cpu_state(newstate); return 0; } @@ -262,7 +228,7 @@ { struct cpuinfo_x86 *c = cpu_data; struct cpufreq_driver *driver; - int ret; + int ret, i; /* Test if we have the right hardware */ if ((c->x86_vendor != X86_VENDOR_AMD) || @@ -282,6 +248,12 @@ if (!max_freq) max_freq = elanfreq_get_cpu_frequency(); + /* table init */ + for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) { + if (elanfreq_table[i].frequency > max_freq) + elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID; + } + #ifdef CONFIG_CPU_FREQ_24_API driver->cpu_cur_freq[0] = elanfreq_get_cpu_frequency(); #endif @@ -290,11 +262,12 @@ driver->setpolicy = &elanfreq_setpolicy; driver->policy[0].cpu = 0; - driver->policy[0].min = 1000; - driver->policy[0].max = max_freq; + ret = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &elanfreq_table[0]); + if (ret) { + kfree(driver); + return ret; + } driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE; - driver->policy[0].cpuinfo.max_freq = max_freq; - driver->policy[0].cpuinfo.min_freq = 1000; driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL; elanfreq_driver = driver; diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Mon Jan 13 10:18:07 2003 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Mon Jan 13 10:18:07 2003 @@ -141,39 +141,27 @@ } +static struct cpufreq_frequency_table p4clockmod_table[] = { + {DC_RESV, CPUFREQ_ENTRY_INVALID}, + {DC_DFLT, 0}, + {DC_25PT, 0}, + {DC_38PT, 0}, + {DC_50PT, 0}, + {DC_64PT, 0}, + {DC_75PT, 0}, + {DC_88PT, 0}, + {DC_DISABLE, 0}, + {DC_RESV, CPUFREQ_TABLE_END}, +}; + + static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy) { - unsigned int i; - unsigned int newstate = 0; - unsigned int number_states = 0; - unsigned int minstate = 1; + unsigned int newstate = DC_RESV; - if (!cpufreq_p4_driver || !stock_freq || - !policy || !cpu_online(policy->cpu)) + if (cpufreq_frequency_table_setpolicy(policy, &p4clockmod_table[0], &newstate)) return -EINVAL; - if (has_N44_O17_errata) - minstate = 3; - - if (policy->policy == CPUFREQ_POLICY_POWERSAVE) - { - for (i=8; i>=minstate; i--) - if ((policy->min <= ((stock_freq / 8) * i)) && - (policy->max >= ((stock_freq / 8) * i))) - { - newstate = i; - number_states++; - } - } else { - for (i=minstate; i<=8; i++) - if ((policy->min <= ((stock_freq / 8) * i)) && - (policy->max >= ((stock_freq / 8) * i))) - { - newstate = i; - number_states++; - } - } - cpufreq_p4_setdc(policy->cpu, newstate); return 0; @@ -182,34 +170,7 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy) { - unsigned int number_states = 0; - unsigned int i = 1; - - if (!cpufreq_p4_driver || !stock_freq || - !policy || !cpu_online(policy->cpu)) - return -EINVAL; - - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - - if (has_N44_O17_errata) - i = 3; - - /* is there at least one state within the limit? */ - for (; i<=8; i++) - if ((policy->min <= ((stock_freq / 8) * i)) && - (policy->max >= ((stock_freq / 8) * i))) - number_states++; - - if (number_states) - return 0; - - policy->max = (stock_freq / 8) * (((unsigned int) ((policy->max * 8) / stock_freq)) + 1); - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - return 0; + return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]); } @@ -262,6 +223,15 @@ driver->policy = (struct cpufreq_policy *) (driver + 1); + /* table init */ + for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) { + if ((i<2) && (has_N44_O17_errata)) + p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID; + else + p4clockmod_table[i].frequency = (stock_freq * i)/8; + } + + #ifdef CONFIG_CPU_FREQ_24_API for (i=0;icpu_cur_freq[i] = stock_freq; @@ -272,17 +242,14 @@ driver->setpolicy = &cpufreq_p4_setpolicy; for (i=0;ipolicy[i].min = (stock_freq * 3) / 8; - else - driver->policy[i].min = stock_freq / 8; - driver->policy[i].max = stock_freq; + driver->policy[i].cpu = i; + ret = cpufreq_frequency_table_cpuinfo(&driver->policy[i], &p4clockmod_table[0]); + if (ret) { + kfree(driver); + return ret; + } driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE; - driver->policy[i].cpuinfo.min_freq = driver->policy[i].min; - driver->policy[i].cpuinfo.max_freq = stock_freq; driver->policy[i].cpuinfo.transition_latency = CPUFREQ_ETERNAL; - - driver->policy[i].cpu = i; } cpufreq_p4_driver = driver; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Mon Jan 13 10:18:05 2003 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Mon Jan 13 10:18:05 2003 @@ -31,15 +31,16 @@ /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ -static int clock_ratio[8] = { - 45, /* 000 -> 4.5x */ - 50, /* 001 -> 5.0x */ - 40, /* 010 -> 4.0x */ - 55, /* 011 -> 5.5x */ - 20, /* 100 -> 2.0x */ - 30, /* 101 -> 3.0x */ - 60, /* 110 -> 6.0x */ - 35 /* 111 -> 3.5x */ +static struct cpufreq_frequency_table clock_ratio[] = { + {45, /* 000 -> 4.5x */ 0}, + {50, /* 001 -> 5.0x */ 0}, + {40, /* 010 -> 4.0x */ 0}, + {55, /* 011 -> 5.5x */ 0}, + {20, /* 100 -> 2.0x */ 0}, + {30, /* 101 -> 3.0x */ 0}, + {60, /* 110 -> 6.0x */ 0}, + {35, /* 111 -> 3.5x */ 0}, + {0, CPUFREQ_TABLE_END} }; @@ -60,7 +61,7 @@ msrval = POWERNOW_IOPORT + 0x0; wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ - return clock_ratio[(invalue >> 5)&7]; + return clock_ratio[(invalue >> 5)&7].index; } @@ -82,7 +83,7 @@ } freqs.old = busfreq * powernow_k6_get_cpu_multiplier(); - freqs.new = busfreq * clock_ratio[best_i]; + freqs.new = busfreq * clock_ratio[best_i].index; freqs.cpu = 0; /* powernow-k6.c is UP only driver */ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); @@ -115,39 +116,7 @@ */ static int powernow_k6_verify(struct cpufreq_policy *policy) { - unsigned int number_states = 0; - unsigned int i, j; - - if (!policy || !busfreq) - return -EINVAL; - - policy->cpu = 0; - cpufreq_verify_within_limits(policy, (20 * busfreq), - (max_multiplier * busfreq)); - - for (i=0; i<8; i++) - if ((policy->min <= (busfreq * clock_ratio[i])) && - (policy->max >= (busfreq * clock_ratio[i]))) - number_states++; - - if (number_states) - return 0; - - /* no state is available within range -- find next larger state */ - - j = 6; - - for (i=0; i<8; i++) - if (((clock_ratio[i] * busfreq) >= policy->min) && - (clock_ratio[i] < clock_ratio[j])) - j = i; - - policy->max = clock_ratio[j] * busfreq; - - cpufreq_verify_within_limits(policy, (20 * busfreq), - (max_multiplier * busfreq)); - - return 0; + return cpufreq_frequency_table_verify(policy, &clock_ratio[0]); } @@ -159,43 +128,12 @@ */ static int powernow_k6_setpolicy (struct cpufreq_policy *policy) { - unsigned int i; - unsigned int optimal; + unsigned int newstate = 0; - if (!powernow_driver || !policy || policy->cpu) + if (cpufreq_frequency_table_setpolicy(policy, &clock_ratio[0], &newstate)) return -EINVAL; - switch(policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - optimal = 6; - break; - case CPUFREQ_POLICY_PERFORMANCE: - optimal = max_multiplier; - break; - default: - return -EINVAL; - } - - for (i=0;i<8;i++) { - unsigned int freq = busfreq * clock_ratio[i]; - if (clock_ratio[i] > max_multiplier) - continue; - if ((freq > policy->max) || - (freq < policy->min)) - continue; - switch(policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - if (freq < (clock_ratio[optimal] * busfreq)) - optimal = i; - break; - case CPUFREQ_POLICY_PERFORMANCE: - if (freq > (clock_ratio[optimal] * busfreq)) - optimal = i; - break; - } - } - - powernow_k6_set_state(optimal); + powernow_k6_set_state(newstate); return 0; } @@ -213,6 +151,7 @@ struct cpuinfo_x86 *c = cpu_data; struct cpufreq_driver *driver; unsigned int result; + unsigned int i; if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || ((c->x86_model != 12) && (c->x86_model != 13))) @@ -235,20 +174,29 @@ } driver->policy = (struct cpufreq_policy *) (driver + 1); -#ifdef CONFIG_CPU_FREQ_24_API - driver->cpu_cur_freq[0] = busfreq * max_multiplier; -#endif + /* table init */ + for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { + if (clock_ratio[i].index > max_multiplier) + clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID; + else + clock_ratio[i].frequency = busfreq * clock_ratio[i].index; + } driver->verify = &powernow_k6_verify; driver->setpolicy = &powernow_k6_setpolicy; + /* cpuinfo and default policy values */ driver->policy[0].cpu = 0; - driver->policy[0].min = busfreq * 20; - driver->policy[0].max = busfreq * max_multiplier; - driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE; - driver->policy[0].cpuinfo.max_freq = busfreq * max_multiplier; - driver->policy[0].cpuinfo.min_freq = busfreq * 20; driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL; + driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE; +#ifdef CONFIG_CPU_FREQ_24_API + driver->cpu_cur_freq[0] = busfreq * max_multiplier; +#endif + result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &clock_ratio[0]); + if (result) { + kfree(driver); + return result; + } powernow_driver = driver; @@ -274,7 +222,7 @@ if (powernow_driver) { for (i=0;i<8;i++) - if (clock_ratio[i] == max_multiplier) + if (clock_ratio[i].index == max_multiplier) powernow_k6_set_state(i); cpufreq_unregister(); kfree(powernow_driver); diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep.c Mon Jan 13 10:18:04 2003 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c Mon Jan 13 10:18:04 2003 @@ -58,12 +58,18 @@ * There are only two frequency states for each processor. Values * are in kHz for the time being. */ -static unsigned int speedstep_low_freq; -static unsigned int speedstep_high_freq; - #define SPEEDSTEP_HIGH 0x00000000 #define SPEEDSTEP_LOW 0x00000001 +static struct cpufreq_frequency_table speedstep_freqs[] = { + {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +#define speedstep_low_freq speedstep_freqs[SPEEDSTEP_LOW].frequency +#define speedstep_high_freq speedstep_freqs[SPEEDSTEP_HIGH].frequency + /* DEBUG * Define it if you want verbose debug output, e.g. for bug reporting @@ -447,7 +453,7 @@ if (c->x86_model != 2) return 0; - if (c->x86_mask != 4) + if ((c->x86_mask != 4) && (c->x86_mask != 7)) return 0; ebx = cpuid_ebx(0x00000001); @@ -569,22 +575,13 @@ */ static int speedstep_setpolicy (struct cpufreq_policy *policy) { - if (!speedstep_driver || !policy) + unsigned int newstate = 0; + + if (cpufreq_frequency_table_setpolicy(policy, &speedstep_freqs[0], &newstate)) return -EINVAL; - if (policy->min > speedstep_low_freq) - speedstep_set_state(SPEEDSTEP_HIGH, 1); - else { - if (policy->max < speedstep_high_freq) - speedstep_set_state(SPEEDSTEP_LOW, 1); - else { - /* both frequency states are allowed */ - if (policy->policy == CPUFREQ_POLICY_POWERSAVE) - speedstep_set_state(SPEEDSTEP_LOW, 1); - else - speedstep_set_state(SPEEDSTEP_HIGH, 1); - } - } + speedstep_set_state(newstate, 1); + return 0; } @@ -598,19 +595,7 @@ */ static int speedstep_verify (struct cpufreq_policy *policy) { - if (!policy || !speedstep_driver || - !speedstep_low_freq || !speedstep_high_freq) - return -EINVAL; - - policy->cpu = 0; /* UP only */ - - cpufreq_verify_within_limits(policy, speedstep_low_freq, speedstep_high_freq); - - if ((policy->min > speedstep_low_freq) && - (policy->max < speedstep_high_freq)) - policy->max = speedstep_high_freq; - - return 0; + return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); } @@ -692,6 +677,13 @@ driver->policy = (struct cpufreq_policy *) (driver + 1); + driver->policy[0].cpu = 0; + result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &speedstep_freqs[0]); + if (result) { + kfree(driver); + return result; + } + #ifdef CONFIG_CPU_FREQ_24_API driver->cpu_cur_freq[0] = speed; #endif @@ -699,11 +691,6 @@ driver->verify = &speedstep_verify; driver->setpolicy = &speedstep_setpolicy; - driver->policy[0].cpu = 0; - driver->policy[0].min = speedstep_low_freq; - driver->policy[0].max = speedstep_high_freq; - driver->policy[0].cpuinfo.min_freq = speedstep_low_freq; - driver->policy[0].cpuinfo.max_freq = speedstep_high_freq; driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL; driver->policy[0].policy = (speed == speedstep_low_freq) ? diff -Nru a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c --- a/arch/i386/kernel/edd.c Mon Jan 13 10:18:05 2003 +++ b/arch/i386/kernel/edd.c Mon Jan 13 10:18:05 2003 @@ -61,7 +61,7 @@ #define EDD_DEVICE_NAME_SIZE 16 #define REPORT_URL "http://domsch.com/linux/edd30/results.html" -#define left (count - (p - buf) - 1) +#define left (PAGE_SIZE - (p - buf) - 1) struct edd_device { struct edd_info *info; @@ -70,8 +70,7 @@ struct edd_attribute { struct attribute attr; - ssize_t(*show) (struct edd_device * edev, char *buf, size_t count, - loff_t off); + ssize_t(*show) (struct edd_device * edev, char *buf); int (*test) (struct edd_device * edev); }; @@ -104,15 +103,14 @@ #define to_edd_device(obj) container_of(obj,struct edd_device,kobj) static ssize_t -edd_attr_show(struct kobject * kobj, struct attribute *attr, - char *buf, size_t count, loff_t off) +edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) { struct edd_device *dev = to_edd_device(kobj); struct edd_attribute *edd_attr = to_edd_attr(attr); ssize_t ret = 0; if (edd_attr->show) - ret = edd_attr->show(dev, buf, count, off); + ret = edd_attr->show(dev, buf); return ret; } @@ -156,13 +154,13 @@ } static ssize_t -edd_show_host_bus(struct edd_device *edev, char *buf, size_t count, loff_t off) +edd_show_host_bus(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; int i; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -200,13 +198,13 @@ } static ssize_t -edd_show_interface(struct edd_device *edev, char *buf, size_t count, loff_t off) +edd_show_interface(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; int i; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -262,7 +260,7 @@ * Returns: number of bytes written, or 0 on failure */ static ssize_t -edd_show_raw_data(struct edd_device *edev, char *buf, size_t count, loff_t off) +edd_show_raw_data(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); int i, rc, warn_padding = 0, email = 0, nonzero_path = 0, @@ -271,7 +269,7 @@ char *p = buf; struct pci_dev *pci_dev=NULL; struct scsi_device *sd; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -372,11 +370,11 @@ } static ssize_t -edd_show_version(struct edd_device *edev, char *buf, size_t count, loff_t off) +edd_show_version(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -385,12 +383,11 @@ } static ssize_t -edd_show_extensions(struct edd_device *edev, char *buf, size_t count, - loff_t off) +edd_show_extensions(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -410,12 +407,11 @@ } static ssize_t -edd_show_info_flags(struct edd_device *edev, char *buf, size_t count, - loff_t off) +edd_show_info_flags(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -439,12 +435,11 @@ } static ssize_t -edd_show_default_cylinders(struct edd_device *edev, char *buf, size_t count, - loff_t off) +edd_show_default_cylinders(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -453,12 +448,11 @@ } static ssize_t -edd_show_default_heads(struct edd_device *edev, char *buf, size_t count, - loff_t off) +edd_show_default_heads(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -467,12 +461,11 @@ } static ssize_t -edd_show_default_sectors_per_track(struct edd_device *edev, char *buf, - size_t count, loff_t off) +edd_show_default_sectors_per_track(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } @@ -481,11 +474,11 @@ } static ssize_t -edd_show_sectors(struct edd_device *edev, char *buf, size_t count, loff_t off) +edd_show_sectors(struct edd_device *edev, char *buf) { struct edd_info *info = edd_dev_get_info(edev); char *p = buf; - if (!edev || !info || !buf || off) { + if (!edev || !info || !buf) { return 0; } diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Mon Jan 13 10:18:07 2003 +++ b/arch/i386/kernel/i386_ksyms.c Mon Jan 13 10:18:07 2003 @@ -118,10 +118,8 @@ EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(clear_user); EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(copy_from_user); -EXPORT_SYMBOL(__copy_from_user); -EXPORT_SYMBOL(copy_to_user); -EXPORT_SYMBOL(__copy_to_user); +EXPORT_SYMBOL(__copy_from_user_ll); +EXPORT_SYMBOL(__copy_to_user_ll); EXPORT_SYMBOL(strnlen_user); EXPORT_SYMBOL(dma_alloc_coherent); diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c --- a/arch/i386/kernel/ptrace.c Mon Jan 13 10:18:05 2003 +++ b/arch/i386/kernel/ptrace.c Mon Jan 13 10:18:05 2003 @@ -21,6 +21,8 @@ #include #include #include +#include +#include /* * does not yet catch signals sent when the child dies. @@ -148,6 +150,85 @@ put_stack_long(child, EFL_OFFSET, tmp); } +/* + * Perform get_thread_area on behalf of the traced child. + */ +static int +ptrace_get_thread_area(struct task_struct *child, + int idx, struct user_desc *user_desc) +{ + struct user_desc info; + struct desc_struct *desc; + +/* + * Get the current Thread-Local Storage area: + */ + +#define GET_BASE(desc) ( \ + (((desc)->a >> 16) & 0x0000ffff) | \ + (((desc)->b << 16) & 0x00ff0000) | \ + ( (desc)->b & 0xff000000) ) + +#define GET_LIMIT(desc) ( \ + ((desc)->a & 0x0ffff) | \ + ((desc)->b & 0xf0000) ) + +#define GET_32BIT(desc) (((desc)->b >> 23) & 1) +#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) +#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) +#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) +#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) +#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) + + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; + + info.entry_number = idx; + info.base_addr = GET_BASE(desc); + info.limit = GET_LIMIT(desc); + info.seg_32bit = GET_32BIT(desc); + info.contents = GET_CONTENTS(desc); + info.read_exec_only = !GET_WRITABLE(desc); + info.limit_in_pages = GET_LIMIT_PAGES(desc); + info.seg_not_present = !GET_PRESENT(desc); + info.useable = GET_USEABLE(desc); + + if (copy_to_user(user_desc, &info, sizeof(info))) + return -EFAULT; + + return 0; +} + +/* + * Perform set_thread_area on behalf of the traced child. + */ +static int +ptrace_set_thread_area(struct task_struct *child, + int idx, struct user_desc *user_desc) +{ + struct user_desc info; + struct desc_struct *desc; + + if (copy_from_user(&info, user_desc, sizeof(info))) + return -EFAULT; + + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; + if (LDT_empty(&info)) { + desc->a = 0; + desc->b = 0; + } else { + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + } + + return 0; +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -415,6 +496,16 @@ ret = set_fpxregs(child, (struct user_fxsr_struct *)data); break; } + + case PTRACE_GET_THREAD_AREA: + ret = ptrace_get_thread_area(child, + addr, (struct user_desc *) data); + break; + + case PTRACE_SET_THREAD_AREA: + ret = ptrace_set_thread_area(child, + addr, (struct user_desc *) data); + break; default: ret = ptrace_request(child, request, addr, data); diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c --- a/arch/i386/kernel/signal.c Mon Jan 13 10:18:06 2003 +++ b/arch/i386/kernel/signal.c Mon Jan 13 10:18:06 2003 @@ -350,6 +350,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { + void *restorer; struct sigframe *frame; int err = 0; @@ -378,8 +379,12 @@ if (err) goto give_sigsegv; + restorer = (void *) (fix_to_virt(FIX_VSYSCALL) + 32); + if (ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + /* Set up to return from userspace. */ - err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 32, &frame->pretcode); + err |= __put_user(restorer, &frame->pretcode); /* * This is popl %eax ; movl $,%eax ; int $0x80 @@ -422,6 +427,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { + void *restorer; struct rt_sigframe *frame; int err = 0; @@ -456,7 +462,10 @@ goto give_sigsegv; /* Set up to return from userspace. */ - err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 64, &frame->pretcode); + restorer = (void *) (fix_to_virt(FIX_VSYSCALL) + 64); + if (ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + err |= __put_user(restorer, &frame->pretcode); /* * This is movl $,%eax ; int $0x80 diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Mon Jan 13 10:18:05 2003 +++ b/arch/i386/kernel/traps.c Mon Jan 13 10:18:05 2003 @@ -297,26 +297,7 @@ } kernel_trap: { - const struct exception_table_entry *fixup; -#ifdef CONFIG_PNPBIOS - if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */ - { - extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; - extern u32 pnp_bios_is_utter_crap; - pnp_bios_is_utter_crap = 1; - printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n"); - __asm__ volatile( - "movl %0, %%esp\n\t" - "jmp *%1\n\t" - : "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip)); - panic("do_trap: can't hit this"); - } -#endif - - fixup = search_exception_tables(regs->eip); - if (fixup) - regs->eip = fixup->fixup; - else + if (!fixup_exception(regs)) die(str, regs, error_code); return; } @@ -393,15 +374,8 @@ return; gp_in_kernel: - { - const struct exception_table_entry *fixup; - fixup = search_exception_tables(regs->eip); - if (fixup) { - regs->eip = fixup->fixup; - return; - } + if (!fixup_exception(regs)) die("general protection fault", regs, error_code); - } } static void mem_parity_error(unsigned char reason, struct pt_regs * regs) diff -Nru a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c --- a/arch/i386/lib/usercopy.c Mon Jan 13 10:18:04 2003 +++ b/arch/i386/lib/usercopy.c Mon Jan 13 10:18:04 2003 @@ -417,7 +417,7 @@ } while (0) -unsigned long __copy_to_user(void *to, const void *from, unsigned long n) +unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n) { if (movsl_is_ok(to, from, n)) __copy_user(to, from, n); @@ -426,27 +426,11 @@ return n; } -unsigned long __copy_from_user(void *to, const void *from, unsigned long n) +unsigned long __copy_from_user_ll(void *to, const void *from, unsigned long n) { if (movsl_is_ok(to, from, n)) __copy_user_zeroing(to, from, n); else n = __copy_user_zeroing_intel(to, from, n); - return n; -} - -unsigned long copy_to_user(void *to, const void *from, unsigned long n) -{ - prefetch(from); - if (access_ok(VERIFY_WRITE, to, n)) - n = __copy_to_user(to, from, n); - return n; -} - -unsigned long copy_from_user(void *to, const void *from, unsigned long n) -{ - prefetchw(to); - if (access_ok(VERIFY_READ, from, n)) - n = __copy_from_user(to, from, n); return n; } diff -Nru a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c --- a/arch/i386/mm/extable.c Mon Jan 13 10:18:07 2003 +++ b/arch/i386/mm/extable.c Mon Jan 13 10:18:07 2003 @@ -28,3 +28,31 @@ } return NULL; } + +int fixup_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + +#ifdef CONFIG_PNPBIOS + if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */ + { + extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; + extern u32 pnp_bios_is_utter_crap; + pnp_bios_is_utter_crap = 1; + printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n"); + __asm__ volatile( + "movl %0, %%esp\n\t" + "jmp *%1\n\t" + : "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip)); + panic("do_trap: can't hit this"); + } +#endif + + fixup = search_exception_tables(regs->eip); + if (fixup) { + regs->eip = fixup->fixup; + return 1; + } + + return 0; +} diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Mon Jan 13 10:18:04 2003 +++ b/arch/i386/mm/fault.c Mon Jan 13 10:18:04 2003 @@ -155,7 +155,6 @@ struct vm_area_struct * vma; unsigned long address; unsigned long page; - const struct exception_table_entry *fixup; int write; siginfo_t info; @@ -311,10 +310,8 @@ no_context: /* Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_tables(regs->eip)) != NULL) { - regs->eip = fixup->fixup; + if (fixup_exception(regs)) return; - } /* * Oops. The kernel tried to access some bad page. We'll have to diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c --- a/arch/i386/mm/init.c Mon Jan 13 10:18:07 2003 +++ b/arch/i386/mm/init.c Mon Jan 13 10:18:07 2003 @@ -41,7 +41,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; unsigned long highstart_pfn, highend_pfn; /* @@ -71,12 +71,16 @@ */ static pte_t * __init one_page_table_init(pmd_t *pmd) { - pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); - if (page_table != pte_offset_kernel(pmd, 0)) - BUG(); + if (pmd_none(*pmd)) { + pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); + if (page_table != pte_offset_kernel(pmd, 0)) + BUG(); - return page_table; + return page_table; + } + + return pte_offset_kernel(pmd, 0); } /* diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S --- a/arch/i386/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/i386/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -31,6 +31,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } __stop___kallsyms = .; diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Mon Jan 13 10:18:06 2003 +++ b/arch/ia64/mm/init.c Mon Jan 13 10:18:06 2003 @@ -29,7 +29,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; /* References to section boundaries: */ extern char _stext, _etext, _edata, __init_begin, __init_end; diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S --- a/arch/ia64/vmlinux.lds.S Mon Jan 13 10:18:07 2003 +++ b/arch/ia64/vmlinux.lds.S Mon Jan 13 10:18:07 2003 @@ -65,6 +65,11 @@ { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL only */ + __gpl_ksymtab : AT(ADDR(__gpl_ksymtab) - PAGE_OFFSET) + { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + __kallsyms : AT(ADDR(__kallsyms) - PAGE_OFFSET) { __start___kallsyms = .; /* All kernel symbols */ diff -Nru a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c --- a/arch/m68k/mac/iop.c Mon Jan 13 10:18:07 2003 +++ b/arch/m68k/mac/iop.c Mon Jan 13 10:18:07 2003 @@ -28,7 +28,7 @@ * globally-visible functions take an IOP number instead of an * an actual base address. * 990610 (jmt) - Finished the message passing framework and it seems to work. - * Sending _definately_ works; my adb-bus.c mods can send + * Sending _definitely_ works; my adb-bus.c mods can send * messages and receive the MSG_COMPLETED status back from the * IOP. The trick now is figuring out the message formats. * 990611 (jmt) - More cleanups. Fixed problem where unclaimed messages on a diff -Nru a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c --- a/arch/m68k/mm/init.c Mon Jan 13 10:18:07 2003 +++ b/arch/m68k/mm/init.c Mon Jan 13 10:18:07 2003 @@ -33,7 +33,7 @@ #endif #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; /* * ZERO_PAGE is a special page that is used for zero-initialized diff -Nru a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds --- a/arch/m68k/vmlinux-std.lds Mon Jan 13 10:18:07 2003 +++ b/arch/m68k/vmlinux-std.lds Mon Jan 13 10:18:07 2003 @@ -24,6 +24,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL only */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + _etext = .; /* End of text section */ .data : { /* Data */ diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds --- a/arch/m68k/vmlinux-sun3.lds Mon Jan 13 10:18:04 2003 +++ b/arch/m68k/vmlinux-sun3.lds Mon Jan 13 10:18:04 2003 @@ -30,6 +30,9 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; } /* End of data goes *here* so that freeing init code works properly. */ _edata = .; diff -Nru a/arch/m68knommu/platform/5206/ARNEWSH/ram.ld b/arch/m68knommu/platform/5206/ARNEWSH/ram.ld --- a/arch/m68knommu/platform/5206/ARNEWSH/ram.ld Mon Jan 13 10:18:05 2003 +++ b/arch/m68knommu/platform/5206/ARNEWSH/ram.ld Mon Jan 13 10:18:05 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld b/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld --- a/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld Mon Jan 13 10:18:06 2003 +++ b/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld Mon Jan 13 10:18:06 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5206e/eLITE/ram.ld b/arch/m68knommu/platform/5206e/eLITE/ram.ld --- a/arch/m68knommu/platform/5206e/eLITE/ram.ld Mon Jan 13 10:18:06 2003 +++ b/arch/m68knommu/platform/5206e/eLITE/ram.ld Mon Jan 13 10:18:06 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5249/MOTOROLA/ram.ld b/arch/m68knommu/platform/5249/MOTOROLA/ram.ld --- a/arch/m68knommu/platform/5249/MOTOROLA/ram.ld Mon Jan 13 10:18:05 2003 +++ b/arch/m68knommu/platform/5249/MOTOROLA/ram.ld Mon Jan 13 10:18:05 2003 @@ -25,6 +25,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5272/MOTOROLA/ram.ld b/arch/m68knommu/platform/5272/MOTOROLA/ram.ld --- a/arch/m68knommu/platform/5272/MOTOROLA/ram.ld Mon Jan 13 10:18:07 2003 +++ b/arch/m68knommu/platform/5272/MOTOROLA/ram.ld Mon Jan 13 10:18:07 2003 @@ -25,6 +25,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5272/NETtel/ram.ld b/arch/m68knommu/platform/5272/NETtel/ram.ld --- a/arch/m68knommu/platform/5272/NETtel/ram.ld Mon Jan 13 10:18:04 2003 +++ b/arch/m68knommu/platform/5272/NETtel/ram.ld Mon Jan 13 10:18:04 2003 @@ -25,6 +25,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5307/ARNEWSH/ram.ld b/arch/m68knommu/platform/5307/ARNEWSH/ram.ld --- a/arch/m68knommu/platform/5307/ARNEWSH/ram.ld Mon Jan 13 10:18:05 2003 +++ b/arch/m68knommu/platform/5307/ARNEWSH/ram.ld Mon Jan 13 10:18:05 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld b/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld --- a/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld Mon Jan 13 10:18:05 2003 +++ b/arch/m68knommu/platform/5307/CLEOPATRA/ram.ld Mon Jan 13 10:18:05 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5307/MOTOROLA/ram.ld b/arch/m68knommu/platform/5307/MOTOROLA/ram.ld --- a/arch/m68knommu/platform/5307/MOTOROLA/ram.ld Mon Jan 13 10:18:07 2003 +++ b/arch/m68knommu/platform/5307/MOTOROLA/ram.ld Mon Jan 13 10:18:07 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5307/MP3/ram.ld b/arch/m68knommu/platform/5307/MP3/ram.ld --- a/arch/m68knommu/platform/5307/MP3/ram.ld Mon Jan 13 10:18:07 2003 +++ b/arch/m68knommu/platform/5307/MP3/ram.ld Mon Jan 13 10:18:07 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5307/NETtel/ram.ld b/arch/m68knommu/platform/5307/NETtel/ram.ld --- a/arch/m68knommu/platform/5307/NETtel/ram.ld Mon Jan 13 10:18:06 2003 +++ b/arch/m68knommu/platform/5307/NETtel/ram.ld Mon Jan 13 10:18:06 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld b/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld --- a/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld Mon Jan 13 10:18:07 2003 +++ b/arch/m68knommu/platform/5407/CLEOPATRA/ram.ld Mon Jan 13 10:18:07 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/5407/MOTOROLA/ram.ld b/arch/m68knommu/platform/5407/MOTOROLA/ram.ld --- a/arch/m68knommu/platform/5407/MOTOROLA/ram.ld Mon Jan 13 10:18:05 2003 +++ b/arch/m68knommu/platform/5407/MOTOROLA/ram.ld Mon Jan 13 10:18:05 2003 @@ -24,6 +24,11 @@ __start___ksymtab = .; /* Kernel symbol table */ *(__ksymtab) __stop___ksymtab = .; + + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(4) ; _etext = . ; } > ram diff -Nru a/arch/m68knommu/platform/68360/uCquicc/ram.ld b/arch/m68knommu/platform/68360/uCquicc/ram.ld --- a/arch/m68knommu/platform/68360/uCquicc/ram.ld Mon Jan 13 10:18:06 2003 +++ b/arch/m68knommu/platform/68360/uCquicc/ram.ld Mon Jan 13 10:18:06 2003 @@ -38,6 +38,9 @@ __start___ksymtab = . ; *(__ksymtab) __stop___ksymtab = . ; + __start___gpl_ksymtab = . ; + *(__gpl_ksymtab) + __stop___gpl_ksymtab = . ; __start___ex_table = . ; *(___ex_table) __stop___ex_table = . ; diff -Nru a/arch/m68knommu/platform/68360/uCquicc/rom.ld b/arch/m68knommu/platform/68360/uCquicc/rom.ld --- a/arch/m68knommu/platform/68360/uCquicc/rom.ld Mon Jan 13 10:18:07 2003 +++ b/arch/m68knommu/platform/68360/uCquicc/rom.ld Mon Jan 13 10:18:07 2003 @@ -38,6 +38,9 @@ __start___ksymtab = . ; *(__ksymtab) __stop___ksymtab = . ; + __start___gpl_ksymtab = . ; + *(__gpl_ksymtab) + __stop___gpl_ksymtab = . ; __start___ex_table = . ; *(___ex_table) __stop___ex_table = . ; diff -Nru a/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld b/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld --- a/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld Mon Jan 13 10:18:06 2003 +++ b/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld Mon Jan 13 10:18:06 2003 @@ -30,6 +30,10 @@ *(__ksymtab) __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(0x4) ; _etext = . ; __data_rom_start = . ; diff -Nru a/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld b/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld --- a/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld Mon Jan 13 10:18:07 2003 +++ b/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld Mon Jan 13 10:18:07 2003 @@ -51,6 +51,10 @@ *(__ksymtab) __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + _etext = . ; __data_rom_start = ALIGN ( 4 ) ; } > ram diff -Nru a/arch/m68knommu/platform/68VZ328/de2/fixed.ld b/arch/m68knommu/platform/68VZ328/de2/fixed.ld --- a/arch/m68knommu/platform/68VZ328/de2/fixed.ld Mon Jan 13 10:18:06 2003 +++ b/arch/m68knommu/platform/68VZ328/de2/fixed.ld Mon Jan 13 10:18:06 2003 @@ -29,6 +29,10 @@ *(__ksymtab) __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(0x4) ; _etext = . ; __data_rom_start = . ; diff -Nru a/arch/m68knommu/platform/68VZ328/de2/ram.ld b/arch/m68knommu/platform/68VZ328/de2/ram.ld --- a/arch/m68knommu/platform/68VZ328/de2/ram.ld Mon Jan 13 10:18:06 2003 +++ b/arch/m68knommu/platform/68VZ328/de2/ram.ld Mon Jan 13 10:18:06 2003 @@ -50,6 +50,10 @@ *(__ksymtab) __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + _etext = . ; __data_rom_start = ALIGN ( 4 ) ; } > ram diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld b/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld --- a/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld Mon Jan 13 10:18:05 2003 +++ b/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld Mon Jan 13 10:18:05 2003 @@ -29,6 +29,10 @@ *(__ksymtab) __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + . = ALIGN(0x4) ; _etext = . ; __data_rom_start = . ; diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld b/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld --- a/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld Mon Jan 13 10:18:07 2003 +++ b/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld Mon Jan 13 10:18:07 2003 @@ -50,6 +50,10 @@ *(__ksymtab) __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only */ + *(__gpl_ksymtab) + __stop___gpl_ksymtab = .; + _etext = . ; __data_rom_start = ALIGN ( 4 ) ; } > ram diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c --- a/arch/mips/mm/init.c Mon Jan 13 10:18:07 2003 +++ b/arch/mips/mm/init.c Mon Jan 13 10:18:07 2003 @@ -42,7 +42,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; extern void prom_free_prom_memory(void); diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S --- a/arch/mips/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/mips/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -29,6 +29,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + _etext = .; . = ALIGN(8192); diff -Nru a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c --- a/arch/mips64/mm/init.c Mon Jan 13 10:18:06 2003 +++ b/arch/mips64/mm/init.c Mon Jan 13 10:18:06 2003 @@ -37,7 +37,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; void pgd_init(unsigned long page) { diff -Nru a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c --- a/arch/parisc/mm/init.c Mon Jan 13 10:18:06 2003 +++ b/arch/parisc/mm/init.c Mon Jan 13 10:18:06 2003 @@ -23,7 +23,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; extern char _text; /* start of kernel code, defined by linker */ extern int data_start; diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S --- a/arch/parisc/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/parisc/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -49,6 +49,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } __stop___kallsyms = .; diff -Nru a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S --- a/arch/ppc/lib/string.S Mon Jan 13 10:18:06 2003 +++ b/arch/ppc/lib/string.S Mon Jan 13 10:18:06 2003 @@ -507,18 +507,18 @@ blr /* read fault, initial single-byte copy */ -100: li r4,0 +100: li r9,0 b 90f /* write fault, initial single-byte copy */ -101: li r4,1 +101: li r9,1 90: subf r5,r8,r5 li r3,0 b 99f /* read fault, initial word copy */ -102: li r4,0 +102: li r9,0 b 91f /* write fault, initial word copy */ -103: li r4,1 +103: li r9,1 91: li r3,2 b 99f @@ -542,38 +542,47 @@ #endif /* read fault in cacheline loop */ -104: li r4,0 +104: li r9,0 b 92f /* fault on dcbz (effectively a write fault) */ /* or write fault in cacheline loop */ -105: li r4,1 +105: li r9,1 92: li r3,LG_CACHELINE_BYTES b 99f /* read fault in final word loop */ -108: li r4,0 +108: li r9,0 b 93f /* write fault in final word loop */ -109: li r4,1 +109: li r9,1 93: andi. r5,r5,3 li r3,2 b 99f /* read fault in final byte loop */ -110: li r4,0 +110: li r9,0 b 94f /* write fault in final byte loop */ -111: li r4,1 +111: li r9,1 94: li r5,0 li r3,0 /* * At this stage the number of bytes not copied is - * r5 + (ctr << r3), and r4 is 0 for read or 1 for write. + * r5 + (ctr << r3), and r9 is 0 for read or 1 for write. */ 99: mfctr r0 slw r3,r0,r3 - add r3,r3,r5 - cmpwi 0,r4,0 + add. r3,r3,r5 + beq 120f /* shouldn't happen */ + cmpwi 0,r9,0 bne 120f -/* for read fault, clear out the destination: r3 bytes starting at 4(r6) */ +/* for a read fault, first try to continue the copy one byte at a time */ + mtctr r3 +130: lbz r0,4(r4) +131: stb r0,4(r6) + addi r4,r4,1 + addi r6,r6,1 + bdnz 130b +/* then clear out the destination: r3 bytes starting at 4(r6) */ +132: mfctr r3 srwi. r0,r3,2 li r9,0 mtctr r0 @@ -594,6 +603,8 @@ .long 31b,109b .long 40b,110b .long 41b,111b + .long 130b,132b + .long 131b,120b .long 112b,120b .long 114b,120b .text diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c --- a/arch/ppc/mm/init.c Mon Jan 13 10:18:05 2003 +++ b/arch/ppc/mm/init.c Mon Jan 13 10:18:05 2003 @@ -55,7 +55,7 @@ #endif #define MAX_LOW_MEM CONFIG_LOWMEM_SIZE -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; unsigned long total_memory; unsigned long total_lowmem; diff -Nru a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c --- a/arch/ppc/mm/tlb.c Mon Jan 13 10:18:06 2003 +++ b/arch/ppc/mm/tlb.c Mon Jan 13 10:18:06 2003 @@ -50,7 +50,7 @@ * Called at the end of a mmu_gather operation to make sure the * TLB flush is completely done. */ -void tlb_flush(mmu_gather_t *tlb) +void tlb_flush(struct mmu_gather *tlb) { if (Hash == 0) { /* diff -Nru a/arch/ppc/platforms/k2_pci.c b/arch/ppc/platforms/k2_pci.c --- a/arch/ppc/platforms/k2_pci.c Mon Jan 13 10:18:07 2003 +++ b/arch/ppc/platforms/k2_pci.c Mon Jan 13 10:18:07 2003 @@ -156,6 +156,13 @@ __raw_writel(0x00000080, K2_PCI32_BAR+PSBAR); /* Base@0x80 */ __raw_writel(0x00000000, K2_PCI32_BAR+PPBAR); + __raw_writel(0xc0000000, K2_PCI32_BAR+BPMDLK); + __raw_writel(0xd0000000, K2_PCI32_BAR+TPMDLK); + __raw_writel(0x80000000, K2_PCI32_BAR+BIODLK); + __raw_writel(0x80100000, K2_PCI32_BAR+TIODLK); + __raw_writel(0xe0008000, K2_PCI32_BAR+DLKCTRL); + __raw_writel(0xffffffff, K2_PCI32_BAR+DLKDEV); + /* PCI64 mappings */ __raw_writel(0x00100000, K2_PCI64_BAR+PIBAR); /* PCI I/O base */ __raw_writel(0x10000000, K2_PCI64_BAR+PMBAR); /* PCI Mem base */ diff -Nru a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h --- a/arch/ppc/syslib/cpc710.h Mon Jan 13 10:18:05 2003 +++ b/arch/ppc/syslib/cpc710.h Mon Jan 13 10:18:05 2003 @@ -61,6 +61,12 @@ #define BARPP 0x000f8130 #define PSBAR 0x000f8140 #define PPBAR 0x000f8150 +#define BPMDLK 0x000f8200 /* Bottom of Peripheral Memory Space */ +#define TPMDLK 0x000f8210 /* Top of Peripheral Memory Space */ +#define BIODLK 0x000f8220 /* Bottom of Peripheral I/O Space */ +#define TIODLK 0x000f8230 /* Top of Perioheral I/O Space */ +#define DLKCTRL 0x000f8240 /* Deadlock control */ +#define DLKDEV 0x000f8250 /* Deadlock device */ /* System standard configuration registers space */ #define DCR 0xff200000 diff -Nru a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c --- a/arch/ppc/syslib/mpc10x_common.c Mon Jan 13 10:18:05 2003 +++ b/arch/ppc/syslib/mpc10x_common.c Mon Jan 13 10:18:05 2003 @@ -243,6 +243,8 @@ #ifdef CONFIG_MPC10X_STORE_GATHERING mpc10x_enable_store_gathering(hose); +#else + mpc10x_disable_store_gathering(hose); #endif if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100); @@ -367,6 +369,28 @@ &picr1); picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN; + + early_write_config_dword(hose, + 0, + PCI_DEVFN(0,0), + MPC10X_CFG_PICR1_REG, + picr1); + + return 0; +} + +int __init +mpc10x_disable_store_gathering(struct pci_controller *hose) +{ + uint picr1; + + early_read_config_dword(hose, + 0, + PCI_DEVFN(0,0), + MPC10X_CFG_PICR1_REG, + &picr1); + + picr1 &= ~MPC10X_CFG_PICR1_ST_GATH_EN; early_write_config_dword(hose, 0, diff -Nru a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c --- a/arch/ppc/syslib/todc_time.c Mon Jan 13 10:18:07 2003 +++ b/arch/ppc/syslib/todc_time.c Mon Jan 13 10:18:07 2003 @@ -240,6 +240,7 @@ switch (todc_info->rtc_type) { case TODC_TYPE_DS1557: + case TODC_TYPE_DS1743: case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ case TODC_TYPE_DS1747: break; @@ -274,6 +275,7 @@ if (todc_info->rtc_type != TODC_TYPE_MC146818) { switch (todc_info->rtc_type) { case TODC_TYPE_DS1557: + case TODC_TYPE_DS1743: case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ case TODC_TYPE_DS1747: break; @@ -367,6 +369,7 @@ switch (todc_info->rtc_type) { case TODC_TYPE_DS1557: + case TODC_TYPE_DS1743: case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ case TODC_TYPE_DS1747: case TODC_TYPE_MC146818: @@ -381,6 +384,7 @@ switch (todc_info->rtc_type) { case TODC_TYPE_DS1557: + case TODC_TYPE_DS1743: case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ case TODC_TYPE_DS1747: case TODC_TYPE_MC146818: diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S --- a/arch/ppc/vmlinux.lds.S Mon Jan 13 10:18:07 2003 +++ b/arch/ppc/vmlinux.lds.S Mon Jan 13 10:18:07 2003 @@ -61,6 +61,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } __stop___kallsyms = .; diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Mon Jan 13 10:18:05 2003 +++ b/arch/ppc64/kernel/entry.S Mon Jan 13 10:18:05 2003 @@ -114,6 +114,8 @@ clrldi r4,r4,32 clrldi r5,r5,32 clrldi r6,r6,32 + clrldi r7,r7,32 + clrldi r8,r8,32 b 17f 15: #endif @@ -184,6 +186,8 @@ clrldi r4,r4,32 clrldi r5,r5,32 clrldi r6,r6,32 + clrldi r7,r7,32 + clrldi r8,r8,32 b 57f 55: #endif diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Mon Jan 13 10:18:07 2003 +++ b/arch/ppc64/kernel/misc.S Mon Jan 13 10:18:07 2003 @@ -567,8 +567,8 @@ .llong .sys32_getpriority .llong .sys32_setpriority .llong .sys_ni_syscall /* old profil syscall */ - .llong .sys32_statfs - .llong .sys32_fstatfs /* 100 */ + .llong .compat_sys_statfs + .llong .compat_sys_fstatfs /* 100 */ .llong .sys_ioperm .llong .sys32_socketcall .llong .sys32_syslog diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Mon Jan 13 10:18:07 2003 +++ b/arch/ppc64/kernel/signal32.c Mon Jan 13 10:18:07 2003 @@ -720,18 +720,11 @@ case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); } - if (uts) { - ret = get_user(t.tv_sec, &uts->tv_sec); - ret |= __get_user(t.tv_nsec, &uts->tv_nsec); - if (ret) - return -EFAULT; - } + if (uts && get_compat_timespec(&t, uts)) + return -EFAULT; set_fs(KERNEL_DS); - if (uts) - ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize); - else - ret = sys_rt_sigtimedwait(&s, &info, (struct timespec *)uts, - sigsetsize); + ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL, + sigsetsize); set_fs(old_fs); if (ret >= 0 && uinfo) { if (copy_siginfo_to_user32(uinfo, &info)) diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Mon Jan 13 10:18:06 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Mon Jan 13 10:18:06 2003 @@ -807,65 +807,6 @@ return err; } -static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) -{ - int err; - - err = put_user (kbuf->f_type, &ubuf->f_type); - err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize); - err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks); - err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree); - err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail); - err |= __put_user (kbuf->f_files, &ubuf->f_files); - err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree); - err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen); - err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]); - err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]); - return err; -} - -extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); - -asmlinkage long sys32_statfs(const char * path, struct statfs32 *buf) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - char *pth; - - pth = getname (path); - ret = PTR_ERR(pth); - if (!IS_ERR(pth)) { - set_fs (KERNEL_DS); - ret = sys_statfs((const char *)pth, &s); - set_fs (old_fs); - putname (pth); - if (put_statfs(buf, &s)) - return -EFAULT; - } - - return ret; -} - -extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf); - -asmlinkage long sys32_fstatfs(unsigned int fd, struct statfs32 *buf) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_fstatfs(fd, &s); - set_fs (old_fs); - if (put_statfs(buf, &s)) - return -EFAULT; - - return ret; -} - - - extern asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2); /* Note: it is necessary to treat option as an unsigned int, @@ -3603,10 +3544,8 @@ set_fs (KERNEL_DS); ret = sys_sched_rr_get_interval((int)pid, &t); set_fs (old_fs); - if (put_user (t.tv_sec, &interval->tv_sec) || - __put_user (t.tv_nsec, &interval->tv_nsec)) + if (put_compat_timespec(&t, interval)) return -EFAULT; - return ret; } diff -Nru a/arch/ppc64/mm/extable.c b/arch/ppc64/mm/extable.c --- a/arch/ppc64/mm/extable.c Mon Jan 13 10:18:05 2003 +++ b/arch/ppc64/mm/extable.c Mon Jan 13 10:18:05 2003 @@ -1,7 +1,7 @@ /* - * linux/arch/ppc64/mm/extable.c + * arch/ppc64/mm/extable.c * - * from linux/arch/i386/mm/extable.c + * from arch/i386/mm/extable.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,7 +11,7 @@ #include #include -#include +#include #include extern struct exception_table_entry __start___ex_table[]; @@ -45,16 +45,17 @@ } } -void +void __init sort_exception_table(void) { sort_ex_table(__start___ex_table, __stop___ex_table); } -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +/* Simple binary search */ +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) { while (first <= last) { const struct exception_table_entry *mid; @@ -63,41 +64,11 @@ mid = (last - first) / 2 + first; diff = mid->insn - value; if (diff == 0) - return mid->fixup; + return mid; else if (diff < 0) first = mid+1; else last = mid-1; } - return 0; -} - -extern spinlock_t modlist_lock; - -unsigned long -search_exception_table(unsigned long addr) -{ - unsigned long ret = 0; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); - return ret; -#else - unsigned long flags; - /* 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 || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) - continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif + return NULL; } diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c Mon Jan 13 10:18:07 2003 +++ b/arch/ppc64/mm/fault.c Mon Jan 13 10:18:07 2003 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -204,12 +205,11 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) { extern void die(const char *, struct pt_regs *, long); - - unsigned long fixup; + const struct exception_table_entry *entry; /* Are we prepared to handle this fault? */ - if ((fixup = search_exception_table(regs->nip)) != 0) { - regs->nip = fixup; + if ((entry = search_exception_tables(regs->nip)) != NULL) { + regs->nip = entry->fixup; return; } diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Mon Jan 13 10:18:06 2003 +++ b/arch/ppc64/mm/init.c Mon Jan 13 10:18:06 2003 @@ -95,7 +95,7 @@ /* This is declared as we are using the more or less generic * include/asm-ppc64/tlb.h file -- tgall */ -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; void show_mem(void) { @@ -592,36 +592,24 @@ */ void flush_dcache_page(struct page *page) { + /* avoid an atomic op if possible */ if (test_bit(PG_arch_1, &page->flags)) clear_bit(PG_arch_1, &page->flags); } -void flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - if (cpu_has_noexecute()) - return; - - if ((vma->vm_flags & VM_EXEC) == 0) - return; - - if (page->mapping && !PageReserved(page) - && !test_bit(PG_arch_1, &page->flags)) { - __flush_dcache_icache(page_address(page)); - set_bit(PG_arch_1, &page->flags); - } -} - void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); - /* XXX we shouldnt have to do this, but glibc requires it */ - if (cpu_has_noexecute()) { - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); - } else { - __flush_dcache_icache(page); - } + /* + * We shouldnt have to do this, but some versions of glibc + * require it (ld.so assumes zero filled pages are icache clean) + * - Anton + */ + + /* avoid an atomic op if possible */ + if (test_bit(PG_arch_1, &pg->flags)) + clear_bit(PG_arch_1, &pg->flags); } void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, @@ -630,20 +618,23 @@ copy_page(vto, vfrom); /* - * Unfortunately we havent always marked our GOT and PLT sections - * as executable, so we need to flush all file regions - Anton + * We should be able to use the following optimisation, however + * there are two problems. + * Firstly a bug in some versions of binutils meant PLT sections + * were not marked executable. + * Secondly the first word in the GOT section is blrl, used + * to establish the GOT address. Until recently the GOT was + * not marked executable. + * - Anton */ #if 0 if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0)) return; #endif - if (cpu_has_noexecute()) { - if (test_bit(PG_arch_1, &pg->flags)) - clear_bit(PG_arch_1, &pg->flags); - } else { - __flush_dcache_icache(vto); - } + /* avoid an atomic op if possible */ + if (test_bit(PG_arch_1, &pg->flags)) + clear_bit(PG_arch_1, &pg->flags); } void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, @@ -674,6 +665,19 @@ void *pgdir; pte_t *ptep; int local = 0; + + /* handle i-cache coherency */ + if (!cpu_has_noexecute()) { + unsigned long pfn = pte_pfn(pte); + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); + if (!PageReserved(page) + && !test_bit(PG_arch_1, &page->flags)) { + __flush_dcache_icache(page_address(page)); + set_bit(PG_arch_1, &page->flags); + } + } + } /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ if (!pte_young(pte)) diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S --- a/arch/ppc64/vmlinux.lds.S Mon Jan 13 10:18:07 2003 +++ b/arch/ppc64/vmlinux.lds.S Mon Jan 13 10:18:07 2003 @@ -69,6 +69,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } __stop___kallsyms = .; diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c --- a/arch/s390/mm/init.c Mon Jan 13 10:18:07 2003 +++ b/arch/s390/mm/init.c Mon Jan 13 10:18:07 2003 @@ -38,7 +38,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S --- a/arch/s390/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/s390/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -30,6 +30,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + #ifdef CONFIG_SHARED_KERNEL . = ALIGN(1048576); /* VM shared segments are 1MB aligned */ diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S --- a/arch/s390x/kernel/entry.S Mon Jan 13 10:18:05 2003 +++ b/arch/s390x/kernel/entry.S Mon Jan 13 10:18:05 2003 @@ -490,8 +490,8 @@ .long SYSCALL(sys_getpriority,sys32_getpriority_wrapper) .long SYSCALL(sys_setpriority,sys32_setpriority_wrapper) .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old profil syscall */ - .long SYSCALL(sys_statfs,sys32_statfs_wrapper) - .long SYSCALL(sys_fstatfs,sys32_fstatfs_wrapper) /* 100 */ + .long SYSCALL(sys_statfs,compat_sys_statfs_wrapper) + .long SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper) /* 100 */ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) .long SYSCALL(sys_socketcall,sys32_socketcall_wrapper) .long SYSCALL(sys_syslog,sys32_syslog_wrapper) diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c --- a/arch/s390x/kernel/linux32.c Mon Jan 13 10:18:06 2003 +++ b/arch/s390x/kernel/linux32.c Mon Jan 13 10:18:06 2003 @@ -884,61 +884,6 @@ return sys32_fcntl(fd, cmd, arg); } -static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) -{ - int err; - - err = put_user (kbuf->f_type, &ubuf->f_type); - err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize); - err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks); - err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree); - err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail); - err |= __put_user (kbuf->f_files, &ubuf->f_files); - err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree); - err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen); - err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]); - err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]); - return err; -} - -extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); - -asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - char *pth; - - pth = getname (path); - ret = PTR_ERR(pth); - if (!IS_ERR(pth)) { - set_fs (KERNEL_DS); - ret = sys_statfs((const char *)pth, &s); - set_fs (old_fs); - putname (pth); - if (put_statfs(buf, &s)) - return -EFAULT; - } - return ret; -} - -extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf); - -asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_fstatfs(fd, &s); - set_fs (old_fs); - if (put_statfs(buf, &s)) - return -EFAULT; - return ret; -} - extern asmlinkage long sys_truncate(const char * path, unsigned long length); extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); diff -Nru a/arch/s390x/kernel/linux32.h b/arch/s390x/kernel/linux32.h --- a/arch/s390x/kernel/linux32.h Mon Jan 13 10:18:07 2003 +++ b/arch/s390x/kernel/linux32.h Mon Jan 13 10:18:07 2003 @@ -25,19 +25,6 @@ #define F_SETLK64 13 #define F_SETLKW64 14 -struct statfs32 { - __s32 f_type; - __s32 f_bsize; - __s32 f_blocks; - __s32 f_bfree; - __s32 f_bavail; - __s32 f_files; - __s32 f_ffree; - __kernel_fsid_t f_fsid; - __s32 f_namelen; - __s32 f_spare[6]; -}; - typedef __u32 old_sigset_t32; /* at least 32 bits */ struct old_sigaction32 { diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S --- a/arch/s390x/kernel/wrapper32.S Mon Jan 13 10:18:07 2003 +++ b/arch/s390x/kernel/wrapper32.S Mon Jan 13 10:18:07 2003 @@ -440,17 +440,17 @@ lgfr %r4,%r4 # int jg sys_setpriority # branch to system call - .globl sys32_statfs_wrapper -sys32_statfs_wrapper: + .globl compat_sys_statfs_wrapper +compat_sys_statfs_wrapper: llgtr %r2,%r2 # char * - llgtr %r3,%r3 # struct statfs_emu31 * - jg sys32_statfs # branch to system call + llgtr %r3,%r3 # struct compat_statfs * + jg compat_sys_statfs # branch to system call - .globl sys32_fstatfs_wrapper -sys32_fstatfs_wrapper: + .globl compat_sys_fstatfs_wrapper +compat_sys_fstatfs_wrapper: llgfr %r2,%r2 # unsigned int - llgtr %r3,%r3 # struct statfs_emu31 * - jg sys32_fstatfs # branch to system call + llgtr %r3,%r3 # struct compat_statfs * + jg compat_sys_fstatfs # branch to system call .globl sys32_socketcall_wrapper sys32_socketcall_wrapper: diff -Nru a/arch/s390x/mm/init.c b/arch/s390x/mm/init.c --- a/arch/s390x/mm/init.c Mon Jan 13 10:18:05 2003 +++ b/arch/s390x/mm/init.c Mon Jan 13 10:18:05 2003 @@ -38,7 +38,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S --- a/arch/s390x/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/s390x/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -30,6 +30,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + #ifdef CONFIG_SHARED_KERNEL . = ALIGN(1048576); /* VM shared segments are 1MB aligned */ diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c --- a/arch/sh/mm/init.c Mon Jan 13 10:18:07 2003 +++ b/arch/sh/mm/init.c Mon Jan 13 10:18:07 2003 @@ -36,7 +36,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; /* * Cache of MMU context last used. diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S --- a/arch/sh/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/sh/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -37,6 +37,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } __stop___kallsyms = .; diff -Nru a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c --- a/arch/sparc/mm/init.c Mon Jan 13 10:18:06 2003 +++ b/arch/sparc/mm/init.c Mon Jan 13 10:18:06 2003 @@ -34,7 +34,7 @@ #include /* bug in asm-generic/tlb.h: check_pgt_cache */ #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; unsigned long *sparc_valid_addr_bitmap; diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S --- a/arch/sparc/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/sparc/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -35,6 +35,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } __stop___kallsyms = .; diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Mon Jan 13 10:18:06 2003 +++ b/arch/sparc64/kernel/sys_sparc32.c Mon Jan 13 10:18:06 2003 @@ -840,61 +840,6 @@ return sys32_fcntl(fd, cmd, arg); } -static int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) -{ - int err; - - err = put_user (kbuf->f_type, &ubuf->f_type); - err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize); - err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks); - err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree); - err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail); - err |= __put_user (kbuf->f_files, &ubuf->f_files); - err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree); - err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen); - err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]); - err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]); - return err; -} - -extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); - -asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - char *pth; - - pth = getname (path); - ret = PTR_ERR(pth); - if (!IS_ERR(pth)) { - set_fs (KERNEL_DS); - ret = sys_statfs((const char *)pth, &s); - set_fs (old_fs); - putname (pth); - if (put_statfs(buf, &s)) - return -EFAULT; - } - return ret; -} - -extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf); - -asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_fstatfs(fd, &s); - set_fs (old_fs); - if (put_statfs(buf, &s)) - return -EFAULT; - return ret; -} - extern asmlinkage long sys_truncate(const char * path, unsigned long length); extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S Mon Jan 13 10:18:06 2003 +++ b/arch/sparc64/kernel/systbls.S Mon Jan 13 10:18:06 2003 @@ -50,7 +50,7 @@ /*140*/ .word sys32_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys32_getrlimit .word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 - .word sys32_fcntl64, sys_ni_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount + .word sys32_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall .word sys_quotactl, sys_set_tid_address, sys32_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents @@ -197,7 +197,7 @@ .word sunos_nosys, sunos_nosys /*150*/ .word sys_getsockname, sunos_nosys, sunos_nosys .word sys_poll, sunos_nosys, sunos_nosys - .word sunos_getdirentries, sys32_statfs, sys32_fstatfs + .word sunos_getdirentries, compat_sys_statfs, compat_sys_fstatfs .word sys_oldumount, sunos_nosys, sunos_nosys .word sys_getdomainname, sys_setdomainname .word sunos_nosys, sys_quotactl, sunos_nosys diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c --- a/arch/sparc64/mm/init.c Mon Jan 13 10:18:05 2003 +++ b/arch/sparc64/mm/init.c Mon Jan 13 10:18:05 2003 @@ -36,7 +36,7 @@ #include #include -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; extern void device_scan(void); diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S --- a/arch/sparc64/vmlinux.lds.S Mon Jan 13 10:18:07 2003 +++ b/arch/sparc64/vmlinux.lds.S Mon Jan 13 10:18:07 2003 @@ -39,6 +39,9 @@ __start___ksymtab = .; __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; __kstrtab : { *(.kstrtab) } __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c --- a/arch/um/kernel/mem.c Mon Jan 13 10:18:05 2003 +++ b/arch/um/kernel/mem.c Mon Jan 13 10:18:05 2003 @@ -44,7 +44,7 @@ extern long physmem_size; /* Not changed by UML */ -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; /* Changed during early boot */ int kmalloc_ok = 0; diff -Nru a/arch/v850/README b/arch/v850/README --- a/arch/v850/README Mon Jan 13 10:18:07 2003 +++ b/arch/v850/README Mon Jan 13 10:18:07 2003 @@ -1,7 +1,6 @@ This port to the NEC V850E processor supports the following platforms: - + The gdb v850e simulator (CONFIG_V850E_SIM); see the subdirectory `sim' - for some more support files for this. + + The gdb v850e simulator (CONFIG_V850E_SIM). + The Midas labs RTE-V850E/MA1-CB evaluation board (CONFIG_RTE_CB_MA1), with untested support for the RTE-V850E/NB85E-CB board diff -Nru a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c --- a/arch/v850/kernel/as85ep1.c Mon Jan 13 10:18:07 2003 +++ b/arch/v850/kernel/as85ep1.c Mon Jan 13 10:18:07 2003 @@ -44,8 +44,10 @@ void __init mach_early_init (void) { +#ifndef CONFIG_ROM_KERNEL const u32 *src; register u32 *dst asm ("ep"); +#endif AS85EP1_CSC(0) = 0x0403; AS85EP1_BCT(0) = 0xB8B8; @@ -53,25 +55,28 @@ AS85EP1_BCC = 0x0012; AS85EP1_ASC = 0; AS85EP1_LBS = 0x00A9; - AS85EP1_RFS(1) = 0x8205; - AS85EP1_RFS(3) = 0x8205; - AS85EP1_SCR(1) = 0x20A9; - AS85EP1_SCR(3) = 0x20A9; AS85EP1_PORT_PMC(6) = 0xFF; /* A20-25, A0,A1 $BM-8z(B */ AS85EP1_PORT_PMC(7) = 0x0E; /* CS1,2,3 $BM-8z(B */ AS85EP1_PORT_PMC(9) = 0xFF; /* D16-23 $BM-8z(B */ AS85EP1_PORT_PMC(10) = 0xFF; /* D24-31 $BM-8z(B */ - AS85EP1_IRAMM = 0x3; /* $BFbB"L?Na(BRAM$B$O!V(Bwrite-mode$B!W$K$J$j$^$9(B */ + AS85EP1_RFS(1) = 0x800c; + AS85EP1_RFS(3) = 0x800c; + AS85EP1_SCR(1) = 0x20A9; + AS85EP1_SCR(3) = 0x20A9; - /* The early chip we have is buggy, so that writing the interrupt +#ifndef CONFIG_ROM_KERNEL + /* The early chip we have is buggy, and writing the interrupt vectors into low RAM may screw up, so for non-ROM kernels, we only rely on the reset vector being downloaded, and copy the rest of the interrupt vectors into place here. The specific bug is that writing address N, where (N & 0x10) == 0x10, will _also_ write to address (N - 0x10). We avoid this (effectively) by writing in 16-byte chunks backwards from the end. */ + + AS85EP1_IRAMM = 0x3; /* $BFbB"L?Na(BRAM$B$O!V(Bwrite-mode$B!W$K$J$j$^$9(B */ + src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF); dst = (u32 *)&_intv_copy_dst_start + (src - (u32 *)&_intv_copy_src_start); @@ -83,6 +88,7 @@ } while (src > (u32 *)&_intv_copy_src_start); AS85EP1_IRAMM = 0x0; /* $BFbB"L?Na(BRAM$B$O!V(Bread-mode$B!W$K$J$j$^$9(B */ +#endif /* !CONFIG_ROM_KERNEL */ nb85e_intc_disable_irqs (); } @@ -107,16 +113,20 @@ *ram_len = RAM_END - RAM_START; } +/* Convenience macros. */ +#define SRAM_END (SRAM_ADDR + SRAM_SIZE) +#define SDRAM_END (SDRAM_ADDR + SDRAM_SIZE) + void __init mach_reserve_bootmem () { extern char _root_fs_image_start, _root_fs_image_end; u32 root_fs_image_start = (u32)&_root_fs_image_start; u32 root_fs_image_end = (u32)&_root_fs_image_end; - /* We can't use the space between SRAM and SDRAM, so prevent the - kernel from trying. */ - reserve_bootmem (SRAM_ADDR + SRAM_SIZE, - SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE)); + if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START) + /* We can't use the space between SRAM and SDRAM, so + prevent the kernel from trying. */ + reserve_bootmem (SRAM_END, SDRAM_ADDR - SRAM_END); /* Reserve the memory used by the root filesystem image if it's in RAM. */ diff -Nru a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c --- a/arch/v850/kernel/module.c Mon Jan 13 10:18:05 2003 +++ b/arch/v850/kernel/module.c Mon Jan 13 10:18:05 2003 @@ -1,9 +1,9 @@ /* * arch/v850/kernel/module.c -- Architecture-specific module functions * - * Copyright (C) 2002 NEC Corporation - * Copyright (C) 2002 Miles Bader - * Copyright (C) 2001 Rusty Russell + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * Copyright (C) 2001,03 Rusty Russell * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -100,18 +100,31 @@ return ret; } -long module_core_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, - const char *secstrings, struct module *mod) +int module_frob_arch_sections(Elf32_Ehdr *hdr, + Elf32_Shdr *sechdrs, + char *secstrings, + struct module *me) { - mod->arch.core_plt_offset = (mod->core_size + 3) & ~3; - return mod->core_size + get_plt_size (hdr, sechdrs, secstrings, 1); -} + unsigned int i; -long module_init_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, - const char *secstrings, struct module *mod) -{ - mod->arch.init_plt_offset = (mod->init_size + 3) & ~3; - return mod->init_size + get_plt_size (hdr, sechdrs, secstrings, 1); + /* Find .plt and .pltinit sections */ + for (i = 0; i < hdr->e_shnum; i++) { + if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0) + me->arch.init_plt_section = i; + else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0) + me->arch.core_plt_section = i; + } + if (!me->arch.core_plt_section || !me->arch.init_plt_section) { + printk("Module doesn't contain .plt or .plt.init sections.\n"); + return -ENOEXEC; + } + + /* Override their sizes */ + sechdrs[me->arch.core_plt_section].sh_size + = get_plt_size(hdr, sechdrs, secstrings, 0); + sechdrs[me->arch.init_plt_section].sh_size + = get_plt_size(hdr, sechdrs, secstrings, 1); + return 0; } int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab, @@ -123,7 +136,8 @@ } /* Set up a trampoline in the PLT to bounce us to the distant function */ -static uint32_t do_plt_call(void *location, Elf32_Addr val, struct module *mod) +static uint32_t do_plt_call (void *location, Elf32_Addr val, + Elf32_Shdr *sechdrs, struct module *mod) { struct v850_plt_entry *entry; /* Instructions used to do the indirect jump. */ @@ -137,10 +151,10 @@ /* Init, or core PLT? */ if (location >= mod->module_core - && location < mod->module_core + mod->arch.core_plt_offset) - entry = mod->module_core + mod->arch.core_plt_offset; + && location < mod->module_core + mod->core_size) + entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; else - entry = mod->module_init + mod->arch.init_plt_offset; + entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; /* Find this entry, or if that fails, the next avail. entry */ while (entry->tramp[0]) @@ -199,7 +213,7 @@ /* Maybe jump indirectly via a PLT table entry. */ if ((int32_t)(val - (uint32_t)loc) > 0x1fffff || (int32_t)(val - (uint32_t)loc) < -0x200000) - val = do_plt_call (loc, val, mod); + val = do_plt_call (loc, val, sechdrs, mod); val -= (uint32_t)loc; diff -Nru a/arch/v850/vmlinux.lds.S b/arch/v850/vmlinux.lds.S --- a/arch/v850/vmlinux.lds.S Mon Jan 13 10:18:06 2003 +++ b/arch/v850/vmlinux.lds.S Mon Jan 13 10:18:06 2003 @@ -1,8 +1,8 @@ /* * arch/v850/vmlinux.lds.S -- kernel linker script for v850 platforms * - * Copyright (C) 2002 NEC Electronics Corporation - * Copyright (C) 2002 Miles Bader + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -51,6 +51,9 @@ ___start___ksymtab = . ;/* Kernel symbol table. */ \ *(__ksymtab) \ ___stop___ksymtab = . ; \ + ___start___gpl_ksymtab = . ; /* Same for GPL symbols. */ \ + *(__gpl_ksymtab) \ + ___stop___gpl_ksymtab = . ; \ . = ALIGN (4) ; \ __etext = . ; diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c --- a/arch/x86_64/mm/init.c Mon Jan 13 10:18:05 2003 +++ b/arch/x86_64/mm/init.c Mon Jan 13 10:18:05 2003 @@ -40,7 +40,7 @@ unsigned long start_pfn, end_pfn; -mmu_gather_t mmu_gathers[NR_CPUS]; +struct mmu_gather mmu_gathers[NR_CPUS]; /* * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S --- a/arch/x86_64/vmlinux.lds.S Mon Jan 13 10:18:05 2003 +++ b/arch/x86_64/vmlinux.lds.S Mon Jan 13 10:18:05 2003 @@ -30,6 +30,9 @@ __start___ksymtab = .; /* Kernel symbol table */ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ + __gpl_ksymtab : { *(__gpl_ksymtab) } + __stop___gpl_ksymtab = .; __start___kallsyms = .; /* All kernel symbols */ __kallsyms : { *(__kallsyms) } diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c --- a/drivers/acorn/scsi/cumana_2.c Mon Jan 13 10:18:06 2003 +++ b/drivers/acorn/scsi/cumana_2.c Mon Jan 13 10:18:06 2003 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -163,26 +164,27 @@ fasdmadir_t direction, fasdmatype_t min_type) { struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; + struct device *dev = scsi_get_device(host); int dmach = host->dma_channel; outb(ALATCH_DIS_DMA, info->alatch); if (dmach != NO_DMA && (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs, pci_dir, dma_dir, alatch_dir; + int bufs, map_dir, dma_dir, alatch_dir; bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); if (direction == DMA_OUT) - pci_dir = PCI_DMA_TODEVICE, + map_dir = DMA_TO_DEVICE, dma_dir = DMA_MODE_WRITE, alatch_dir = ALATCH_DMA_OUT; else - pci_dir = PCI_DMA_FROMDEVICE, + map_dir = DMA_FROM_DEVICE, dma_dir = DMA_MODE_READ, alatch_dir = ALATCH_DMA_IN; - pci_map_sg(NULL, info->sg, bufs + 1, pci_dir); + dma_map_sg(dev, info->sg, bufs + 1, map_dir); disable_dma(dmach); set_dma_sg(dmach, info->sg, bufs + 1); diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c --- a/drivers/acorn/scsi/eesox.c Mon Jan 13 10:18:07 2003 +++ b/drivers/acorn/scsi/eesox.c Mon Jan 13 10:18:07 2003 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -165,22 +166,23 @@ fasdmadir_t direction, fasdmatype_t min_type) { struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; + struct device *dev = scsi_get_device(host); int dmach = host->dma_channel; if (dmach != NO_DMA && (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs, pci_dir, dma_dir; + int bufs, map_dir, dma_dir; bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); if (direction == DMA_OUT) - pci_dir = PCI_DMA_TODEVICE, + map_dir = DMA_TO_DEVICE, dma_dir = DMA_MODE_WRITE; else - pci_dir = PCI_DMA_FROMDEVICE, + map_dir = DMA_FROM_DEVICE, dma_dir = DMA_MODE_READ; - pci_map_sg(NULL, info->sg, bufs + 1, pci_dir); + dma_map_sg(dev, info->sg, bufs + 1, map_dir); disable_dma(dmach); set_dma_sg(dmach, info->sg, bufs + 1); diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c --- a/drivers/acorn/scsi/powertec.c Mon Jan 13 10:18:06 2003 +++ b/drivers/acorn/scsi/powertec.c Mon Jan 13 10:18:06 2003 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -135,22 +136,23 @@ fasdmadir_t direction, fasdmatype_t min_type) { struct powertec_info *info = (struct powertec_info *)host->hostdata; + struct device *dev = scsi_get_device(host); int dmach = host->dma_channel; if (dmach != NO_DMA && (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs, pci_dir, dma_dir; + int bufs, map_dir, dma_dir; bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); if (direction == DMA_OUT) - pci_dir = PCI_DMA_TODEVICE, + map_dir = DMA_TO_DEVICE, dma_dir = DMA_MODE_WRITE; else - pci_dir = PCI_DMA_FROMDEVICE, + map_dir = DMA_FROM_DEVICE, dma_dir = DMA_MODE_READ; - pci_map_sg(NULL, info->sg, bufs + 1, pci_dir); + dma_map_sg(dev, info->sg, bufs + 1, map_dir); disable_dma(dmach); set_dma_sg(dmach, info->sg, bufs + 1); diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Mon Jan 13 10:18:05 2003 +++ b/drivers/base/bus.c Mon Jan 13 10:18:05 2003 @@ -31,28 +31,26 @@ static ssize_t -drv_attr_show(struct kobject * kobj, struct attribute * attr, - char * buf, size_t count, loff_t off) +drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) { struct driver_attribute * drv_attr = to_drv_attr(attr); struct device_driver * drv = to_driver(kobj); ssize_t ret = 0; if (drv_attr->show) - ret = drv_attr->show(drv,buf,count,off); + ret = drv_attr->show(drv,buf); return ret; } static ssize_t -drv_attr_store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count, loff_t off) +drv_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf) { struct driver_attribute * drv_attr = to_drv_attr(attr); struct device_driver * drv = to_driver(kobj); ssize_t ret = 0; if (drv_attr->store) - ret = drv_attr->store(drv,buf,count,off); + ret = drv_attr->store(drv,buf); return ret; } @@ -80,28 +78,26 @@ static ssize_t -bus_attr_show(struct kobject * kobj, struct attribute * attr, - char * buf, size_t count, loff_t off) +bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) { struct bus_attribute * bus_attr = to_bus_attr(attr); struct bus_type * bus = to_bus(kobj); ssize_t ret = 0; if (bus_attr->show) - ret = bus_attr->show(bus,buf,count,off); + ret = bus_attr->show(bus,buf); return ret; } static ssize_t -bus_attr_store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count, loff_t off) +bus_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf) { struct bus_attribute * bus_attr = to_bus_attr(attr); struct bus_type * bus = to_bus(kobj); ssize_t ret = 0; if (bus_attr->store) - ret = bus_attr->store(bus,buf,count,off); + ret = bus_attr->store(bus,buf); return ret; } @@ -316,12 +312,14 @@ * If bus_match() returns 0 and the @dev->driver is set, we've found * a compatible pair, so we call devclass_add_device() to add the * device to the class. + * + * Note that we ignore the error from bus_match(), since it's perfectly + * valid for a driver not to bind to any devices. */ static int driver_attach(struct device_driver * drv) { struct bus_type * bus = drv->bus; struct list_head * entry; - int error = 0; if (!bus->match) return 0; @@ -333,7 +331,7 @@ devclass_add_device(dev); } } - return error; + return 0; } @@ -387,15 +385,18 @@ int bus_add_device(struct device * dev) { struct bus_type * bus = get_bus(dev->bus); + int error = 0; + if (bus) { down_write(&dev->bus->subsys.rwsem); pr_debug("bus %s: add device %s\n",bus->name,dev->bus_id); list_add_tail(&dev->bus_list,&dev->bus->devices.list); - device_attach(dev); + if ((error = device_attach(dev))) + list_del_init(&dev->bus_list); up_write(&dev->bus->subsys.rwsem); sysfs_create_link(&bus->devices.kobj,&dev->kobj,dev->bus_id); } - return 0; + return error; } /** @@ -429,19 +430,33 @@ int bus_add_driver(struct device_driver * drv) { struct bus_type * bus = get_bus(drv->bus); + int error = 0; + if (bus) { pr_debug("bus %s: add driver %s\n",bus->name,drv->name); strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN); drv->kobj.kset = &bus->drivers; - kobject_register(&drv->kobj); + + if ((error = kobject_register(&drv->kobj))) { + put_bus(bus); + return error; + } down_write(&bus->subsys.rwsem); - devclass_add_driver(drv); - driver_attach(drv); + if (!(error = devclass_add_driver(drv))) { + if ((error = driver_attach(drv))) { + devclass_remove_driver(drv); + } + } up_write(&bus->subsys.rwsem); + + if (error) { + kobject_unregister(&drv->kobj); + put_bus(bus); + } } - return 0; + return error; } diff -Nru a/drivers/base/class.c b/drivers/base/class.c --- a/drivers/base/class.c Mon Jan 13 10:18:07 2003 +++ b/drivers/base/class.c Mon Jan 13 10:18:07 2003 @@ -2,7 +2,7 @@ * class.c - basic device class management */ -#define DEBUG +#undef DEBUG #include #include @@ -14,28 +14,26 @@ #define to_class(obj) container_of(obj,struct device_class,subsys.kset.kobj) static ssize_t -devclass_attr_show(struct kobject * kobj, struct attribute * attr, - char * buf, size_t count, loff_t off) +devclass_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) { struct devclass_attribute * class_attr = to_class_attr(attr); struct device_class * dc = to_class(kobj); ssize_t ret = 0; if (class_attr->show) - ret = class_attr->show(dc,buf,count,off); + ret = class_attr->show(dc,buf); return ret; } static ssize_t -devclass_attr_store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count, loff_t off) +devclass_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf) { struct devclass_attribute * class_attr = to_class_attr(attr); struct device_class * dc = to_class(kobj); ssize_t ret = 0; if (class_attr->store) - ret = class_attr->store(dc,buf,count,off); + ret = class_attr->store(dc,buf); return ret; } @@ -100,15 +98,19 @@ int devclass_add_driver(struct device_driver * drv) { struct device_class * cls = get_devclass(drv->devclass); + int error = 0; + if (cls) { down_write(&cls->subsys.rwsem); pr_debug("device class %s: adding driver %s:%s\n", cls->name,drv->bus->name,drv->name); - list_add_tail(&drv->class_list,&cls->drivers.list); - devclass_drv_link(drv); + error = devclass_drv_link(drv); + + if (!error) + list_add_tail(&drv->class_list,&cls->drivers.list); up_write(&cls->subsys.rwsem); } - return 0; + return error; } void devclass_remove_driver(struct device_driver * drv) diff -Nru a/drivers/base/core.c b/drivers/base/core.c --- a/drivers/base/core.c Mon Jan 13 10:18:05 2003 +++ b/drivers/base/core.c Mon Jan 13 10:18:05 2003 @@ -35,28 +35,26 @@ extern struct attribute * dev_default_attrs[]; static ssize_t -dev_attr_show(struct kobject * kobj, struct attribute * attr, - char * buf, size_t count, loff_t off) +dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) { struct device_attribute * dev_attr = to_dev_attr(attr); struct device * dev = to_dev(kobj); ssize_t ret = 0; if (dev_attr->show) - ret = dev_attr->show(dev,buf,count,off); + ret = dev_attr->show(dev,buf); return ret; } static ssize_t -dev_attr_store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count, loff_t off) +dev_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf) { struct device_attribute * dev_attr = to_dev_attr(attr); struct device * dev = to_dev(kobj); ssize_t ret = 0; if (dev_attr->store) - ret = dev_attr->store(dev,buf,count,off); + ret = dev_attr->store(dev,buf); return ret; } diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c --- a/drivers/base/driver.c Mon Jan 13 10:18:07 2003 +++ b/drivers/base/driver.c Mon Jan 13 10:18:07 2003 @@ -3,7 +3,7 @@ * */ -#define DEBUG +#undef DEBUG #include #include diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c --- a/drivers/base/interface.c Mon Jan 13 10:18:05 2003 +++ b/drivers/base/interface.c Mon Jan 13 10:18:05 2003 @@ -10,21 +10,21 @@ #include #include -static ssize_t device_read_name(struct device * dev, char * buf, size_t count, loff_t off) +static ssize_t device_read_name(struct device * dev, char * buf) { - return off ? 0 : sprintf(buf,"%s\n",dev->name); + return sprintf(buf,"%s\n",dev->name); } static DEVICE_ATTR(name,S_IRUGO,device_read_name,NULL); static ssize_t -device_read_power(struct device * dev, char * page, size_t count, loff_t off) +device_read_power(struct device * dev, char * page) { - return off ? 0 : sprintf(page,"%d\n",dev->power_state); + return sprintf(page,"%d\n",dev->power_state); } static ssize_t -device_write_power(struct device * dev, const char * buf, size_t count, loff_t off) +device_write_power(struct device * dev, const char * buf) { char str_command[20]; char str_level[20]; @@ -33,9 +33,6 @@ u32 int_level; int error = 0; - if (off) - return 0; - if (!dev->driver) goto done; @@ -83,7 +80,7 @@ error = 0; } done: - return error < 0 ? error : count; + return error < 0 ? error : strlen(buf); } static DEVICE_ATTR(power,S_IWUSR | S_IRUGO, diff -Nru a/drivers/base/intf.c b/drivers/base/intf.c --- a/drivers/base/intf.c Mon Jan 13 10:18:07 2003 +++ b/drivers/base/intf.c Mon Jan 13 10:18:07 2003 @@ -2,7 +2,7 @@ * intf.c - class-specific interface management */ -#define DEBUG +#undef DEBUG #include #include @@ -66,8 +66,7 @@ kobject_register(&data->kobj); list_add_tail(&data->dev_entry,&data->dev->intf_list); - intf_dev_link(data); - return 0; + return intf_dev_link(data); } return -EINVAL; } diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c --- a/drivers/base/sys.c Mon Jan 13 10:18:04 2003 +++ b/drivers/base/sys.c Mon Jan 13 10:18:04 2003 @@ -80,7 +80,7 @@ * and @root->dev. * If both are 0, they will be cleaned up by the core. */ -void sys_unegister_root(struct sys_root * root) +void sys_unregister_root(struct sys_root *root) { device_unregister(&root->sysdev); device_unregister(&root->dev); diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Mon Jan 13 10:18:06 2003 +++ b/drivers/block/genhd.c Mon Jan 13 10:18:06 2003 @@ -276,17 +276,17 @@ struct disk_attribute { struct attribute attr; - ssize_t (*show)(struct gendisk *, char *, size_t, loff_t); + ssize_t (*show)(struct gendisk *, char *); }; static ssize_t disk_attr_show(struct kobject * kobj, struct attribute * attr, - char * page, size_t count, loff_t off) + char * page) { struct gendisk * disk = to_disk(kobj); struct disk_attribute * disk_attr = container_of(attr,struct disk_attribute,attr); ssize_t ret = 0; if (disk_attr->show) - ret = disk_attr->show(disk,page,count,off); + ret = disk_attr->show(disk,page); return ret; } @@ -294,21 +294,18 @@ .show = &disk_attr_show, }; -static ssize_t disk_dev_read(struct gendisk * disk, - char *page, size_t count, loff_t off) +static ssize_t disk_dev_read(struct gendisk * disk, char *page) { dev_t base = MKDEV(disk->major, disk->first_minor); - return off ? 0 : sprintf(page, "%04x\n",base); + return sprintf(page, "%04x\n",base); } -static ssize_t disk_range_read(struct gendisk * disk, - char *page, size_t count, loff_t off) +static ssize_t disk_range_read(struct gendisk * disk, char *page) { - return off ? 0 : sprintf(page, "%d\n",disk->minors); + return sprintf(page, "%d\n",disk->minors); } -static ssize_t disk_size_read(struct gendisk * disk, - char *page, size_t count, loff_t off) +static ssize_t disk_size_read(struct gendisk * disk, char *page) { - return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk)); + return sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk)); } static inline unsigned jiffies_to_msec(unsigned jif) @@ -321,11 +318,10 @@ return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ; #endif } -static ssize_t disk_stat_read(struct gendisk * disk, - char *page, size_t count, loff_t off) +static ssize_t disk_stat_read(struct gendisk * disk, char *page) { disk_round_stats(disk); - return off ? 0 : sprintf(page, + return sprintf(page, "%8u %8u %8llu %8u " "%8u %8u %8llu %8u " "%8u %8u %8u" diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Mon Jan 13 10:18:07 2003 +++ b/drivers/block/umem.c Mon Jan 13 10:18:07 2003 @@ -371,11 +371,12 @@ { request_queue_t *q = data; struct cardinfo *card = q->queuedata; + unsigned long flags; - spin_lock_bh(&card->lock); + spin_lock_irqsave(&card->lock, flags); if (blk_remove_plug(q)) activate(card); - spin_unlock_bh(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); } /* @@ -557,12 +558,12 @@ PRINTK("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size); bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/ - spin_lock_bh(&card->lock); + spin_lock_irq(&card->lock); *card->biotail = bio; bio->bi_next = NULL; card->biotail = &bio->bi_next; blk_plug_device(q); - spin_unlock_bh(&card->lock); + spin_unlock_irq(&card->lock); return 0; } diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c --- a/drivers/char/rio/rioctrl.c Mon Jan 13 10:18:06 2003 +++ b/drivers/char/rio/rioctrl.c Mon Jan 13 10:18:06 2003 @@ -203,7 +203,7 @@ func_enter (); - /* Confuse teh compiler to think that we've initialized these */ + /* Confuse the compiler to think that we've initialized these */ Host=0; PortP = NULL; diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig --- a/drivers/char/watchdog/Kconfig Mon Jan 13 10:18:06 2003 +++ b/drivers/char/watchdog/Kconfig Mon Jan 13 10:18:06 2003 @@ -168,6 +168,19 @@ Not sure? It's safe to say N. +config SA1100_WATCHDOG + tristate "SA1100 watchdog" + depends on WATCHDOG && ARCH_SA1100 + help + Watchdog timer embedded into SA11x0 chips. This will reboot your + system when timeout is reached. + NOTE, that once enabled, this timer cannot be disabled. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + If you want to compile it as a module, say M here and read + Documentation/modules.txt. The module will be called sa1100_wdt.o. + config EUROTECH_WDT tristate "Eurotech CPU-1220/1410 Watchdog Timer" depends on WATCHDOG diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile --- a/drivers/char/watchdog/Makefile Mon Jan 13 10:18:06 2003 +++ b/drivers/char/watchdog/Makefile Mon Jan 13 10:18:06 2003 @@ -21,6 +21,7 @@ obj-$(CONFIG_I810_TCO) += i810-tco.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SH_WDT) += shwdt.o +obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o diff -Nru a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/sa1100_wdt.c Mon Jan 13 10:18:07 2003 @@ -0,0 +1,217 @@ +/* + * Watchdog driver for the SA11x0 + * + * (c) Copyright 2000 Oleg Drokin + * Based on SoftDog driver by Alan Cox + * + * 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 Oleg Drokin nor iXcelerator.com admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 Oleg Drokin + * + * 27/11/2000 Initial release + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define OSCR_FREQ 3686400 +#define SA1100_CLOSE_MAGIC (0x5afc4453) + +static unsigned long sa1100wdt_users; +static int expect_close; +static int pre_margin; +static int boot_status; +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +/* + * Allow only one person to hold it open + */ +static int sa1100dog_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(1,&sa1100wdt_users)) + return -EBUSY; + + /* Activate SA1100 Watchdog timer */ + OSMR3 = OSCR + pre_margin; + OSSR = OSSR_M3; + OWER = OWER_WME; + OIER |= OIER_E3; + return 0; +} + +/* + * Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT + * Oddly, the watchdog can only be enabled, but we can turn off + * the interrupt, which appears to prevent the watchdog timing out. + */ +static int sa1100dog_release(struct inode *inode, struct file *file) +{ + OSMR3 = OSCR + pre_margin; + + if (expect_close == SA1100_CLOSE_MAGIC) { + OIER &= ~OIER_E3; + } else { + printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); + } + + clear_bit(1, &sa1100wdt_users); + + return 0; +} + +static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (len) { + if (!nowayout) { + size_t i; + + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_close = SA1100_CLOSE_MAGIC; + } + } + /* Refresh OSMR3 timer. */ + OSMR3 = OSCR + pre_margin; + } + + return len ? 1 : 0; +} + +static struct watchdog_info ident = { + .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | + WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "SA1100 Watchdog", +}; + +static int sa1100dog_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + int time; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + ret = put_user(0, (int *)arg); + break; + + case WDIOC_GETBOOTSTATUS: + ret = put_user(boot_status, (int *)arg); + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(time, (int *)arg); + if (ret) + break; + + if (time <= 0 || time > 255) { + ret = -EINVAL; + break; + } + + pre_margin = OSCR_FREQ * time; + OSMR3 = OSCR + pre_margin; + /*fall through*/ + + case WDIOC_GETTIMEOUT: + ret = put_user(pre_margin / OSCR_FREQ, (int *)arg); + break; + + case WDIOC_KEEPALIVE: + OSMR3 = OSCR + pre_margin; + ret = 0; + break; + } + return ret; +} + +static struct file_operations sa1100dog_fops = +{ + .owner = THIS_MODULE, + .write = sa1100dog_write, + .ioctl = sa1100dog_ioctl, + .open = sa1100dog_open, + .release = sa1100dog_release, +}; + +static struct miscdevice sa1100dog_miscdev = +{ + .minor = WATCHDOG_MINOR, + .name = "SA1100 watchdog", + .fops = &sa1100dog_fops, +}; + +static int margin __initdata = 60; /* (secs) Default is 1 minute */ + +static int __init sa1100dog_init(void) +{ + int ret; + + /* + * Read the reset status, and save it for later. If + * we suspend, RCSR will be cleared, and the watchdog + * reset reason will be lost. + */ + boot_status = (RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0; + pre_margin = OSCR_FREQ * margin; + + ret = misc_register(&sa1100dog_miscdev); + if (ret == 0) + printk("SA1100 Watchdog Timer: timer margin %d sec\n", + margin); + + return ret; +} + +static void __exit sa1100dog_exit(void) +{ + misc_deregister(&sa1100dog_miscdev); +} + +module_init(sa1100dog_init); +module_exit(sa1100dog_exit); + +MODULE_AUTHOR("Oleg Drokin "); +MODULE_DESCRIPTION("SA1100 Watchdog"); +MODULE_PARM(margin,"i"); +MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); + +MODULE_PARM(nowayout, "i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig Mon Jan 13 10:18:06 2003 +++ b/drivers/ide/Kconfig Mon Jan 13 10:18:06 2003 @@ -438,7 +438,7 @@ SAY N! config BLK_DEV_AMD74XX - tristate "AMD Viper support" + tristate "AMD and nVidia IDE support" depends on BLK_DEV_IDEDMA_PCI help This driver adds explicit support for AMD-7xx and AMD-8111 chips @@ -446,10 +446,6 @@ change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. -config AMD74XX_OVERRIDE - bool "AMD Viper ATA-66 Override" - depends on BLK_DEV_AMD74XX - config BLK_DEV_CMD64X tristate "CMD64{3|6|8|9} chipset support" depends on BLK_DEV_IDEDMA_PCI @@ -457,6 +453,13 @@ Say Y here if you have an IDE controller which uses any of these chipsets: CMD643, CMD646, or CMD648. +config BLK_DEV_TRIFLEX + tristate "Compaq Triflex IDE support" + depends on BLK_DEV_IDEDMA_PCI + help + Say Y here if you have a Compaq Triflex IDE controller, such + as those commonly found on Compaq Pentium-Pro systems + config BLK_DEV_CY82C693 tristate "CY82C693 chipset support" depends on BLK_DEV_IDEDMA_PCI @@ -556,10 +559,6 @@ Technology Express, Inc. ITE8172 SBC. Vendor page at ; picture of the board at . - -config BLK_DEV_NFORCE - tristate "nVidia NFORCE support" - depends on BLK_DEV_IDEDMA_PCI config BLK_DEV_NS87415 tristate "NS87415 chipset support" diff -Nru a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c --- a/drivers/ide/ide-pnp.c Mon Jan 13 10:18:06 2003 +++ b/drivers/ide/ide-pnp.c Mon Jan 13 10:18:06 2003 @@ -21,10 +21,7 @@ #include -#define DEV_IO(dev, index) (dev->resource[index].start) -#define DEV_IRQ(dev, index) (dev->irq_resource[index].start) - -#define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP") +#define DEV_NAME(dev) (dev->name) #define GENERIC_HD_DATA 0 #define GENERIC_HD_ERROR 1 @@ -44,12 +41,12 @@ /* ISA PnP device table entry */ struct pnp_dev_t { unsigned short card_vendor, card_device, vendor, device; - int (*init_fn)(struct pci_dev *dev, int enable); + int (*init_fn)(struct pnp_dev *dev, int enable); }; /* Generic initialisation function for ISA PnP IDE interface */ -static int __init pnpide_generic_init(struct pci_dev *dev, int enable) +static int __init pnpide_generic_init(struct pnp_dev *dev, int enable) { hw_regs_t hw; ide_hwif_t *hwif; @@ -58,21 +55,21 @@ if (!enable) return 0; - if (!(DEV_IO(dev, 0) && DEV_IO(dev, 1) && DEV_IRQ(dev, 0))) + if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0))) return 1; - ide_setup_ports(&hw, (ide_ioreg_t) DEV_IO(dev, 0), + ide_setup_ports(&hw, (ide_ioreg_t) pnp_port_start(dev, 0), generic_ide_offsets, - (ide_ioreg_t) DEV_IO(dev, 1), + (ide_ioreg_t) pnp_port_start(dev, 1), 0, NULL, // generic_pnp_ide_iops, - DEV_IRQ(dev, 0)); + pnp_irq(dev, 0)); index = ide_register_hw(&hw, &hwif); if (index != -1) { printk(KERN_INFO "ide%d: %s IDE interface\n", index, DEV_NAME(dev)); - hwif->pci_dev = dev; + hwif->pnp_dev = dev; return 0; } @@ -90,7 +87,7 @@ #define NR_PNP_DEVICES 8 struct pnp_dev_inst { - struct pci_dev *dev; + struct pnp_dev *dev; struct pnp_dev_t *dev_type; }; static struct pnp_dev_inst devices[NR_PNP_DEVICES]; @@ -102,7 +99,7 @@ void __init pnpide_init(int enable) { - struct pci_dev *dev = NULL; + struct pnp_dev *dev = NULL; struct pnp_dev_t *dev_type; if (!isapnp_present()) @@ -114,33 +111,26 @@ for (i = 0; i < pnp_ide_dev_idx; i++) { dev = devices[i].dev; devices[i].dev_type->init_fn(dev, 0); - if (dev->deactivate) - dev->deactivate(dev); + pnp_device_detach(dev); } return; } for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) { - while ((dev = isapnp_find_dev(NULL, dev_type->vendor, + while ((dev = pnp_find_dev(NULL, dev_type->vendor, dev_type->device, dev))) { - - if (dev->active) - continue; - - if (dev->prepare && dev->prepare(dev) < 0) { - printk(KERN_ERR"ide-pnp: %s prepare failed\n", DEV_NAME(dev)); + + if (pnp_device_attach(dev) < 0) continue; - } - - if (dev->activate && dev->activate(dev) < 0) { + + if (pnp_activate_dev(dev, NULL) < 0) { printk(KERN_ERR"ide: %s activate failed\n", DEV_NAME(dev)); continue; } /* Call device initialization function */ if (dev_type->init_fn(dev, 1)) { - if (dev->deactivate(dev)) - dev->deactivate(dev); + pnp_device_detach(dev); } else { #ifdef MODULE /* diff -Nru a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile --- a/drivers/ide/pci/Makefile Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/Makefile Mon Jan 13 10:18:05 2003 @@ -15,7 +15,6 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o -obj-$(CONFIG_BLK_DEV_NFORCE) += nvidia.o obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o obj-$(CONFIG_BLK_DEV_PDC202XX_NEW) += pdc202xx_new.o @@ -27,6 +26,7 @@ obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o +obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o diff -Nru a/drivers/ide/pci/adma100.c b/drivers/ide/pci/adma100.c --- a/drivers/ide/pci/adma100.c Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/adma100.c Mon Jan 13 10:18:05 2003 @@ -18,7 +18,7 @@ void __init ide_init_adma100 (ide_hwif_t *hwif) { - u32 phy_admctl = pci_resource_start(hwif->pci_dev, 4) + 0x80 + (hwif->channel * 0x20); + unsigned long phy_admctl = pci_resource_start(hwif->pci_dev, 4) + 0x80 + (hwif->channel * 0x20); void *v_admctl; hwif->autodma = 0; // not compatible with normal IDE DMA transfers diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c --- a/drivers/ide/pci/aec62xx.c Mon Jan 13 10:18:07 2003 +++ b/drivers/ide/pci/aec62xx.c Mon Jan 13 10:18:07 2003 @@ -42,7 +42,7 @@ for (i = 0; i < n_aec_devs; i++) { struct pci_dev *dev = aec_devs[i]; - u32 iobase = pci_resource_start(dev, 4); + unsigned long iobase = pci_resource_start(dev, 4); u8 c0 = 0, c1 = 0, art = 0; #ifdef DEBUG_AEC_REGS u8 uart = 0; @@ -493,7 +493,7 @@ static void __init init_setup_aec6x80 (struct pci_dev *dev, ide_pci_device_t *d) { - u32 bar4reg = pci_resource_start(dev, 4); + unsigned long bar4reg = pci_resource_start(dev, 4); if (inb(bar4reg+2) & 0x10) { strcpy(d->name, "AEC6880"); diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Mon Jan 13 10:18:07 2003 +++ b/drivers/ide/pci/amd74xx.c Mon Jan 13 10:18:07 2003 @@ -1,390 +1,439 @@ /* - * linux/drivers/ide/amd74xx.c Version 0.05 June 9, 2000 + * Version 2.9 * - * Copyright (C) 1999-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License + * AMD 755/756/766/8111 and nVidia nForce IDE driver for Linux. * + * Copyright (c) 2000-2002 Vojtech Pavlik + * + * Based on the work of: + * Andre Hedrick + */ + +/* + * 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 #include -#include #include -#include -#include -#include #include #include -#include - -#include -#include #include +#include #include - #include -#include -#include "ide_modes.h" +#include "ide-timing.h" #include "amd74xx.h" -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) +#define AMD_IDE_ENABLE (0x00 + amd_config->base) +#define AMD_IDE_CONFIG (0x01 + amd_config->base) +#define AMD_CABLE_DETECT (0x02 + amd_config->base) +#define AMD_DRIVE_TIMING (0x08 + amd_config->base) +#define AMD_8BIT_TIMING (0x0e + amd_config->base) +#define AMD_ADDRESS_SETUP (0x0c + amd_config->base) +#define AMD_UDMA_TIMING (0x10 + amd_config->base) + +#define AMD_UDMA 0x07 +#define AMD_UDMA_33 0x01 +#define AMD_UDMA_66 0x02 +#define AMD_UDMA_100 0x03 +#define AMD_CHECK_SWDMA 0x08 +#define AMD_BAD_SWDMA 0x10 +#define AMD_BAD_FIFO 0x20 + +/* + * AMD SouthBridge chips. + */ + +static struct amd_ide_chip { + unsigned short id; + unsigned char rev; + unsigned long base; + unsigned char flags; +} amd_ide_chips[] = { + { PCI_DEVICE_ID_AMD_8111_IDE, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-8111 */ + { PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-768 Opus */ + { PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO }, /* AMD-766 Viper */ + { PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA }, /* AMD-756 Viper */ + { PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA }, /* AMD-755 Cobra */ + { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x00, 0x50, AMD_UDMA_100 }, /* nVidia nForce */ + + { 0 } +}; + +static struct amd_ide_chip *amd_config; +static unsigned char amd_enabled; +static unsigned int amd_80w; +static unsigned int amd_clock; + +static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3 }; +static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 1 }; +static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" }; + +/* + * AMD /proc entry. + */ + +#ifdef CONFIG_PROC_FS + #include #include -static u8 amd74xx_proc = 0; - +static int amd_base; static struct pci_dev *bmide_dev; +extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ +#define amd_print(format, arg...) p += sprintf(p, format "\n" , ## arg) +#define amd_print_drive(name, format, arg...)\ + p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n"); + +static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count) +{ + int speed[4], cycle[4], setup[4], active[4], recover[4], den[4], + uen[4], udma[4], active8b[4], recover8b[4]; + struct pci_dev *dev = bmide_dev; + unsigned int v, u, i; + unsigned short c, w; + unsigned char t; char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n " - "AMD %04X VIPER Chipset.\n", bmide_dev->device); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static int amd74xx_mode5_check (struct pci_dev *dev) -{ - switch(dev->device) { - case PCI_DEVICE_ID_AMD_VIPER_7411: - case PCI_DEVICE_ID_AMD_VIPER_7441: - case PCI_DEVICE_ID_AMD_8111_IDE: - return 1; - default: - return 0; + amd_print("----------AMD BusMastering IDE Configuration----------------"); + + amd_print("Driver Version: 2.8"); + amd_print("South Bridge: %s", bmide_dev->dev.name); + + pci_read_config_byte(dev, PCI_REVISION_ID, &t); + amd_print("Revision: IDE %#x", t); + amd_print("Highest DMA rate: %s", amd_dma[amd_config->flags & AMD_UDMA]); + + amd_print("BM-DMA base: %#lx", amd_base); + amd_print("PCI clock: %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10); + + amd_print("-----------------------Primary IDE-------Secondary IDE------"); + + pci_read_config_byte(dev, AMD_IDE_CONFIG, &t); + amd_print("Prefetch Buffer: %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no"); + amd_print("Post Write Buffer: %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no"); + + pci_read_config_byte(dev, AMD_IDE_ENABLE, &t); + amd_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); + + c = inb(amd_base + 0x02) | (inb(amd_base + 0x0a) << 8); + amd_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); + + amd_print("Cable Type: %10s%20s", (amd_80w & 1) ? "80w" : "40w", (amd_80w & 2) ? "80w" : "40w"); + + if (!amd_clock) + return p - buffer; + + amd_print("-------------------drive0----drive1----drive2----drive3-----"); + + pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t); + pci_read_config_dword(dev, AMD_DRIVE_TIMING, &v); + pci_read_config_word(dev, AMD_8BIT_TIMING, &w); + pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); + + for (i = 0; i < 4; i++) { + setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1; + recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1; + active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1; + active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; + recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; + + udma[i] = amd_udma2cyc[((u >> ((3 - i) << 3)) & 0x7)]; + uen[i] = ((u >> ((3 - i) << 3)) & 0x40) ? 1 : 0; + den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)); + + if (den[i] && uen[i] && udma[i] == 1) { + speed[i] = amd_clock * 3; + cycle[i] = 666666 / amd_clock; + continue; + } + + speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2); + cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2; } -} -static unsigned int amd74xx_swdma_check (struct pci_dev *dev) -{ - unsigned int class_rev; + amd_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO"); - if (amd74xx_mode5_check(dev)) - return 1; + amd_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / amd_clock); + amd_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / amd_clock); + amd_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / amd_clock); + amd_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / amd_clock); + amd_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / amd_clock); + amd_print_drive("Cycle Time: ", "%8dns", cycle[i]); + amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - return ((int) (class_rev >= 7) ? 1 : 0); + return p - buffer; /* hoping it is less than 4K... */ } -static u8 amd74xx_ratemask (ide_drive_t *drive) +#endif + +/* + * amd_set_speed() writes timing values to the chipset registers + */ + +static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing) { - u8 mode; + unsigned char t; - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_AMD_8111_IDE: - case PCI_DEVICE_ID_AMD_VIPER_7441: - case PCI_DEVICE_ID_AMD_VIPER_7411: - mode = 3; - break; - case PCI_DEVICE_ID_AMD_VIPER_7409: - mode = 2; - break; - case PCI_DEVICE_ID_AMD_COBRA_7401: - return 1; - default: - return 0; - } + pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t); + t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); + pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t); - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)), + ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); - return mode; + pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn), + ((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1)); + + switch (amd_config->flags & AMD_UDMA) { + case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; + case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break; + case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break; + default: return; + } + + pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t); } /* - * Here is where all the hard work goes to program the chipset. + * amd_set_drive() computes timing values configures the drive and + * the chipset to a desired transfer mode. It also can be called + * by upper layers. */ -static int amd74xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) + +static int amd_set_drive(ide_drive_t *drive, u8 speed) { - u8 drive_pci[] = { 0x53, 0x52, 0x51, 0x50 }; - u8 drive_pci2[] = { 0x4b, 0x4a, 0x49, 0x48 }; -#if 0 - u8 ultra_rate[] = { 0x42, 0x41, 0x40, 0x44, 0x45, 0x46 }; - u8 mwdma_rate[] = { 0x77, 0x21, 0x20 }; - u8 swdma_rate[] = { 0xA8, 0x65, 0x42 }; - u8 pio_rate[] = { 0xA8, 0x65, 0x42, 0x22, 0x20}; -#endif - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(amd74xx_ratemask(drive), xferspeed); - u8 ultra_timing = 0, dma_pio_timing = 0, pio_timing = 0; - - pci_read_config_byte(dev, drive_pci[drive->dn], &ultra_timing); - pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_pio_timing); - pci_read_config_byte(dev, 0x4c, &pio_timing); - - ultra_timing &= ~0xC7; - dma_pio_timing &= ~0xFF; - pio_timing &= ~(0x03 << drive->dn); - - switch(speed) { - case XFER_UDMA_7: - case XFER_UDMA_6: - speed = XFER_UDMA_5; - case XFER_UDMA_5: - ultra_timing |= 0x46; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_4: - ultra_timing |= 0x45; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_3: - ultra_timing |= 0x44; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_2: - ultra_timing |= 0x40; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_1: - ultra_timing |= 0x41; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_0: - ultra_timing |= 0x42; - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_2: - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_1: - dma_pio_timing |= 0x21; - break; - case XFER_MW_DMA_0: - dma_pio_timing |= 0x77; - break; - case XFER_SW_DMA_2: - dma_pio_timing |= 0x42; - break; - case XFER_SW_DMA_1: - dma_pio_timing |= 0x65; - break; - case XFER_SW_DMA_0: - dma_pio_timing |= 0xA8; - break; - case XFER_PIO_4: - dma_pio_timing |= 0x20; - break; - case XFER_PIO_3: - dma_pio_timing |= 0x22; - break; - case XFER_PIO_2: - dma_pio_timing |= 0x42; - break; - case XFER_PIO_1: - dma_pio_timing |= 0x65; - break; - case XFER_PIO_0: - default: - dma_pio_timing |= 0xA8; - break; - } + ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); + struct ide_timing t, p; + int T, UT; + + if (speed != XFER_PIO_SLOW && speed != drive->current_speed) + if (ide_config_drive_speed(drive, speed)) + printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", + drive->dn >> 1, drive->dn & 1); - pio_timing |= (0x03 << drive->dn); + T = 1000000000 / amd_clock; + UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2); - pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing); - pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing); - pci_write_config_byte(dev, 0x4c, pio_timing); + ide_timing_compute(drive, speed, &t, T, UT); + + if (peer->present) { + ide_timing_compute(peer, peer->current_speed, &p, T, UT); + ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT); + } - return (ide_config_drive_speed(drive, speed)); + if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1; + + amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); + + if (!drive->init_speed) + drive->init_speed = speed; + drive->current_speed = speed; + + return 0; } -static void amd74xx_tune_drive (ide_drive_t *drive, u8 pio) +/* + * amd74xx_tune_drive() is a callback from upper layers for + * PIO-only tuning. + */ + +static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio) { - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - (void) amd74xx_tune_chipset(drive, (XFER_PIO_0 + pio)); + if (!((amd_enabled >> HWIF(drive)->channel) & 1)) + return; + + if (pio == 255) { + amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO)); + return; + } + + amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5)); } /* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. + * amd74xx_dmaproc() is a callback from upper layers that can do + * a lot, but we use it for DMA/PIO tuning only, delegating everything + * else to the default ide_dmaproc(). */ -static int config_chipset_for_dma (ide_drive_t *drive) + +static int amd74xx_ide_dma_check(ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, amd74xx_ratemask(drive)); + int w80 = HWIF(drive)->udma_four; + + u8 speed = ide_find_best_mode(drive, + XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA | + ((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) | + (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) | + (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0)); - if (!(speed)) - return 0; + amd_set_drive(drive, speed); - (void) amd74xx_tune_chipset(drive, speed); - return ide_dma_enable(drive); + if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) + return HWIF(drive)->ide_dma_on(drive); + return HWIF(drive)->ide_dma_off_quietly(drive); } -static int amd74xx_config_drive_xfer_rate (ide_drive_t *drive) +/* + * The initialization callback. Here we determine the IDE chip type + * and initialize its drive independent registers. + */ + +unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name) { - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; + unsigned char t; + unsigned int u; + int i; - drive->init_speed = 0; +/* + * Check for bad SWDMA. + */ - if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (hwif->ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } + if (amd_config->flags & AMD_CHECK_SWDMA) { + pci_read_config_byte(dev, PCI_REVISION_ID, &t); + if (t <= 7) + amd_config->flags |= AMD_BAD_SWDMA; + } - } else if (hwif->ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: -no_dma_set: - amd74xx_tune_drive(drive, 5); - return hwif->ide_dma_off_quietly(drive); +/* + * Check 80-wire cable presence. + */ + + switch (amd_config->flags & AMD_UDMA) { + + case AMD_UDMA_100: + pci_read_config_byte(dev, AMD_CABLE_DETECT, &t); + amd_80w = ((u & 0x3) ? 1 : 0) | ((u & 0xc) ? 2 : 0); + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { + printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits corectly. Enabling workaround.\n"); + amd_80w |= (1 << (1 - (i >> 4))); + } + break; + + case AMD_UDMA_66: + pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); + for (i = 24; i >= 0; i -= 8) + if ((u >> i) & 4) + amd_80w |= (1 << (1 - (i >> 4))); + break; } - return hwif->ide_dma_on(drive); -} -static unsigned int __init init_chipset_amd74xx (struct pci_dev *dev, const char *name) -{ - if (!amd74xx_swdma_check(dev)) - printk("%s: disabling single-word DMA support (revision < C4)\n", name); + pci_read_config_dword(dev, AMD_IDE_ENABLE, &u); + amd_enabled = ((u & 1) ? 2 : 0) | ((u & 2) ? 1 : 0); -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) - if (!amd74xx_proc) { - amd74xx_proc = 1; - bmide_dev = dev; - ide_pci_register_host_proc(&amd74xx_procs[0]); +/* + * Take care of prefetch & postwrite. + */ + + pci_read_config_byte(dev, AMD_IDE_CONFIG, &t); + pci_write_config_byte(dev, AMD_IDE_CONFIG, + (amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0)); + +/* + * Determine the system bus clock. + */ + + amd_clock = system_bus_clock() * 1000; + + switch (amd_clock) { + case 33000: amd_clock = 33333; break; + case 37000: amd_clock = 37500; break; + case 41000: amd_clock = 41666; break; + } + + if (amd_clock < 20000 || amd_clock > 50000) { + printk(KERN_WARNING "AMD_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", amd_clock); + printk(KERN_WARNING "AMD_IDE: Use ide0=ata66 if you want to assume 80-wire cable\n"); + amd_clock = 33333; } -#endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */ + +/* + * Print the boot message. + */ + + pci_read_config_byte(dev, PCI_REVISION_ID, &t); + printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n", + dev->dev.name, t, amd_dma[amd_config->flags & AMD_UDMA], dev->slot_name); + +/* + * Register /proc/ide/amd74xx entry + */ + +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) + if (!amd74xx_proc) { + amd_base = pci_resource_start(dev, 4); + bmide_dev = dev; + ide_pci_register_host_proc(&amd74xx_procs[0]); + amd74xx_proc = 1; + } +#endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ + return 0; } -static unsigned int __init ata66_amd74xx (ide_hwif_t *hwif) +unsigned int __init ata66_amd74xx(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - u8 cable_80_pin[2] = { 0, 0 }; - u8 ata66 = 0; - u8 tmpbyte; - - /* - * Ultra66 cable detection (from Host View) - * 7411, 7441, 0x42, bit0: primary, bit2: secondary 80 pin - */ - pci_read_config_byte(dev, 0x42, &tmpbyte); - - /* - * 0x42, bit0 is 1 => primary channel - * has 80-pin (from host view) - */ - if (tmpbyte & 0x01) cable_80_pin[0] = 1; - - /* - * 0x42, bit2 is 1 => secondary channel - * has 80-pin (from host view) - */ - if (tmpbyte & 0x04) cable_80_pin[1] = 1; - - switch(dev->device) { - case PCI_DEVICE_ID_AMD_COBRA_7401: - cable_80_pin[hwif->channel] = 0; - return 0; - case PCI_DEVICE_ID_AMD_8111_IDE: - case PCI_DEVICE_ID_AMD_VIPER_7441: - case PCI_DEVICE_ID_AMD_VIPER_7411: - ata66 = (hwif->channel) ? - cable_80_pin[1] : - cable_80_pin[0]; - default: - break; - } - return (unsigned int) ata66; + return ((amd_enabled & amd_80w) >> hwif->channel) & 1; } -static void __init init_hwif_amd74xx (ide_hwif_t *hwif) +void __init init_hwif_amd74xx(ide_hwif_t *hwif) { + int i; + hwif->autodma = 0; + hwif->tuneproc = &amd74xx_tune_drive; - hwif->speedproc = &amd74xx_tune_chipset; + hwif->speedproc = &amd_set_drive; - if (!hwif->dma_base) { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - return; + for (i = 0; i < 2; i++) { + hwif->drives[i].io_32bit = 1; + hwif->drives[i].unmask = 1; + hwif->drives[i].autotune = 1; + hwif->drives[i].dn = hwif->channel * 2 + i; } - hwif->atapi_dma = 1; - hwif->ultra_mask = 0x3f; - hwif->mwdma_mask = 0x07; - if (amd74xx_swdma_check(hwif->pci_dev)) - hwif->swdma_mask = 0x07; - - if (!(hwif->udma_four)) - hwif->udma_four = ata66_amd74xx(hwif); - hwif->ide_dma_check = &amd74xx_config_drive_xfer_rate; - if (!noautodma) - hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; -} - -static void __init init_dma_amd74xx (ide_hwif_t *hwif, unsigned long dmabase) -{ - if (!(hwif->channel)) - hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2); - ide_setup_dma(hwif, dmabase, 8); + if (!hwif->dma_base) + return; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + if (!(hwif->udma_four)) + hwif->udma_four = ((amd_enabled & amd_80w) >> hwif->channel) & 1; + hwif->ide_dma_check = &amd74xx_ide_dma_check; + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); +/* + * We allow the BM-DMA driver only work on enabled interfaces. + */ +static void __init init_dma_amd74xx(ide_hwif_t *hwif, unsigned long dmabase) +{ + if ((amd_enabled >> hwif->channel) & 1) + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); -static int __devinit amd74xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d = &amd74xx_chipsets[id->driver_data]; - if (dev->device != d->device) - BUG(); + ide_pci_device_t *d = amd74xx_chipsets + id->driver_data; + amd_config = amd_ide_chips + id->driver_data; + if (dev->device != d->device) BUG(); + if (dev->device != amd_config->id) BUG(); ide_setup_pci_device(dev, d); MOD_INC_USE_COUNT; return 0; @@ -396,13 +445,14 @@ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, { 0, }, }; static struct pci_driver driver = { .name = "AMD IDE", .id_table = amd74xx_pci_tbl, - .probe = amd74xx_init_one, + .probe = amd74xx_probe, }; static int amd74xx_ide_init(void) @@ -418,8 +468,8 @@ module_init(amd74xx_ide_init); module_exit(amd74xx_ide_exit); -MODULE_AUTHOR("Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for AMD IDE"); +MODULE_AUTHOR("Vojtech Pavlik"); +MODULE_DESCRIPTION("AMD PCI IDE driver"); MODULE_LICENSE("GPL"); EXPORT_NO_SYMBOLS; diff -Nru a/drivers/ide/pci/amd74xx.h b/drivers/ide/pci/amd74xx.h --- a/drivers/ide/pci/amd74xx.h Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/amd74xx.h Mon Jan 13 10:18:05 2003 @@ -5,9 +5,9 @@ #include #include -#define DISPLAY_VIPER_TIMINGS +#define DISPLAY_AMD_TIMINGS -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -23,7 +23,7 @@ .parent = NULL, }, }; -#endif /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */ +#endif /* defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) */ static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *); static void init_hwif_amd74xx(ide_hwif_t *); @@ -95,7 +95,22 @@ .enablebits = {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, .bootable = ON_BOARD, .extra = 0 - },{ + }, + { /* 5 */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, + .name = "NFORCE", + .init_chipset = init_chipset_amd74xx, + .init_iops = NULL, + .init_hwif = init_hwif_amd74xx, + .init_dma = init_dma_amd74xx, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x50,0x01,0x01}, {0x50,0x02,0x02}}, + .bootable = ON_BOARD, + .extra = 0, + }, + { .vendor = 0, .device = 0, .channels = 0, diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c --- a/drivers/ide/pci/cs5520.c Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/cs5520.c Mon Jan 13 10:18:05 2003 @@ -73,8 +73,8 @@ * at that point bibma+0x2 et bibma+0xa are byte registers * to investigate: */ - c0 = inb((unsigned short)bmiba + 0x02); - c1 = inb((unsigned short)bmiba + 0x0a); + c0 = inb(bmiba + 0x02); + c1 = inb(bmiba + 0x0a); p += sprintf(p, "\nCyrix CS55x0 IDE\n"); p += sprintf(p, "--------------- Primary Channel " @@ -203,7 +203,7 @@ static void __devinit cs5520_init_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif) { - u32 bmide = pci_resource_start(dev, 2); /* Not the usual 4 */ + unsigned long bmide = pci_resource_start(dev, 2); /* Not the usual 4 */ if(hwif->mate && hwif->mate->dma_base) /* Second channel at primary + 8 */ bmide += 8; ide_setup_dma(hwif, bmide, 8); diff -Nru a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c --- a/drivers/ide/pci/cs5530.c Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/cs5530.c Mon Jan 13 10:18:05 2003 @@ -42,7 +42,7 @@ static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); + unsigned long bibma = pci_resource_start(bmide_dev, 4); u8 c0 = 0, c1 = 0; /* @@ -124,7 +124,8 @@ static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */ { ide_hwif_t *hwif = HWIF(drive); - unsigned int format, basereg = CS5530_BASEREG(hwif); + unsigned int format; + unsigned long basereg = CS5530_BASEREG(hwif); static u8 modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; pio = ide_get_best_pio_mode(drive, pio, 4, NULL); @@ -151,7 +152,8 @@ int unit = drive->select.b.unit; ide_drive_t *mate = &hwif->drives[unit^1]; struct hd_driveid *id = drive->id; - unsigned int basereg, reg, timings; + unsigned int reg, timings; + unsigned long basereg; /* * Default to DMA-off in case we run into trouble here. @@ -365,7 +367,8 @@ static void __init init_hwif_cs5530 (ide_hwif_t *hwif) { - unsigned int basereg, d0_timings; + unsigned long basereg; + u32 d0_timings; hwif->autodma = 0; if (hwif->mate) diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c --- a/drivers/ide/pci/hpt34x.c Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/hpt34x.c Mon Jan 13 10:18:05 2003 @@ -64,7 +64,7 @@ "HPT34X Chipset.\n"); for (i = 0; i < n_hpt34x_devs; i++) { struct pci_dev *dev = hpt34x_devs[i]; - u32 bibma = pci_resource_start(dev, 4); + unsigned long bibma = pci_resource_start(dev, 4); u8 c0 = 0, c1 = 0; /* diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c --- a/drivers/ide/pci/hpt366.c Mon Jan 13 10:18:06 2003 +++ b/drivers/ide/pci/hpt366.c Mon Jan 13 10:18:06 2003 @@ -659,7 +659,7 @@ static void hpt3xx_reset (ide_drive_t *drive) { #if 0 - u32 high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); + unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); u8 reset = (HWIF(drive)->channel) ? 0x80 : 0x40; u8 reg59h = 0; @@ -818,7 +818,10 @@ } else { pll = F_LOW_PCI_66; if (hpt_minimum_revision(dev,8)) + { + printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n"); return -EOPNOTSUPP; + } else if (hpt_minimum_revision(dev,5)) pci_set_drvdata(dev, (void *) sixty_six_base_hpt372); else if (hpt_minimum_revision(dev,4)) diff -Nru a/drivers/ide/pci/nvidia.c b/drivers/ide/pci/nvidia.c --- a/drivers/ide/pci/nvidia.c Mon Jan 13 10:18:07 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,370 +0,0 @@ -/* - * linux/drivers/ide/nvidia.c Version 0.01 - * - * Copyright (C) 2002-2002 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "ide_modes.h" -#include "nvidia.h" - -#if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 nforce_proc = 0; -static struct pci_dev *bmide_dev; - -static int nforce_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - unsigned long bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n " - "nVidia %04X Chipset.\n", bmide_dev->device); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static u8 nforce_ratemask (ide_drive_t *drive) -{ - u8 mode; - - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_NVIDIA_NFORCE_IDE: - mode = 3; - break; - default: - return 0; - } - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - -/* - * Here is where all the hard work goes to program the chipset. - */ -static int nforce_tune_chipset (ide_drive_t *drive, u8 xferspeed) -{ - static const u8 drive_pci[] = { 0x63, 0x62, 0x61, 0x60 }; - static const u8 drive_pci2[] = { 0x5b, 0x5a, 0x59, 0x58 }; - - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(nforce_ratemask(drive), xferspeed); - u8 ultra_timing = 0, dma_pio_timing = 0, pio_timing = 0; - - pci_read_config_byte(dev, drive_pci[drive->dn], &ultra_timing); - pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_pio_timing); - pci_read_config_byte(dev, 0x5c, &pio_timing); - - ultra_timing &= ~0xC7; - dma_pio_timing &= ~0xFF; - pio_timing &= ~(0x03 << drive->dn); - - switch(speed) { - case XFER_UDMA_7: - case XFER_UDMA_6: - speed = XFER_UDMA_5; - case XFER_UDMA_5: - ultra_timing |= 0x46; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_4: - ultra_timing |= 0x45; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_3: - ultra_timing |= 0x44; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_2: - ultra_timing |= 0x40; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_1: - ultra_timing |= 0x41; - dma_pio_timing |= 0x20; - break; - case XFER_UDMA_0: - ultra_timing |= 0x42; - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_2: - dma_pio_timing |= 0x20; - break; - case XFER_MW_DMA_1: - dma_pio_timing |= 0x21; - break; - case XFER_MW_DMA_0: - dma_pio_timing |= 0x77; - break; - case XFER_SW_DMA_2: - dma_pio_timing |= 0x42; - break; - case XFER_SW_DMA_1: - dma_pio_timing |= 0x65; - break; - case XFER_SW_DMA_0: - dma_pio_timing |= 0xA8; - break; - case XFER_PIO_4: - dma_pio_timing |= 0x20; - break; - case XFER_PIO_3: - dma_pio_timing |= 0x22; - break; - case XFER_PIO_2: - dma_pio_timing |= 0x42; - break; - case XFER_PIO_1: - dma_pio_timing |= 0x65; - break; - case XFER_PIO_0: - default: - dma_pio_timing |= 0xA8; - break; - } - - pio_timing |= (0x03 << drive->dn); - - pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing); - pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing); - pci_write_config_byte(dev, 0x5c, pio_timing); - - return (ide_config_drive_speed(drive, speed)); -} - -static void nforce_tune_drive (ide_drive_t *drive, u8 pio) -{ - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - (void) nforce_tune_chipset(drive, (XFER_PIO_0 + pio)); -} - -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_dma_speed(drive, nforce_ratemask(drive)); - - if (!(speed)) - return 0; - - (void) nforce_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - -static int nforce_config_drive_xfer_rate (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - - drive->init_speed = 0; - - if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (hwif->ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - - } else if (hwif->ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: -no_dma_set: - nforce_tune_drive(drive, 5); - return hwif->ide_dma_off_quietly(drive); - } - return hwif->ide_dma_on(drive); -} - -static unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) - if (!nforce_proc) { - nforce_proc = 1; - bmide_dev = dev; - ide_pci_register_host_proc(&nforce_procs[0]); - } -#endif /* DISPLAY_NFORCE_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - -static unsigned int __init ata66_nforce (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - u8 cable_80_pin[2] = { 0, 0 }; - u8 ata66 = 0; - u8 tmpbyte; - - /* - * Ultra66 cable detection (from Host View) - * 7411, 7441, 0x52, bit0: primary, bit2: secondary 80 pin - */ - pci_read_config_byte(dev, 0x52, &tmpbyte); - - /* - * 0x52, bit0 is 1 => primary channel - * has 80-pin (from host view) - */ - if (tmpbyte & 0x01) cable_80_pin[0] = 1; - - /* - * 0x52, bit2 is 1 => secondary channel - * has 80-pin (from host view) - */ - if (tmpbyte & 0x04) cable_80_pin[1] = 1; - - switch(dev->device) { - case PCI_DEVICE_ID_NVIDIA_NFORCE_IDE: - ata66 = (hwif->channel) ? - cable_80_pin[1] : - cable_80_pin[0]; - default: - break; - } - return (unsigned int) ata66; -} - -static void __init init_hwif_nforce (ide_hwif_t *hwif) -{ - hwif->tuneproc = &nforce_tune_drive; - hwif->speedproc = &nforce_tune_chipset; - hwif->autodma = 0; - - if (!hwif->dma_base) { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - return; - } - - hwif->atapi_dma = 1; - hwif->ultra_mask = 0x3f; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; - - if (!(hwif->udma_four)) - hwif->udma_four = ata66_nforce(hwif); - hwif->ide_dma_check = &nforce_config_drive_xfer_rate; - if (!noautodma) - hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; -} - -/* FIXME - not needed */ -static void __init init_dma_nforce (ide_hwif_t *hwif, unsigned long dmabase) -{ - ide_setup_dma(hwif, dmabase, 8); -} - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - -static int __devinit nforce_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - ide_pci_device_t *d = &nvidia_chipsets[id->driver_data]; - if (dev->device != d->device) - BUG(); - ide_setup_pci_device(dev, d); - MOD_INC_USE_COUNT; - return 0; -} - -static struct pci_device_id nforce_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { 0, }, -}; - -static struct pci_driver driver = { - .name = "nForce IDE", - .id_table = nforce_pci_tbl, - .probe = nforce_init_one, -}; - -static int nforce_ide_init(void) -{ - return ide_pci_register_driver(&driver); -} - -static void nforce_ide_exit(void) -{ - ide_pci_unregister_driver(&driver); -} - -module_init(nforce_ide_init); -module_exit(nforce_ide_exit); - -MODULE_AUTHOR("Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for nVidia nForce IDE"); -MODULE_LICENSE("GPL"); - -EXPORT_NO_SYMBOLS; diff -Nru a/drivers/ide/pci/nvidia.h b/drivers/ide/pci/nvidia.h --- a/drivers/ide/pci/nvidia.h Mon Jan 13 10:18:06 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,50 +0,0 @@ -#ifndef NFORCE_H -#define NFORCE_H - -#include -#include -#include - -#define DISPLAY_NFORCE_TIMINGS - -#if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 nforce_proc; - -static int nforce_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t nforce_procs[] __initdata = { - { - .name = "nforce", - .set = 1, - .get_info = nforce_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static unsigned int init_chipset_nforce(struct pci_dev *, const char *); -static void init_hwif_nforce(ide_hwif_t *); -static void init_dma_nforce(ide_hwif_t *, unsigned long); - -static ide_pci_device_t nvidia_chipsets[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, - .name = "NFORCE", - .init_chipset = init_chipset_nforce, - .init_iops = NULL, - .init_hwif = init_hwif_nforce, - .init_dma = init_dma_nforce, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x50,0x01,0x01}, {0x50,0x02,0x02}}, - .bootable = ON_BOARD, - .extra = 0, - } -}; - - -#endif /* NFORCE_H */ diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c --- a/drivers/ide/pci/pdc202xx_new.c Mon Jan 13 10:18:07 2003 +++ b/drivers/ide/pci/pdc202xx_new.c Mon Jan 13 10:18:07 2003 @@ -237,11 +237,11 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); - u32 indexreg = hwif->dma_vendor1; - u32 datareg = hwif->dma_vendor3; + unsigned long indexreg = hwif->dma_vendor1; + unsigned long datareg = hwif->dma_vendor3; u8 thold = 0x10; u8 adj = (drive->dn%2) ? 0x08 : 0x00; - u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); if (speed == XFER_UDMA_2) { hwif->OUTB((thold + adj), indexreg); diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c --- a/drivers/ide/pci/pdc202xx_old.c Mon Jan 13 10:18:07 2003 +++ b/drivers/ide/pci/pdc202xx_old.c Mon Jan 13 10:18:07 2003 @@ -64,7 +64,7 @@ { char *p = buf; - u32 bibma = pci_resource_start(dev, 4); + unsigned long bibma = pci_resource_start(dev, 4); u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0; u16 reg50h = 0, pmask = (1<<10), smask = (1<<11); u8 hi = 0, lo = 0; @@ -535,9 +535,9 @@ struct request *rq = HWGROUP(drive)->rq; ide_hwif_t *hwif = HWIF(drive); // struct pci_dev *dev = hwif->pci_dev; -// u32 high_16 = pci_resource_start(dev, 4); - u32 high_16 = hwif->dma_master; - u32 atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); +// unsgned long high_16 = pci_resource_start(dev, 4); + unsigned long high_16 = hwif->dma_master; + unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); u32 word_count = 0; u8 clock = hwif->INB(high_16 + 0x11); @@ -555,10 +555,10 @@ { if (drive->addressing == 1) { ide_hwif_t *hwif = HWIF(drive); -// u32 high_16 = pci_resource_start(hwif->pci_dev, 4); - u32 high_16 = hwif->dma_master; - u32 atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); - u8 clock = 0; +// unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); + unsigned long high_16 = hwif->dma_master; + unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); + u8 clock = 0; hwif->OUTL(0, atapi_reg); /* zero out extra */ clock = hwif->INB(high_16 + 0x11); @@ -572,7 +572,7 @@ ide_hwif_t *hwif = HWIF(drive); // struct pci_dev *dev = hwif->pci_dev; // unsigned long high_16 = pci_resource_start(dev, 4); - u32 high_16 = hwif->dma_master; + unsigned long high_16 = hwif->dma_master; u8 dma_stat = hwif->INB(hwif->dma_status); u8 sc1d = hwif->INB((high_16 + 0x001d)); diff -Nru a/drivers/ide/pci/pdcadma.c b/drivers/ide/pci/pdcadma.c --- a/drivers/ide/pci/pdcadma.c Mon Jan 13 10:18:07 2003 +++ b/drivers/ide/pci/pdcadma.c Mon Jan 13 10:18:07 2003 @@ -43,7 +43,7 @@ for (i = 0; i < n_pdc_devs; i++) { struct pci_dev *dev = pdc_devs[i]; - u32 bibma = pci_resource_start(dev, 4); + unsigned long bibma = pci_resource_start(dev, 4); p += sprintf(p, "\n " "PDC ADMA %04X Chipset.\n", dev->device); diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c --- a/drivers/ide/pci/piix.c Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/piix.c Mon Jan 13 10:18:05 2003 @@ -1,8 +1,10 @@ /* - * linux/drivers/ide/piix.c Version 0.40 August 18, 2002 + * linux/drivers/ide/piix.c Version 0.42 January 11, 2003 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick + * Copyright (C) 2003 Red Hat Inc + * * May be copied or modified under the terms of the GNU General Public License * * PIO mode setting function for Intel chipsets. @@ -51,6 +53,41 @@ * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); * + * Documentation + * Publically available from Intel web site. Errata documentation + * is also publically available. As an aide to anyone hacking on this + * driver the list of errata that are relevant is below.going back to + * PIIX4. Older device documentation is now a bit tricky to find. + * + * Errata of note: + * + * Unfixable + * PIIX4 errata #9 - Only on ultra obscure hw + * ICH3 errata #13 - Not observed to affect real hw + * by Intel + * + * Things we must deal with + * PIIX4 errata #10 - BM IDE hang with non UDMA + * (must stop/start dma to recover) + * 440MX errata #15 - As PIIX4 errata #10 + * PIIX4 errata #15 - Must not read control registers + * during a PIO transfer + * 440MX errata #13 - As PIIX4 errata #15 + * ICH2 errata #21 - DMA mode 0 doesn't work right + * ICH0/1 errata #55 - As ICH2 errata #21 + * ICH2 spec c #9 - Extra operations needed to handle + * drive hotswap [NOT YET SUPPORTED] + * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary + * and must be dword aligned + * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 + * + * Should have been BIOS fixed: + * 450NX: errata #19 - DMA hangs on old 450NX + * 450NX: errata #20 - DMA hangs on old 450NX + * 450NX: errata #25 - Corruption with DMA on old 450NX + * ICH3 errata #15 - IDE deadlock under high load + * (BIOS must set dev 31 fn 0 bit 23) + * ICH3 errata #18 - Don't use native mode */ #include @@ -77,6 +114,7 @@ #define PIIX_MAX_DEVS 5 static struct pci_dev *piix_devs[PIIX_MAX_DEVS]; static int n_piix_devs; +static int no_piix_dma = 0; /** * piix_get_info - fill in /proc for PIIX ide @@ -96,7 +134,7 @@ for (i = 0; i < n_piix_devs; i++) { struct pci_dev *dev = piix_devs[i]; - u32 bibma = pci_resource_start(dev, 4); + unsigned long bibma = pci_resource_start(dev, 4); u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; u8 c0 = 0, c1 = 0, reg54 = 0, reg55 = 0; u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0; @@ -155,8 +193,8 @@ * at that point bibma+0x2 et bibma+0xa are byte registers * to investigate: */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); + c0 = inb(bibma + 0x02); + c1 = inb(bibma + 0x0a); p += sprintf(p, "--------------- Primary Channel " "---------------- Secondary Channel " @@ -443,6 +481,33 @@ } /** + * piix_faulty_dma0 - check for DMA0 errata + * @hwif: IDE interface to check + * + * If an ICH/ICH0/ICH2 interface is is operating in multi-word + * DMA mode with 600nS cycle time the IDE PIO prefetch buffer will + * inadvertently provide an extra piece of secondary data to the primary + * device resulting in data corruption. + * + * With such a device this test function returns true. This allows + * our tuning code to follow Intel recommendations and use PIO on + * such devices. + */ + +static int piix_faulty_dma0(ide_hwif_t *hwif) +{ + switch(hwif->pci_dev->device) + { + case PCI_DEVICE_ID_INTEL_82801AA_1: /* ICH */ + case PCI_DEVICE_ID_INTEL_82801AB_1: /* ICH0 */ + case PCI_DEVICE_ID_INTEL_82801BA_8: /* ICH2 */ + case PCI_DEVICE_ID_INTEL_82801BA_9: /* ICH2 */ + return 1; + } + return 0; +} + +/** * piix_config_drive_for_dma - configure drive for DMA * @drive: IDE drive to configure * @@ -454,8 +519,15 @@ static int piix_config_drive_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); - - if (!(speed)) { + + /* Some ICH devices cannot support DMA mode 0 */ + if(speed == XFER_MW_DMA_0 && piix_faulty_dma0(HWIF(drive))) + speed = 0; + + /* If no DMA speed was available or the chipset has DMA bugs + then disable DMA and use PIO */ + + if (!speed || no_piix_dma) { u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); speed = piix_dma_2_pio(XFER_PIO_0 + tspeed); } @@ -675,6 +747,37 @@ return 0; } +/** + * piix_check_450nx - Check for problem 450NX setup + * + * Check for the present of 450NX errata #19 and errata #25. If + * they are found, disable use of DMA IDE + */ + +static void __init piix_check_450nx(void) +{ + struct pci_dev *pdev = NULL; + u16 cfg; + u8 rev; + while((pdev=pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL) + { + /* Look for 450NX PXB. Check for problem configurations + A PCI quirk checks bit 6 already */ + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); + pci_read_config_word(pdev, 0x41, &cfg); + /* Only on the original revision: IDE DMA can hang */ + if(rev == 0x00) + no_piix_dma = 1; + /* On all revisions PXB bus lock must be disabled for IDE */ + else if(cfg & (1<<14)) + no_piix_dma = 2; + } + if(no_piix_dma) + printk(KERN_WARNING "piix: 450NX errata present, disabling IDE DMA.\n"); + if(no_piix_dma == 2) + printk(KERN_WARNING "piix: A BIOS update may resolve this.\n"); +} + static struct pci_device_id piix_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, @@ -703,6 +806,7 @@ static int piix_ide_init(void) { + piix_check_450nx(); return ide_pci_register_driver(&driver); } diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c --- a/drivers/ide/pci/sc1200.c Mon Jan 13 10:18:06 2003 +++ b/drivers/ide/pci/sc1200.c Mon Jan 13 10:18:06 2003 @@ -83,7 +83,7 @@ static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); + unsigned long bibma = pci_resource_start(bmide_dev, 4); u8 c0 = 0, c1 = 0; /* @@ -91,8 +91,8 @@ * to investigate: */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); + c0 = inb_p(bibma + 0x02); + c1 = inb_p(bibma + 0x0a); p += sprintf(p, "\n National SCx200 Chipset.\n"); p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c --- a/drivers/ide/pci/serverworks.c Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/pci/serverworks.c Mon Jan 13 10:18:05 2003 @@ -61,7 +61,7 @@ for (i = 0; i < n_svwks_devs; i++) { struct pci_dev *dev = svwks_devs[i]; - u32 bibma = pci_resource_start(dev, 4); + unsigned long bibma = pci_resource_start(dev, 4); u32 reg40, reg44; u16 reg48, reg56; u8 reg54, c0=0, c1=0; @@ -76,8 +76,8 @@ * at that point bibma+0x2 et bibma+0xa are byte registers * to investigate: */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); + c0 = inb_p(bibma + 0x02); + c1 = inb_p(bibma + 0x0a); p += sprintf(p, "\n ServerWorks "); switch(dev->device) { diff -Nru a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c --- a/drivers/ide/pci/slc90e66.c Mon Jan 13 10:18:07 2003 +++ b/drivers/ide/pci/slc90e66.c Mon Jan 13 10:18:07 2003 @@ -34,7 +34,7 @@ static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); + unsigned long bibma = pci_resource_start(bmide_dev, 4); u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; u8 c0 = 0, c1 = 0; u8 reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0; diff -Nru a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/pci/triflex.c Mon Jan 13 10:18:07 2003 @@ -0,0 +1,252 @@ +/* + * triflex.c + * + * IDE Chipset driver for the Compaq TriFlex IDE controller. + * + * Known to work with the Compaq Workstation 5x00 series. + * + * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. + * Author: Torben Mathiasen + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Loosely based on the piix & svwks drivers. + * + * Documentation: + * Not publically available. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" +#include "triflex.h" + +static struct pci_dev *triflex_dev; + +static int triflex_get_info(char *buf, char **addr, off_t offset, int count) +{ + char *p = buf; + + struct pci_dev *dev = triflex_dev; + unsigned long bibma = pci_resource_start(dev, 4); + u8 c0 = 0, c1 = 0; + u32 pri_timing, sec_timing; + + p += sprintf(p, "\n Compaq Triflex Chipset\n"); + + pci_read_config_dword(dev, 0x70, &pri_timing); + pci_read_config_dword(dev, 0x74, &sec_timing); + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb((unsigned short)bibma + 0x02); + c1 = inb((unsigned short)bibma + 0x0a); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + + return p-buf; +} + +static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 channel_offset = hwif->channel ? 0x74 : 0x70; + u16 timing = 0; + u32 triflex_timings = 0; + u8 unit = (drive->select.b.unit & 0x01); + u8 speed = ide_rate_filter(0, xferspeed); + + pci_read_config_dword(dev, channel_offset, &triflex_timings); + + switch(speed) { + case XFER_MW_DMA_2: + timing = 0x0103; + break; + case XFER_MW_DMA_1: + timing = 0x0203; + break; + case XFER_MW_DMA_0: + timing = 0x0808; + break; + case XFER_SW_DMA_2: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + timing = 0x0f0f; + break; + case XFER_PIO_4: + timing = 0x0202; + break; + case XFER_PIO_3: + timing = 0x0204; + break; + case XFER_PIO_2: + timing = 0x0404; + break; + case XFER_PIO_1: + timing = 0x0508; + break; + case XFER_PIO_0: + timing = 0x0808; + break; + default: + return -1; + } + + triflex_timings &= ~(0xFFFF << (16 * unit)); + triflex_timings |= (timing << (16 * unit)); + + pci_write_config_dword(dev, channel_offset, triflex_timings); + + return (ide_config_drive_speed(drive, speed)); +} + +static void triflex_tune_drive(ide_drive_t *drive, u8 pio) +{ + int use_pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void) triflex_tune_chipset(drive, (XFER_PIO_0 + use_pio)); +} + +static int triflex_config_drive_for_dma(ide_drive_t *drive) +{ + int speed = ide_dma_speed(drive, 0); /* No ultra speeds */ + + if (!speed) { + u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL); + speed = XFER_PIO_0 + pspeed; + } + + (void) triflex_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int triflex_config_drive_xfer_rate(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + if (id && (id->capability & 1) && drive->autodma) { + if (hwif->ide_dma_bad_drive(drive)) + goto tune_pio; + if (id->field_valid & 2) { + if ((id->dma_mword & hwif->mwdma_mask) || + (id->dma_1word & hwif->swdma_mask)) { + if (!triflex_config_drive_for_dma(drive)) + goto tune_pio; + } + } else + goto tune_pio; + } else { +tune_pio: + hwif->tuneproc(drive, 255); + return hwif->ide_dma_off_quietly(drive); + } + + return hwif->ide_dma_on(drive); +} + +static void __init init_hwif_triflex(ide_hwif_t *hwif) +{ + hwif->tuneproc = &triflex_tune_drive; + hwif->speedproc = &triflex_tune_chipset; + + hwif->atapi_dma = 1; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + hwif->ide_dma_check = &triflex_config_drive_xfer_rate; + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static unsigned int __init init_chipset_triflex(struct pci_dev *dev, + const char *name) +{ +#ifdef CONFIG_PROC_FS + ide_pci_register_host_proc(&triflex_proc); +#endif + return 0; +} + +static int __devinit triflex_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + ide_pci_device_t *d = &triflex_devices[id->driver_data]; + if (dev->device != d->device) + BUG(); + + ide_setup_pci_device(dev, d); + triflex_dev = dev; + MOD_INC_USE_COUNT; + + return 0; +} + +static struct pci_driver driver = { + .name = "TRIFLEX IDE", + .id_table = triflex_pci_tbl, + .probe = triflex_init_one, +}; + +static int triflex_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void triflex_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(triflex_ide_init); +module_exit(triflex_ide_exit); + +MODULE_AUTHOR("Torben Mathiasen"); +MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE"); +MODULE_LICENSE("GPL"); + + diff -Nru a/drivers/ide/pci/triflex.h b/drivers/ide/pci/triflex.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ide/pci/triflex.h Mon Jan 13 10:18:07 2003 @@ -0,0 +1,55 @@ +/* + * triflex.h + * + * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. + * Author: Torben Mathiasen + * + */ +#ifndef TRIFLEX_H +#define TRIFLEX_H + +#include +#include +#include + +static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *); +static void init_hwif_triflex(ide_hwif_t *); +static int triflex_get_info(char *, char **, off_t, int); + +static ide_pci_device_t triflex_devices[] __devinitdata = { + { + .vendor PCI_VENDOR_ID_COMPAQ, + .device PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, + .name "TRIFLEX", + .init_chipset init_chipset_triflex, + .init_iops NULL, + .init_hwif init_hwif_triflex, + .channels 2, + .autodma AUTODMA, + .enablebits {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, + .bootable ON_BOARD, + .extra 0, + },{ + .vendor 0, + .device 0, + .channels 0, + .bootable EOL, + } +}; + +#ifdef CONFIG_PROC_FS +static ide_pci_host_proc_t triflex_proc __initdata = { + name: "triflex", + set: 1, + get_info: triflex_get_info, + parent: NULL, +}; +#endif + +static struct pci_device_id triflex_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0 }, + { 0, }, +}; + +#endif /* TRIFLEX_H */ diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c Mon Jan 13 10:18:05 2003 +++ b/drivers/ide/setup-pci.c Mon Jan 13 10:18:05 2003 @@ -315,7 +315,7 @@ "Could not enable device.\n", d->name); return -EBUSY; } else - printk(KERN_WARNING "%s: Not fully BIOS configured!\n", d->name); + printk(KERN_WARNING "%s: BIOS configuration fixed.\n", d->name); } /* @@ -482,7 +482,7 @@ if ((d->autodma == AUTODMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { - u32 dma_base = ide_get_or_set_dma_base(hwif); + unsigned long dma_base = ide_get_or_set_dma_base(hwif); if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { /* * Set up BM-DMA capability diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c --- a/drivers/input/gameport/gameport.c Mon Jan 13 10:18:06 2003 +++ b/drivers/input/gameport/gameport.c Mon Jan 13 10:18:06 2003 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c --- a/drivers/input/gameport/ns558.c Mon Jan 13 10:18:07 2003 +++ b/drivers/input/gameport/ns558.c Mon Jan 13 10:18:07 2003 @@ -194,7 +194,7 @@ int ioport, iolen; struct ns558 *port; - if (!(dev->resource[0].flags & IORESOURCE_IO)) { + if (!pnp_port_valid(dev, 0)) { printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n"); return -ENODEV; } diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig --- a/drivers/input/serio/Kconfig Mon Jan 13 10:18:06 2003 +++ b/drivers/input/serio/Kconfig Mon Jan 13 10:18:06 2003 @@ -89,6 +89,7 @@ config SERIO_RPCKBD tristate "Acorn RiscPC keyboard controller" depends on ARCH_ACORN && SERIO + default y help Say Y here if you have the Acorn RiscPC and want to use an AT keyboard connected to its keyboard controller. diff -Nru a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c --- a/drivers/isdn/divert/divert_init.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/divert/divert_init.c Mon Jan 13 10:18:06 2003 @@ -51,9 +51,6 @@ printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n",i); return(-EIO); } -#if (LINUX_VERSION_CODE < 0x020111) - register_symtab(0); -#endif printk(KERN_INFO "dss1_divert module successfully installed\n"); return(0); } diff -Nru a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig --- a/drivers/isdn/hisax/Kconfig Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/Kconfig Mon Jan 13 10:18:07 2003 @@ -109,6 +109,7 @@ config HISAX_TELESPCI bool "Teles PCI" + depends on PCI help This enables HiSax support for the Teles PCI. See on how to configure it. @@ -235,6 +236,7 @@ config HISAX_NETJET bool "NETjet card" + depends on PCI help This enables HiSax support for the NetJet from Traverse Technologies. @@ -245,6 +247,7 @@ config HISAX_NETJET_U bool "NETspider U card" + depends on PCI help This enables HiSax support for the Netspider U interface ISDN card from Traverse Technologies. @@ -283,6 +286,7 @@ config HISAX_BKM_A4T bool "Telekom A4T card" + depends on PCI help This enables HiSax support for the Telekom A4T card. @@ -292,6 +296,7 @@ config HISAX_SCT_QUADRO bool "Scitel Quadro card" + depends on PCI help This enables HiSax support for the Scitel Quadro card. @@ -310,6 +315,7 @@ config HISAX_HFC_PCI bool "HFC PCI-Bus cards" + depends on PCI help This enables HiSax support for the HFC-S PCI 2BDS0 based cards. @@ -318,6 +324,7 @@ config HISAX_W6692 bool "Winbond W6692 based cards" + depends on PCI help This enables HiSax support for Winbond W6692 based PCI ISDN cards. @@ -335,7 +342,7 @@ config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on PCI && EXPERIMENTAL help This enables HiSax support for the Formula-n enter:now PCI ISDN card. @@ -397,14 +404,14 @@ config HISAX_FRITZ_CLASSIC tristate "AVM Fritz!Card classic support (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on ISA && EXPERIMENTAL help This enables the driver for the AVM Fritz!Card classic, formerly known as AVM A1. config HISAX_HFCPCI tristate "HFC PCI support (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on PCI && EXPERIMENTAL help This enables the driver for CCD HFC PCI based cards. diff -Nru a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile --- a/drivers/isdn/hisax/Makefile Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/Makefile Mon Jan 13 10:18:05 2003 @@ -38,12 +38,12 @@ hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o -hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o ipac.o hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o -hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o +hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o ipac.o hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o -hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o +hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o ipac.o isar.o hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o @@ -55,8 +55,8 @@ hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o hisax-objs-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o -hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o -hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o +hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o ipac.o +hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o ipac.o hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o hisax-objs-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o #hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c --- a/drivers/isdn/hisax/amd7930.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/amd7930.c Mon Jan 13 10:18:05 2003 @@ -686,31 +686,19 @@ Bchan_mode(cs->bcs + 1, 0, 0); } -void -release_amd7930(struct IsdnCardState *cs) -{ -} - static int -amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg) +amd7930_init(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - return(0); - case CARD_RELEASE: - release_amd7930(cs); - return(0); - case CARD_INIT: - cs->l1cmd = amd7930_l1cmd; - amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs); - init_amd7930(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); + cs->l1cmd = amd7930_l1cmd; + amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs); + init_amd7930(cs); + return 0; } +static struct card_ops amd7930_ops = { + .init = amd7930_init, +}; + int __init setup_amd7930(struct IsdnCard *card) { @@ -719,14 +707,11 @@ strcpy(tmp, amd7930_revision); printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_AMD7930) - return (0); cs->irq = amd7930_get_irqnum(0); if (cs->irq == 0) - return (0); - - cs->cardmsg = &amd7930_card_msg; + return 0; - return (1); + cs->card_ops = &amd7930_ops; + return 1; } diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c --- a/drivers/isdn/hisax/amd7930_fn.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/amd7930_fn.c Mon Jan 13 10:18:06 2003 @@ -659,7 +659,7 @@ } } -void +static int setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs) { @@ -667,16 +667,9 @@ debugl1(cs, "Amd7930: setstack called"); st->l1.l1hw = Amd7930_l1hw; + return 0; } - -void -DC_Close_Amd7930(struct IsdnCardState *cs) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "Amd7930: DC_Close called"); -} - - static void dbusy_timer_handler(struct IsdnCardState *cs) { @@ -723,7 +716,7 @@ /* Transmitter reset, abort transmit */ wByteAMD(cs, 0x21, 0x82); wByteAMD(cs, 0x21, 0x02); - cs->irq_func(cs->irq, cs, NULL); + cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset"); @@ -764,26 +757,26 @@ 0xFFFF}; +static struct dc_l1_ops amd7930_l1_ops = { + .open = setstack_Amd7930, + .bh_func = Amd7930_bh, + .dbusy_func = dbusy_timer_handler, +}; void __devinit Amd7930_init(struct IsdnCardState *cs) { - u16 *ptr; - u8 cmd, cnt; + u16 *ptr; + u8 cmd, cnt; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: initamd called"); + dc_l1_init(cs, &amd7930_l1_ops); cs->dc.amd7930.tx_xmtlen = 0; cs->dc.amd7930.old_state = 0; cs->dc.amd7930.lmr1 = 0x40; cs->dc.amd7930.ph_command = Amd7930_ph_command; - INIT_WORK(&cs->work, Amd7930_bh, cs); - cs->setstack_d = setstack_Amd7930; - cs->DC_Close = DC_Close_Amd7930; - cs->dbusytimer.function = (void *) dbusy_timer_handler; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); /* AMD Initialisation */ for (ptr = initAMD; *ptr != 0xFFFF; ) { @@ -810,4 +803,13 @@ wByteAMD(cs, 0x01, LOBYTE(*ptr++)); } } +} + +int +amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops, + void (*set_irq_mask)(struct IsdnCardState *, u8 val)) +{ + cs->dc_hw_ops = amd7930_ops; + cs->dc.amd7930.setIrqMask = set_irq_mask; + return 0; } diff -Nru a/drivers/isdn/hisax/amd7930_fn.h b/drivers/isdn/hisax/amd7930_fn.h --- a/drivers/isdn/hisax/amd7930_fn.h Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/amd7930_fn.h Mon Jan 13 10:18:07 2003 @@ -18,5 +18,7 @@ #define DBUSY_TIMER_VALUE 80 -extern void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags); -extern void Amd7930_init(struct IsdnCardState *cs); +void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags); +void Amd7930_init(struct IsdnCardState *cs); +int amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops, + void (*set_irq_mask)(struct IsdnCardState *, u8 val)); diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c --- a/drivers/isdn/hisax/asuscom.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/asuscom.c Mon Jan 13 10:18:07 2003 @@ -114,37 +114,6 @@ }; static u8 -ipac_dc_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, cs->hw.asus.isac, offset|0x80); -} - -static void -ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - writereg(cs, cs->hw.asus.isac, offset|0x80, value); -} - -static void -ipac_dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - readfifo(cs, cs->hw.asus.isac, 0x80, data, size); -} - -static void -ipac_dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - writefifo(cs, cs->hw.asus.isac, 0x80, data, size); -} - -static struct dc_hw_ops ipac_dc_ops = { - .read_reg = ipac_dc_read, - .write_reg = ipac_dc_write, - .read_fifo = ipac_dc_read_fifo, - .write_fifo = ipac_dc_write_fifo, -}; - -static u8 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) { return readreg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0)); @@ -175,141 +144,93 @@ .write_fifo = hscx_write_fifo, }; -static void -asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs) +static inline u8 +ipac_read(struct IsdnCardState *cs, u8 off) { - struct IsdnCardState *cs = dev_id; - u8 val; + u8 ret; + unsigned long flags; - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); + spin_lock_irqsave(&asuscom_lock, flags); + byteout(cs->hw.asus.adr, off); + ret = bytein(cs->hw.asus.isac); + spin_unlock_irqrestore(&asuscom_lock, flags); + return ret; } -static void -asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +static inline void +ipac_write(struct IsdnCardState *cs, u8 off, u8 data) { - struct IsdnCardState *cs = dev_id; - u8 ista, val, icnt = 5; + unsigned long flags; - if (!cs) { - printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n"); - return; - } - ista = readreg(cs, cs->hw.asus.isac, IPAC_ISTA); -Start_IPAC: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = hscx_read(cs, 1, HSCX_ISTA); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) - hscx_int_main(cs, val); - } - if (ista & 0x20) { - val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe; - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = readreg(cs, cs->hw.asus.isac, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPAC; - } - if (!icnt) - printk(KERN_WARNING "ASUS IRQ LOOP\n"); - writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xFF); - writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xC0); + spin_lock_irqsave(&asuscom_lock, flags); + byteout(cs->hw.asus.adr, off); + byteout(cs->hw.asus.isac, data); + spin_unlock_irqrestore(&asuscom_lock, flags); } -void -release_io_asuscom(struct IsdnCardState *cs) +static inline void +ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) { - int bytecnt = 8; + byteout(cs->hw.asus.adr, off); + insb(cs->hw.asus.isac, data, size); +} - if (cs->hw.asus.cfg_reg) - release_region(cs->hw.asus.cfg_reg, bytecnt); + +static inline void +ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) +{ + byteout(cs->hw.asus.adr, off); + outsb(cs->hw.asus.isac, data, size); } -static void -reset_asuscom(struct IsdnCardState *cs) +/* This will generate ipac_dc_ops and ipac_bc_ops using the functions + * above */ + +BUILD_IPAC_OPS(ipac); + +static int +asuscom_reset(struct IsdnCardState *cs) { - if (cs->subtyp == ASUS_IPAC) - writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20); - else - byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ + byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); - if (cs->subtyp == ASUS_IPAC) - writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0); - else - byteout(cs->hw.asus.adr, 0); /* Reset Off */ + byteout(cs->hw.asus.adr, 0); /* Reset Off */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); - if (cs->subtyp == ASUS_IPAC) { - writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0); - writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff); - writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0); - writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0); - writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12); - } + return 0; } static int -Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg) +asuscom_ipac_reset(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - reset_asuscom(cs); - return(0); - case CARD_RELEASE: - release_io_asuscom(cs); - return(0); - case CARD_INIT: - cs->debug |= L1_DEB_IPAC; - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); + writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0); + writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff); + writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0); + writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0); + writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12); + return 0; } +static struct card_ops asuscom_ops = { + .init = inithscxisac, + .reset = asuscom_reset, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; + +static struct card_ops asuscom_ipac_ops = { + .init = ipac_init, + .reset = asuscom_ipac_reset, + .release = hisax_release_resources, + .irq_func = ipac_irq, +}; + #ifdef __ISAPNP__ static struct isapnp_device_id asus_ids[] __initdata = { { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688), @@ -328,7 +249,7 @@ }; static struct isapnp_device_id *adev = &asus_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __init @@ -341,33 +262,40 @@ strcpy(tmp, Asuscom_revision); printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_ASUSCOM) - return (0); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; while(adev->card_vendor) { - if ((pb = isapnp_find_card(adev->card_vendor, - adev->card_device, pnp_c))) { + if ((pb = pnp_find_card(adev->card_vendor, + adev->card_device, + pnp_c))) { pnp_c = pb; pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - adev->vendor, adev->function, pd))) { + if ((pd = pnp_find_dev(pnp_c, + adev->vendor, + adev->function, + pd))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)adev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = pd->resource[0].start; - card->para[0] = pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "AsusPnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "AsusPnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n", - card->para[0], card->para[1]); - pd->deactivate(pd); + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); return(0); } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "AsusPnP: PnP error card found, no device\n"); @@ -385,47 +313,33 @@ bytecnt = 8; cs->hw.asus.cfg_reg = card->para[1]; cs->irq = card->para[0]; - if (!request_region((cs->hw.asus.cfg_reg), bytecnt, - "asuscom isdn")) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.asus.cfg_reg, - cs->hw.asus.cfg_reg + bytecnt); - return (0); - } + if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) + goto err; printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n", cs->hw.asus.cfg_reg, cs->irq); - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &Asus_card_msg; cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); if ((val == 1) || (val == 2)) { cs->subtyp = ASUS_IPAC; + cs->card_ops = &asuscom_ipac_ops; cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; - cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; - test_and_set_bit(HW_IPAC, &cs->HW_Flags); - cs->dc_hw_ops = &ipac_dc_ops; - cs->irq_func = &asuscom_interrupt_ipac; - printk(KERN_INFO "Asus: IPAC version %x\n", val); + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; } else { cs->subtyp = ASUS_ISACHSCX; + cs->card_ops = &asuscom_ops; cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; - cs->dc_hw_ops = &isac_ops; - cs->irq_func = &asuscom_interrupt; - ISACVersion(cs, "ISDNLink:"); - if (HscxVersion(cs, "ISDNLink:")) { - printk(KERN_WARNING - "ISDNLink: wrong HSCX versions check IO address\n"); - release_io_asuscom(cs); - return (0); - } + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; } printk(KERN_INFO "ISDNLink: resetting card\n"); - reset_asuscom(cs); - return (1); + cs->card_ops->reset(cs); + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c --- a/drivers/isdn/hisax/avm_a1.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/avm_a1.c Mon Jan 13 10:18:05 2003 @@ -146,43 +146,19 @@ spin_unlock(&cs->lock); } -inline static void -release_ioregs(struct IsdnCardState *cs, int mask) +static void +avm_a1_init(struct IsdnCardState *cs) { - release_region(cs->hw.avm.cfg_reg, 8); - if (mask & 1) - release_region(cs->hw.avm.isac + 32, 32); - if (mask & 2) - release_region(cs->hw.avm.isacfifo, 1); - if (mask & 4) - release_region(cs->hw.avm.hscx[0] + 32, 32); - if (mask & 8) - release_region(cs->hw.avm.hscxfifo[0], 1); - if (mask & 0x10) - release_region(cs->hw.avm.hscx[1] + 32, 32); - if (mask & 0x20) - release_region(cs->hw.avm.hscxfifo[1], 1); + byteout(cs->hw.avm.cfg_reg, 0x16); + byteout(cs->hw.avm.cfg_reg, 0x1E); + inithscxisac(cs); } -static int -AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - return(0); - case CARD_RELEASE: - release_ioregs(cs, 0x3f); - return(0); - case CARD_INIT: - byteout(cs->hw.avm.cfg_reg, 0x16); - byteout(cs->hw.avm.cfg_reg, 0x1E); - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} +static struct card_ops avm_a1_ops = { + .init = avm_a1_init, + .release = hisax_release_resources, + .irq_func = avm_a1_interrupt, +}; int __init setup_avm_a1(struct IsdnCard *card) @@ -193,76 +169,26 @@ strcpy(tmp, avm_revision); printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_A1) - return (0); - cs->hw.avm.cfg_reg = card->para[1] + 0x1800; - cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20; - cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20; - cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20; - cs->hw.avm.isacfifo = card->para[1] + 0x1000; - cs->hw.avm.hscxfifo[0] = card->para[1]; - cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800; + cs->hw.avm.cfg_reg = request_io(&cs->rs, card->para[1] + 0x1800, 8, "avm cfg"); + if (!cs->hw.avm.cfg_reg) goto err; + cs->hw.avm.isac = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac"); + if (!cs->hw.avm.isac) goto err; + cs->hw.avm.isacfifo = request_io(&cs->rs, card->para[1] + 0x1000, 1, "HiSax isac fifo"); + if (!cs->hw.avm.isacfifo) goto err; + cs->hw.avm.hscx[0] = request_io(&cs->rs, card->para[1] + 0x400, 32, "HiSax hscx A"); + if (!cs->hw.avm.hscx[0]) goto err; + cs->hw.avm.hscxfifo[0] = request_io(&cs->rs, card->para[1], 1, "HiSax hscx A fifo"); + if (!cs->hw.avm.hscxfifo[0]) goto err; + cs->hw.avm.hscx[1] = request_io(&cs->rs, card->para[1] + 0xc00, 32, "HiSax hscx B"); + if (!cs->hw.avm.hscx[1]) goto err; + cs->hw.avm.hscxfifo[1] = request_io(&cs->rs, card->para[1] + 0x800, 1, "HiSax hscx B fifo"); + if (!cs->hw.avm.hscxfifo[1]) goto err; + cs->hw.avm.isac -= 0x20; + cs->hw.avm.hscx[0] -= 0x20; + cs->hw.avm.hscx[1] -= 0x20; cs->irq = card->para[0]; - if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.avm.cfg_reg, - cs->hw.avm.cfg_reg + 8); - return (0); - } - if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) { - printk(KERN_WARNING - "HiSax: %s isac ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.avm.isac + 32, - cs->hw.avm.isac + 64); - release_ioregs(cs, 0); - return (0); - } - if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) { - printk(KERN_WARNING - "HiSax: %s isac fifo port %x already in use\n", - CardType[cs->typ], - cs->hw.avm.isacfifo); - release_ioregs(cs, 1); - return (0); - } - if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) { - printk(KERN_WARNING - "HiSax: %s hscx A ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.avm.hscx[0] + 32, - cs->hw.avm.hscx[0] + 64); - release_ioregs(cs, 3); - return (0); - } - if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) { - printk(KERN_WARNING - "HiSax: %s hscx A fifo port %x already in use\n", - CardType[cs->typ], - cs->hw.avm.hscxfifo[0]); - release_ioregs(cs, 7); - return (0); - } - if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) { - printk(KERN_WARNING - "HiSax: %s hscx B ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.avm.hscx[1] + 32, - cs->hw.avm.hscx[1] + 64); - release_ioregs(cs, 0xf); - return (0); - } - if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) { - printk(KERN_WARNING - "HiSax: %s hscx B fifo port %x already in use\n", - CardType[cs->typ], - cs->hw.avm.hscxfifo[1]); - release_ioregs(cs, 0x1f); - return (0); - } + byteout(cs->hw.avm.cfg_reg, 0x0); HZDELAY(HZ / 5 + 1); byteout(cs->hw.avm.cfg_reg, 0x1); @@ -302,16 +228,11 @@ cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0], cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &AVM_card_msg; - cs->irq_func = &avm_a1_interrupt; - ISACVersion(cs, "AVM A1:"); - if (HscxVersion(cs, "AVM A1:")) { - printk(KERN_WARNING - "AVM A1: wrong HSCX versions check IO address\n"); - release_ioregs(cs, 0x3f); - return (0); - } - return (1); + cs->card_ops = &avm_a1_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c --- a/drivers/isdn/hisax/avm_a1p.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/avm_a1p.c Mon Jan 13 10:18:07 2003 @@ -189,39 +189,32 @@ spin_unlock(&cs->lock); } +static void +avm_a1p_init(struct IsdnCardState *cs) +{ + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, + ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); + inithscxisac(cs); +} + static int -AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +avm_a1p_reset(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); - HZDELAY(HZ / 5 + 1); - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); - HZDELAY(HZ / 5 + 1); - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); - return 0; - - case CARD_RELEASE: - /* free_irq is done in HiSax_closecard(). */ - /* free_irq(cs->irq, cs); */ - return 0; - - case CARD_INIT: - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); - inithscxisac(cs); - return 0; - - case CARD_TEST: - /* we really don't need it for the PCMCIA Version */ - return 0; - - default: - /* all card drivers ignore others, so we do the same */ - return 0; - } + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + return 0; } +static struct card_ops avm_a1p_ops = { + .init = avm_a1p_init, + .reset = avm_a1p_reset, + .irq_func = avm_a1p_interrupt, +}; + int __devinit setup_avm_a1_pcmcia(struct IsdnCard *card) { @@ -232,10 +225,7 @@ strcpy(tmp, avm_revision); printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", - HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_A1_PCMCIA) - return (0); - + HiSax_getrev(tmp)); cs->hw.avm.cfg_reg = card->para[1]; cs->irq = card->para[0]; @@ -256,16 +246,9 @@ printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n", cs->hw.avm.cfg_reg, cs->irq, model, vers); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &AVM_card_msg; - cs->irq_func = &avm_a1p_interrupt; - - ISACVersion(cs, "AVM A1 PCMCIA:"); - if (HscxVersion(cs, "AVM A1 PCMCIA:")) { - printk(KERN_WARNING - "AVM A1 PCMCIA: wrong HSCX versions check IO address\n"); - return (0); - } - return (1); + cs->card_ops = &avm_a1p_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + return 0; + + return 1; } diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/avm_pci.c Mon Jan 13 10:18:05 2003 @@ -175,6 +175,39 @@ spin_unlock_irqrestore(&avm_pci_lock, flags); } +static void +hdlc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len) +{ + u8 idx = hscx ? AVM_HDLC_2 : AVM_HDLC_1; + int i; + + if (cs->subtyp == AVM_FRITZ_PCI) { + u32 *ptr = (u32 *) data; + + outl(idx, cs->hw.avm.cfg_reg + 4); + for (i = 0; i < len; i += 4) { +#ifdef __powerpc__ +#ifdef CONFIG_APUS + *ptr++ = in_le32((u32 *)(cs->hw.avm.isac +_IO_BASE)); +#else + *ptr++ = in_be32((u32 *)(cs->hw.avm.isac +_IO_BASE)); +#endif /* CONFIG_APUS */ +#else + *ptr++ = inl(cs->hw.avm.isac); +#endif /* __powerpc__ */ + } + } else { + outb(idx, cs->hw.avm.cfg_reg + 4); + for (i = 0; i < len; i++) { + *data++ = inb(cs->hw.avm.isac); + } + } +} + +static struct bc_hw_ops hdlc_hw_ops = { + .read_fifo = hdlc_read_fifo, +}; + static inline struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel) { @@ -259,52 +292,7 @@ static inline void hdlc_empty_fifo(struct BCState *bcs, int count) { - register u_int *ptr; - u8 *p; - u8 idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1; - int cnt=0; - struct IsdnCardState *cs = bcs->cs; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "hdlc_empty_fifo %d", count); - if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "hdlc_empty_fifo: incoming packet too large"); - return; - } - ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx; - bcs->hw.hdlc.rcvidx += count; - if (cs->subtyp == AVM_FRITZ_PCI) { - outl(idx, cs->hw.avm.cfg_reg + 4); - while (cnt < count) { -#ifdef __powerpc__ -#ifdef CONFIG_APUS - *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); -#else - *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); -#endif /* CONFIG_APUS */ -#else - *ptr++ = inl(cs->hw.avm.isac); -#endif /* __powerpc__ */ - cnt += 4; - } - } else { - outb(idx, cs->hw.avm.cfg_reg + 4); - while (cnt < count) { - *p++ = inb(cs->hw.avm.isac); - cnt++; - } - } - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - if (cs->subtyp == AVM_FRITZ_PNP) - p = (u8 *) ptr; - t += sprintf(t, "hdlc_empty_fifo %c cnt %d", - bcs->channel ? 'B' : 'A', count); - QuickHex(t, p, count); - debugl1(cs, bcs->blog); - } + recv_empty_fifo_b(bcs, count); } static void @@ -360,15 +348,10 @@ hdlc_fill_fifo(bcs); } -static struct bc_l1_ops hdlc_l1_ops = { - .fill_fifo = hdlc_fill_fifo, -}; - static inline void HDLC_irq(struct BCState *bcs, u_int stat) { int len; - struct sk_buff *skb; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat); @@ -384,7 +367,7 @@ write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS; write_ctrl(bcs, 1); - bcs->hw.hdlc.rcvidx = 0; + bcs->rcvidx = 0; } else { if (!(len = (stat & HDLC_STAT_RML_MASK)>>8)) len = 32; @@ -392,21 +375,13 @@ if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) { if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) || (bcs->mode == L1_MODE_TRANS)) { - if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx))) - printk(KERN_WARNING "HDLC: receive out of memory\n"); - else { - memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx), - bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx); - skb_queue_tail(&bcs->rqueue, skb); - } - bcs->hw.hdlc.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); + recv_rme_b(bcs); } else { if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "invalid frame"); else debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat); - bcs->hw.hdlc.rcvidx = 0; + bcs->rcvidx = 0; } } } @@ -492,57 +467,20 @@ close_hdlcstate(struct BCState *bcs) { modehdlc(bcs, 0, 0); - if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hdlc.rcvbuf) { - kfree(bcs->hw.hdlc.rcvbuf); - bcs->hw.hdlc.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - if (bcs->tx_skb) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - } - } + bc_close(bcs); } int open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs) { - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for hdlc.rcvbuf\n"); - return (1); - } - if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for bcs->blog\n"); - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); - kfree(bcs->hw.hdlc.rcvbuf); - bcs->hw.hdlc.rcvbuf = NULL; - return (2); - } - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - } - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->event = 0; - bcs->hw.hdlc.rcvidx = 0; - bcs->tx_cnt = 0; - return (0); + return bc_open(bcs); } int setstack_hdlc(struct PStack *st, struct BCState *bcs) { bcs->channel = st->l1.bc; + bcs->unit = bcs->channel; if (open_hdlcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; @@ -553,6 +491,12 @@ return (0); } +static struct bc_l1_ops hdlc_l1_ops = { + .fill_fifo = hdlc_fill_fifo, + .open = setstack_hdlc, + .close = close_hdlcstate, +}; + void __init inithdlc(struct IsdnCardState *cs) { @@ -582,10 +526,6 @@ debugl1(cs, "HDLC 2 VIN %x", val); } - cs->bcs[0].BC_SetStack = setstack_hdlc; - cs->bcs[1].BC_SetStack = setstack_hdlc; - cs->bcs[0].BC_Close = close_hdlcstate; - cs->bcs[1].BC_Close = close_hdlcstate; modehdlc(cs->bcs, -1, 0); modehdlc(cs->bcs + 1, -1, 1); } @@ -616,8 +556,8 @@ WriteISAC(cs, ISAC_MASK, 0x0); } -static void -reset_avmpcipnp(struct IsdnCardState *cs) +static int +avm_pcipnp_reset(struct IsdnCardState *cs) { printk(KERN_INFO "AVM PCI/PnP: reset\n"); outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2); @@ -628,37 +568,38 @@ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3)); + return 0; } -static int -AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +avm_pcipnp_init(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - reset_avmpcipnp(cs); - return(0); - case CARD_RELEASE: - outb(0, cs->hw.avm.cfg_reg + 2); - release_region(cs->hw.avm.cfg_reg, 32); - return(0); - case CARD_INIT: - initisac(cs); - inithdlc(cs); - outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, - cs->hw.avm.cfg_reg + 2); - outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | - AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); - return(0); - case CARD_TEST: - return(0); - } - return(0); + initisac(cs); + inithdlc(cs); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, + cs->hw.avm.cfg_reg + 2); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | + AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); +} + +static void +avm_pcipnp_release(struct IsdnCardState *cs) +{ + outb(0, cs->hw.avm.cfg_reg + 2); + hisax_release_resources(cs); } +static struct card_ops avm_pci_ops = { + .init = avm_pcipnp_init, + .reset = avm_pcipnp_reset, + .release = avm_pcipnp_release, + .irq_func = avm_pcipnp_interrupt, +}; + static struct pci_dev *dev_avm __initdata = NULL; #ifdef __ISAPNP__ -static struct pci_bus *bus_avm __initdata = NULL; -static struct pci_dev *pnp_avm __initdata = NULL; +static struct pnp_card *card_avm __initdata = NULL; +static struct pnp_dev *pnp_avm __initdata = NULL; #endif int __init @@ -670,8 +611,6 @@ strcpy(tmp, avm_pci_rev); printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_FRITZPCI) - return (0); if (card->para[1]) { /* old manual method */ cs->hw.avm.cfg_reg = card->para[1]; @@ -680,32 +619,36 @@ } else { #ifdef __ISAPNP__ if (isapnp_present()) { - struct pci_bus *ba; - if ((ba = isapnp_find_card( + struct pnp_card *ba; + if ((ba = pnp_find_card( ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), bus_avm))) { - bus_avm = ba; + ISAPNP_FUNCTION(0x0900), card_avm))) { + card_avm = ba; pnp_avm = NULL; - if ((pnp_avm = isapnp_find_dev(bus_avm, + if ((pnp_avm = pnp_find_dev(card_avm, ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), pnp_avm))) { - pnp_avm->prepare(pnp_avm); - pnp_avm->deactivate(pnp_avm); - pnp_avm->activate(pnp_avm); - cs->hw.avm.cfg_reg = - pnp_avm->resource[0].start; - cs->irq = - pnp_avm->irq_resource[0].start; - if (!cs->irq) { + if (pnp_device_attach(pnp_avm) < 0) { + printk(KERN_ERR "FritzPnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pnp_avm, NULL) < 0) { + printk(KERN_ERR "FritzPnP: activate failed\n"); + pnp_device_detach(pnp_avm); + return 0; + } + if (!pnp_irq_valid(pnp_avm, 0)) { printk(KERN_ERR "FritzPnP:No IRQ\n"); - pnp_avm->deactivate(pnp_avm); + pnp_device_detach(pnp_avm); return(0); } - if (!cs->hw.avm.cfg_reg) { + if (!pnp_port_valid(pnp_avm, 0)) { printk(KERN_ERR "FritzPnP:No IO address\n"); - pnp_avm->deactivate(pnp_avm); + pnp_device_detach(pnp_avm); return(0); } + cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0); + cs->irq = pnp_irq(pnp_avm, 0); cs->subtyp = AVM_FRITZ_PNP; goto ready; } @@ -715,10 +658,6 @@ } #endif #if CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "FritzPCI: no PCI bus present\n"); - return(0); - } if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { cs->irq = dev_avm->irq; @@ -739,22 +678,14 @@ return(0); } cs->irq_flags |= SA_SHIRQ; -#else - printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); - return (0); #endif /* CONFIG_PCI */ } ready: cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; - if (!request_region((cs->hw.avm.cfg_reg), 32, (cs->subtyp == AVM_FRITZ_PCI) - ? "avm PCI" : "avm PnP")) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.avm.cfg_reg, - cs->hw.avm.cfg_reg + 31); - return (0); - } + if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, + cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP")) + goto err; + switch (cs->subtyp) { case AVM_FRITZ_PCI: val = inl(cs->hw.avm.cfg_reg); @@ -766,17 +697,19 @@ val = inb(cs->hw.avm.cfg_reg); ver = inb(cs->hw.avm.cfg_reg + 1); printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); - reset_avmpcipnp(cs); + avm_pcipnp_reset(cs); break; } printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n", (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP", cs->irq, cs->hw.avm.cfg_reg); - cs->dc_hw_ops = &isac_ops; + cs->bc_hw_ops = &hdlc_hw_ops; cs->bc_l1_ops = &hdlc_l1_ops; - cs->cardmsg = &AVM_card_msg; - cs->irq_func = &avm_pcipnp_interrupt; - ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); - return (1); + cs->card_ops = &avm_pci_ops; + isac_setup(cs, &isac_ops); + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c --- a/drivers/isdn/hisax/bkm_a4t.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/bkm_a4t.c Mon Jan 13 10:18:05 2003 @@ -174,89 +174,81 @@ spin_unlock(&cs->lock); } -void -release_io_bkm(struct IsdnCardState *cs) +static void +enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) { - if (cs->hw.ax.base) { - iounmap((void *) cs->hw.ax.base); - cs->hw.ax.base = 0; - } + I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if (bEnable) + pI20_Regs->i20IntCtrl |= (intISDN | intPCI); + else + /* CAUTION: This disables the video capture driver too */ + pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); } static void -enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) +reset_bkm(struct IsdnCardState *cs) { - if (cs->typ == ISDN_CTYPE_BKM_A4T) { - I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - if (bEnable) - pI20_Regs->i20IntCtrl |= (intISDN | intPCI); - else - /* CAUTION: This disables the video capture driver too */ - pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); - } + I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + /* Issue the I20 soft reset */ + pI20_Regs->i20SysControl = 0xFF; /* all in */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10 * HZ) / 1000); + /* Remove the soft reset */ + pI20_Regs->i20SysControl = sysRESET | 0xFF; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10 * HZ) / 1000); + /* Set our configuration */ + pI20_Regs->i20SysControl = sysRESET | sysCFG; + /* Issue ISDN reset */ + pI20_Regs->i20GuestControl = guestWAIT_CFG | + g_A4T_JADE_RES | + g_A4T_ISAR_RES | + g_A4T_ISAC_RES | + g_A4T_JADE_BOOTR | + g_A4T_ISAR_BOOTR; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10 * HZ) / 1000); + + /* Remove RESET state from ISDN */ + pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | + g_A4T_JADE_RES | + g_A4T_ISAR_RES); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10 * HZ) / 1000); } static void -reset_bkm(struct IsdnCardState *cs) +bkm_a4t_init(struct IsdnCardState *cs) { - if (cs->typ == ISDN_CTYPE_BKM_A4T) { - I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - /* Issue the I20 soft reset */ - pI20_Regs->i20SysControl = 0xFF; /* all in */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - /* Remove the soft reset */ - pI20_Regs->i20SysControl = sysRESET | 0xFF; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - /* Set our configuration */ - pI20_Regs->i20SysControl = sysRESET | sysCFG; - /* Issue ISDN reset */ - pI20_Regs->i20GuestControl = guestWAIT_CFG | - g_A4T_JADE_RES | - g_A4T_ISAR_RES | - g_A4T_ISAC_RES | - g_A4T_JADE_BOOTR | - g_A4T_ISAR_BOOTR; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - - /* Remove RESET state from ISDN */ - pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | - g_A4T_JADE_RES | - g_A4T_ISAR_RES); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - } + initisac(cs); + initjade(cs); + /* Enable ints */ + enable_bkm_int(cs, 1); } static int -BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +bkm_a4t_reset(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - /* Disable ints */ - enable_bkm_int(cs, 0); - reset_bkm(cs); - return (0); - case CARD_RELEASE: - /* Sanity */ - enable_bkm_int(cs, 0); - reset_bkm(cs); - release_io_bkm(cs); - return (0); - case CARD_INIT: - initisac(cs); - initjade(cs); - /* Enable ints */ - enable_bkm_int(cs, 1); - return (0); - case CARD_TEST: - return (0); - } - return (0); + /* Disable ints */ + enable_bkm_int(cs, 0); + reset_bkm(cs); + return 0; } +static void +bkm_a4t_release(struct IsdnCardState *cs) +{ + reset_bkm(cs); + hisax_release_resources(cs); +} + +static struct card_ops bkm_a4t_ops = { + .init = bkm_a4t_init, + .reset = bkm_a4t_reset, + .release = bkm_a4t_release, + .irq_func = bkm_interrupt, +}; + static struct pci_dev *dev_a4t __initdata = NULL; int __init @@ -266,21 +258,9 @@ char tmp[64]; u_int pci_memaddr = 0, found = 0; I20_REGISTER_FILE *pI20_Regs; -#if CONFIG_PCI -#endif strcpy(tmp, bkm_a4t_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ == ISDN_CTYPE_BKM_A4T) { - cs->subtyp = BKM_A4T; - } else - return (0); - -#if CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); - return (0); - } while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { u16 sub_sys; @@ -305,40 +285,32 @@ printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); return (0); } - if (!pci_memaddr) { + cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T"); + if (!cs->hw.ax.base) { printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); return (0); } - cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096); + /* Check suspecious address */ pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n", CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096); - iounmap((void *) cs->hw.ax.base); - cs->hw.ax.base = 0; + hisax_release_resources(cs); return (0); } cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; cs->hw.ax.isac_ale = GCS_1; cs->hw.ax.jade_ale = GCS_3; -#else - printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]); - printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]); - return (0); -#endif /* CONFIG_PCI */ + printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n", CardType[card->typ], cs->hw.ax.base, cs->irq); reset_bkm(cs); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &jade_ops; - cs->cardmsg = &BKM_card_msg; - cs->irq_func = &bkm_interrupt; cs->irq_flags |= SA_SHIRQ; - ISACVersion(cs, "Telekom A4T:"); - /* Jade version */ - JadeVersion(cs, "Telekom A4T:"); - return (1); + cs->card_ops = &bkm_a4t_ops; + isac_setup(cs, &isac_ops); + jade_setup(cs, &jade_ops); + return 1; } diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c --- a/drivers/isdn/hisax/bkm_a8.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/bkm_a8.c Mon Jan 13 10:18:07 2003 @@ -20,8 +20,6 @@ #include #include "bkm_ax.h" -#if CONFIG_PCI - #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ extern const char *CardType[]; @@ -42,7 +40,7 @@ #define wordin(addr) inw(addr) static inline u8 -readreg(struct IsdnCardState *cs, u8 off) +ipac_read(struct IsdnCardState *cs, u8 off) { u8 ret; unsigned long flags; @@ -51,13 +49,14 @@ wordout(cs->hw.ax.base, off); ret = wordin(cs->hw.ax.data_adr) & 0xFF; spin_unlock_irqrestore(&bkm_a8_lock, flags); - return (ret); + return ret; } static inline void -writereg(struct IsdnCardState *cs, u8 off, u8 data) +ipac_write(struct IsdnCardState *cs, u8 off, u8 data) { unsigned long flags; + spin_lock_irqsave(&bkm_a8_lock, flags); wordout(cs->hw.ax.base, off); wordout(cs->hw.ax.data_adr, data); @@ -65,7 +64,7 @@ } static inline void -readfifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) +ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) { int i; @@ -75,7 +74,7 @@ } static inline void -writefifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) +ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) { int i; @@ -84,144 +83,26 @@ wordout(cs->hw.ax.data_adr, data[i]); } -static u8 -ipac_dc_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, offset | 0x80); -} - -static void -ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - writereg(cs, offset | 0x80, value); -} - -static void -ipac_dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - readfifo(cs, 0x80, data, size); -} - -static void -ipac_dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - writefifo(cs, 0x80, data, size); -} - -static struct dc_hw_ops ipac_dc_ops = { - .read_reg = ipac_dc_read, - .write_reg = ipac_dc_write, - .read_fifo = ipac_dc_read_fifo, - .write_fifo = ipac_dc_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) -{ - return readreg(cs, offset + (hscx ? 0x40 : 0)); -} - -static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) -{ - writereg(cs, offset + (hscx ? 0x40 : 0), value); -} - -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs, hscx ? 0x40 : 0, data, size); -} - -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs, hscx ? 0x40 : 0, data, size); -} - -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +/* This will generate ipac_dc_ops and ipac_bc_ops using the functions + * above */ +BUILD_IPAC_OPS(ipac); + /* Set the specific ipac to active */ static void set_ipac_active(struct IsdnCardState *cs, u_int active) { /* set irq mask */ - writereg(cs, IPAC_MASK, active ? 0xc0 : 0xff); -} - -static void -bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 ista, val, icnt = 5; - - spin_lock(&cs->lock); - ista = readreg(cs, IPAC_ISTA); - if (!(ista & 0x3f)) /* not this IPAC */ - goto unlock; - Start_IPAC: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = hscx_read(cs, 1, HSCX_ISTA); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) { - hscx_int_main(cs, val); - } - } - if (ista & 0x20) { - val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe; - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = readreg(cs, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPAC; - } - if (!icnt) - printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n", - CardType[cs->typ], - sct_quadro_subtypes[cs->subtyp]); - writereg(cs, IPAC_MASK, 0xFF); - writereg(cs, IPAC_MASK, 0xC0); - unlock: - spin_unlock(&cs->lock); -} - - -void -release_io_sct_quadro(struct IsdnCardState *cs) -{ - release_region(cs->hw.ax.base & 0xffffffc0, 128); - if (cs->subtyp == SCT_1) - release_region(cs->hw.ax.plx_adr, 64); + ipac_write(cs, IPAC_MASK, active ? 0xc0 : 0xff); } static void enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) { - if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { - if (bEnable) - wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41)); - else - wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41)); - } + if (bEnable) + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41)); + else + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41)); } static void @@ -238,58 +119,49 @@ } } +static void +bkm_a8_init(struct IsdnCardState *cs) +{ + cs->debug |= L1_DEB_IPAC; + set_ipac_active(cs, 1); + ipac_init(cs); + /* Enable ints */ + enable_bkm_int(cs, 1); +} + static int -BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +bkm_a8_reset(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - /* Disable ints */ - set_ipac_active(cs, 0); - enable_bkm_int(cs, 0); - reset_bkm(cs); - return (0); - case CARD_RELEASE: - /* Sanity */ - set_ipac_active(cs, 0); - enable_bkm_int(cs, 0); - release_io_sct_quadro(cs); - return (0); - case CARD_INIT: - cs->debug |= L1_DEB_IPAC; - set_ipac_active(cs, 1); - inithscxisac(cs); - /* Enable ints */ - enable_bkm_int(cs, 1); - return (0); - case CARD_TEST: - return (0); - } - return (0); + /* Disable ints */ + set_ipac_active(cs, 0); + enable_bkm_int(cs, 0); + reset_bkm(cs); + return 0; } -int __init -sct_alloc_io(u_int adr, u_int len) +static void +bkm_a8_release(struct IsdnCardState *cs) { - if (!request_region(adr, len, "scitel")) { - printk(KERN_WARNING - "HiSax: Scitel port %#x-%#x already in use\n", - adr, adr + len); - return (1); - } - return(0); + set_ipac_active(cs, 0); + enable_bkm_int(cs, 0); + hisax_release_resources(cs); } +static struct card_ops bkm_a8_ops = { + .init = bkm_a8_init, + .reset = bkm_a8_reset, + .release = bkm_a8_release, + .irq_func = ipac_irq, +}; + static struct pci_dev *dev_a8 __initdata = NULL; static u16 sub_vendor_id __initdata = 0; static u16 sub_sys_id __initdata = 0; static u8 pci_irq __initdata = 0; -#endif /* CONFIG_PCI */ - int __init setup_sct_quadro(struct IsdnCard *card) { -#if CONFIG_PCI struct IsdnCardState *cs = card->cs; char tmp[64]; u8 pci_rev_id; @@ -298,11 +170,6 @@ strcpy(tmp, sct_quadro_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { - cs->subtyp = SCT_1; /* Preset */ - } else - return (0); - /* Identify subtype by para[0] */ if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4) cs->subtyp = card->para[0]; @@ -315,10 +182,6 @@ (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) return (0); if (cs->subtyp == SCT_1) { - if (!pci_present()) { - printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); - return (0); - } while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, dev_a8))) { @@ -390,31 +253,31 @@ cs->hw.ax.plx_adr = pci_ioaddr1; /* Enter all ipac_base addresses */ switch(cs->subtyp) { - case 1: - cs->hw.ax.base = pci_ioaddr5 + 0x00; - if (sct_alloc_io(pci_ioaddr1, 128)) - return(0); - if (sct_alloc_io(pci_ioaddr5, 64)) - return(0); - break; - case 2: - cs->hw.ax.base = pci_ioaddr4 + 0x08; - if (sct_alloc_io(pci_ioaddr4, 64)) - return(0); - break; - case 3: - cs->hw.ax.base = pci_ioaddr3 + 0x10; - if (sct_alloc_io(pci_ioaddr3, 64)) - return(0); - break; - case 4: - cs->hw.ax.base = pci_ioaddr2 + 0x20; - if (sct_alloc_io(pci_ioaddr2, 64)) - return(0); - break; + case 1: + cs->hw.ax.base = pci_ioaddr5 + 0x00; + if (!request_io(&cs->rs, pci_ioaddr1, 128, "scitel")) + goto err; + if (!request_io(&cs->rs, pci_ioaddr5, 64, "scitel")) + goto err; + break; + case 2: + cs->hw.ax.base = pci_ioaddr4 + 0x08; + if (!request_io(&cs->rs, pci_ioaddr4, 64, "scitel")) + goto err; + break; + case 3: + cs->hw.ax.base = pci_ioaddr3 + 0x10; + if (!request_io(&cs->rs, pci_ioaddr3, 64, "scitel")) + goto err; + break; + case 4: + cs->hw.ax.base = pci_ioaddr2 + 0x20; + if (!request_io(&cs->rs, pci_ioaddr2, 64, "scitel")) + goto err; + break; } cs->hw.ax.data_adr = cs->hw.ax.base + 4; - writereg(cs, IPAC_MASK, 0xFF); + ipac_write(cs, IPAC_MASK, 0xFF); printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n", CardType[card->typ], @@ -424,19 +287,12 @@ cs->hw.ax.data_adr, cs->irq); - test_and_set_bit(HW_IPAC, &cs->HW_Flags); - - cs->dc_hw_ops = &ipac_dc_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &BKM_card_msg; - cs->irq_func = &bkm_interrupt_ipac; - - printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n", - CardType[card->typ], - sct_quadro_subtypes[cs->subtyp], - readreg(cs, IPAC_ID)); - return (1); -#else - printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n"); -#endif /* CONFIG_PCI */ + cs->card_ops = &bkm_a8_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c --- a/drivers/isdn/hisax/callc.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/callc.c Mon Jan 13 10:18:06 2003 @@ -205,13 +205,49 @@ } static inline void +mdl_info_setup(struct Channel *chanp) +{ + if (chanp->chan) + chanp->cs->status |= 0x0200; + else + chanp->cs->status |= 0x0100; + + if (chanp->cs->card_ops->led_handler) + chanp->cs->card_ops->led_handler(chanp->cs); +} + +static inline void +mdl_info_connect(struct Channel *chanp) +{ + if (chanp->chan) + chanp->cs->status |= 0x2000; + else + chanp->cs->status |= 0x1000; + + if (chanp->cs->card_ops->led_handler) + chanp->cs->card_ops->led_handler(chanp->cs); +} + +static inline void +mdl_info_release(struct Channel *chanp) +{ + if (chanp->chan) + chanp->cs->status &= ~0x2200; + else + chanp->cs->status &= ~0x1100; + + if (chanp->cs->card_ops->led_handler) + chanp->cs->card_ops->led_handler(chanp->cs); +} + +static void lli_close(struct FsmInst *fi) { struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_NULL); chanp->Flags = 0; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + mdl_info_release(chanp); } static void @@ -223,7 +259,8 @@ if (!chanp->leased) return; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + + mdl_info_setup(chanp); FsmChangeState(fi, ST_IN_WAIT_LL); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_ICALL_LEASED"); @@ -240,7 +277,7 @@ if (chanp->debug & 1) link_debug(chanp, 1, "statcallb ret=%d", ret); if (!ret) { - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + mdl_info_release(chanp); FsmChangeState(fi, ST_NULL); } } @@ -270,7 +307,7 @@ FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + mdl_info_setup(chanp); if (chanp->leased) { lli_init_bchan_out(fi, event, arg); } else { @@ -288,7 +325,7 @@ FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + mdl_info_setup(chanp); if (chanp->leased) { lli_init_bchan_out(fi, event, arg); } else { @@ -316,7 +353,7 @@ ic.command = ISDN_STAT_BCONN; ic.arg = chanp->chan; chanp->cs->iif.statcallb(&ic); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan); + mdl_info_connect(chanp); } @@ -333,7 +370,7 @@ isdn_ctrl ic; int ret; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + mdl_info_setup(chanp); /* * Report incoming calls only once to linklevel, use CallFlags * which is set to 3 with each broadcast message in isdnl1.c @@ -381,13 +418,13 @@ case 0: /* OK, nobody likes this call */ default: /* statcallb problems */ L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + mdl_info_release(chanp); FsmChangeState(fi, ST_NULL); break; } } else { L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + mdl_info_release(chanp); } } @@ -730,7 +767,7 @@ chanp->cs->iif.statcallb(&ic); HL_LL(chanp, ISDN_STAT_DHUP); chanp->Flags = 0; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + mdl_info_release(chanp); } static void @@ -853,10 +890,11 @@ static void release_b_st(struct Channel *chanp) { + struct IsdnCardState *cs = chanp->cs; struct PStack *st = chanp->b_st; if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) { - chanp->bcs->BC_Close(chanp->bcs); + cs->bc_l1_ops->close(chanp->bcs); switch (chanp->l2_active_protocol) { case (ISDN_PROTO_L2_X75I): releasestack_isdnl2(st); @@ -1297,7 +1335,7 @@ break; } chanp->bcs->conmsg = NULL; - if (chanp->bcs->BC_SetStack(st, chanp->bcs)) + if (cs->bc_l1_ops->open(st, chanp->bcs)) return (-1); st->l2.flag = 0; test_and_set_bit(FLG_LAPB, &st->l2.flag); @@ -1457,12 +1495,8 @@ void lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) { - if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) || - (cs->typ == ISDN_CTYPE_ELSA_PCI)) { - if (cs->hw.elsa.MFlag) { - cs->cardmsg(cs, CARD_AUX_IND, cm->para); - } - } + if (cs->card_ops->aux_ind) + cs->card_ops->aux_ind(cs, cm->para); } diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c --- a/drivers/isdn/hisax/config.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/config.c Mon Jan 13 10:18:07 2003 @@ -24,6 +24,7 @@ #include #include #include +#include "isdnl1.h" #define HISAX_STATUS_BUFSIZE 4096 #define INCLUDE_INLINE_FUNCS @@ -825,9 +826,9 @@ { struct IsdnCardState *csta = cards[cardnr].cs; - if (csta->bcs->BC_Close != NULL) { - csta->bcs->BC_Close(csta->bcs + 1); - csta->bcs->BC_Close(csta->bcs); + if (csta->bc_l1_ops->close) { + csta->bc_l1_ops->close(csta->bcs + 1); + csta->bc_l1_ops->close(csta->bcs); } skb_queue_purge(&csta->rq); @@ -840,11 +841,11 @@ dev_kfree_skb(csta->tx_skb); csta->tx_skb = NULL; } - if (csta->DC_Close != NULL) { - csta->DC_Close(csta); - } - if (csta->cardmsg) - csta->cardmsg(csta, CARD_RELEASE, NULL); + if (csta->dc_l1_ops->close) + csta->dc_l1_ops->close(csta); + + if (csta->card_ops->release) + csta->card_ops->release(csta); if (csta->dbusytimer.function != NULL) // FIXME? del_timer(&csta->dbusytimer); ll_unload(csta); @@ -854,19 +855,18 @@ { int irq_cnt, cnt = 3; - if (!cs->irq) - return cs->cardmsg(cs, CARD_INIT, NULL); + cs->card_ops->init(cs); irq_cnt = kstat_irqs(cs->irq); printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, irq_cnt); - if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) { + if (request_irq(cs->irq, cs->card_ops->irq_func, cs->irq_flags, "HiSax", cs)) { printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", cs->irq); return 1; } while (cnt) { - cs->cardmsg(cs, CARD_INIT, NULL); + cs->card_ops->init(cs); set_current_state(TASK_UNINTERRUPTIBLE); /* Timeout 10ms */ schedule_timeout((10 * HZ) / 1000); @@ -880,11 +880,13 @@ free_irq(cs->irq, cs); return 2; } else { - cs->cardmsg(cs, CARD_RESET, NULL); + if (cs->card_ops->reset) + cs->card_ops->reset(cs); cnt--; } } else { - cs->cardmsg(cs, CARD_TEST, NULL); + if (cs->card_ops->test) + cs->card_ops->test(cs); return 0; } } @@ -943,6 +945,7 @@ cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; cs->typ = card->typ; spin_lock_init(&cs->lock); + resources_init(&cs->rs); SET_MODULE_OWNER(&cs->iif); strcpy(cs->iif.id, id); cs->iif.channels = 2; @@ -1741,12 +1744,15 @@ static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg); static void hisax_d_l2l1(struct PStack *st, int pr, void *arg); static void hisax_b_l2l1(struct PStack *st, int pr, void *arg); -static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg); static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs); static void hisax_bc_close(struct BCState *bcs); static void hisax_bh(void *data); static void EChannel_proc_rcv(struct hisax_d_if *d_if); +static struct dc_l1_ops hisax_l1_ops = { + .bh_func = hisax_bh, +}; + int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], char *name, int protocol) { @@ -1775,14 +1781,13 @@ cs = cards[i].cs; hisax_d_if->cs = cs; cs->hw.hisax_d_if = hisax_d_if; - cs->cardmsg = hisax_cardmsg; cs->iif.owner = hisax_d_if->owner; // FIXME should be done before registering - INIT_WORK(&cs->work, hisax_bh, cs); + dc_l1_init(cs, &hisax_l1_ops); cs->channel[0].d_st->l1.l2l1 = hisax_d_l2l1; - for (i = 0; i < 2; i++) { - cs->bcs[i].BC_SetStack = hisax_bc_setstack; - cs->bcs[i].BC_Close = hisax_bc_close; + cs->bc_l1_ops->open = hisax_bc_setstack; + cs->bc_l1_ops->close = hisax_bc_close; + for (i = 0; i < 2; i++) { b_if[i]->ifc.l1l2 = hisax_b_l1l2; hisax_d_if->b_if[i] = b_if[i]; @@ -1954,11 +1959,6 @@ } } -static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg) -{ - return 0; -} - static void hisax_b_l2l1(struct PStack *st, int pr, void *arg) { struct BCState *bcs = st->l1.bcs; @@ -2047,6 +2047,100 @@ } dev_kfree_skb_any(skb); } +} + +void +resources_init(struct resources *rs) +{ + INIT_LIST_HEAD(&rs->res_head); +} + +void +resources_release(struct resources *rs) +{ + struct res *r; + + list_for_each_entry(r, &rs->res_head, node) { + if (r->flags & IORESOURCE_IO) { + release_region(r->start, r->end - r->start + 1); + } + if (r->flags & IORESOURCE_MEM) { + iounmap(r->r_u.ioremap_addr); + release_mem_region(r->start, r->end - r->start + 1); + } + } +} + +unsigned long +request_io(struct resources *rs, unsigned long start, int len, + const char *name) +{ + struct res *r; + + r = kmalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); + goto err; + } + if (!request_region(start, len, name)) { + printk(KERN_WARNING "%s: IO %#lx-%#lx already in use\n", + __FUNCTION__, start, start + len - 1); + goto err_free; + } + r->flags = IORESOURCE_IO; + r->start = start; + r->end = start + len - 1; + r->name = name; + list_add_tail(&r->node, &rs->res_head); + + return r->start; + + err_free: + kfree(r); + err: + return 0; +} + +void * +request_mmio(struct resources *rs, unsigned long start, int len, + const char *name) +{ + struct res *r; + + r = kmalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); + goto err; + } + if (!request_mem_region(start, len, name)) { + printk(KERN_WARNING "%s: MMIO %#lx-%#lx already in use\n", + __FUNCTION__, start, start + len - 1); + goto err_free; + } + r->flags = IORESOURCE_MEM; + r->start = start; + r->end = start + len - 1; + r->name = name; + r->r_u.ioremap_addr = ioremap(start, len); + if (!r->r_u.ioremap_addr) + goto err_release; + + list_add_tail(&r->node, &rs->res_head); + + return r->r_u.ioremap_addr; + + err_release: + release_mem_region(r->start, r->end - r->start + 1); + err_free: + kfree(r); + err: + return 0; +} + +void +hisax_resources_release(struct IsdnCardState *cs) +{ + resources_release(&cs->rs); } #include diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c --- a/drivers/isdn/hisax/diva.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/diva.c Mon Jan 13 10:18:07 2003 @@ -164,37 +164,6 @@ }; static u8 -ipac_dc_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80); -} - -static void -ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value); -} - -static void -ipac_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size) -{ - readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); -} - -static void -ipac_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size) -{ - writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); -} - -static struct dc_hw_ops ipac_dc_ops = { - .read_reg = ipac_dc_read, - .write_reg = ipac_dc_write, - .read_fifo = ipac_dc_read_fifo, - .write_fifo = ipac_dc_write_fifo, -}; - -static u8 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) { return readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, @@ -227,55 +196,65 @@ .write_fifo = hscx_write_fifo, }; -static u8 -mem_ipac_dc_read(struct IsdnCardState *cs, u8 offset) +static inline u8 +ipac_read(struct IsdnCardState *cs, u8 offset) { - return memreadreg(cs->hw.diva.cfg_reg, offset+0x80); + return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset); } -static void -mem_ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) +static inline void +ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) { - memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value); } -static void -mem_ipac_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +static inline void +ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) { - while(size--) - *data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80); + readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size); } -static void -mem_ipac_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +static inline void +ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) { - while(size--) - memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++); + writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size); } -static struct dc_hw_ops mem_ipac_dc_ops = { - .read_reg = mem_ipac_dc_read, - .write_reg = mem_ipac_dc_write, - .read_fifo = mem_ipac_dc_read_fifo, - .write_fifo = mem_ipac_dc_write_fifo, -}; +/* This will generate ipac_dc_ops and ipac_bc_ops using the functions + * above */ -static u8 -mem_hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +BUILD_IPAC_OPS(ipac); + +static inline u8 +mem_ipac_read(struct IsdnCardState *cs, u8 offset) { - return memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0)); + return memreadreg(cs->hw.diva.cfg_reg, offset); } -static void -mem_hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +static inline void +mem_ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) { - memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value); + memwritereg(cs->hw.diva.cfg_reg, offset, value); } -static struct bc_hw_ops mem_hscx_ops = { - .read_reg = mem_hscx_read, - .write_reg = mem_hscx_write, -}; +static inline void +mem_ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +{ + while(size--) + *data++ = memreadreg(cs->hw.diva.cfg_reg, offset); +} + +static inline void +mem_ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +{ + while(size--) + memwritereg(cs->hw.diva.cfg_reg, offset, *data++); +} + +/* This will generate mem_ipac_dc_ops and mem_ipac_bc_ops using the functions + * above */ + +BUILD_IPAC_OPS(mem_ipac); /* IO-Functions for IPACX type cards */ static u8 @@ -325,457 +304,151 @@ (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value); } +static void +ipacx_bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len) +{ + int i; + + for (i = 0; i < len ; i++) + *data++ = ipacx_bc_read(cs, hscx, IPACX_RFIFOB); +} + static struct bc_hw_ops ipacx_bc_ops = { .read_reg = ipacx_bc_read, .write_reg = ipacx_bc_write, + .read_fifo = ipacx_bc_read_fifo, }; static void diva_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; + u8 sval; int cnt=5; - spin_lock(&cs->lock); while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) { - val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40); - if (val) - hscx_int_main(cs, val); - val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA); - if (val) - isac_interrupt(cs, val); - cnt--; + hscxisac_irq(intno, dev_id, regs); } if (!cnt) printk(KERN_WARNING "Diva: IRQ LOOP\n"); - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF); - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0); - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0); - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0); - spin_unlock(&cs->lock); } static void -diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs) +diva_ipac_pci_irq(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 ista,val; - int icnt=5; - - if (!cs) { - printk(KERN_WARNING "Diva: Spurious interrupt!\n"); - return; - } - ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); -Start_IPACISA: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) - hscx_int_main(cs, val); - } - if (ista & 0x20) { - val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80); - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPACISA; - } - if (!icnt) - printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n"); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0); -} - -static inline void -MemwaitforCEC(struct IsdnCardState *cs, int hscx) -{ - int to = 50; - - while ((mem_hscx_read(cs, hscx, HSCX_STAR) & 0x04) && to) { - udelay(1); - to--; - } - if (!to) - printk(KERN_WARNING "HiSax: waitforCEC timeout\n"); -} - - -static inline void -MemwaitforXFW(struct IsdnCardState *cs, int hscx) -{ - int to = 50; - - while ((!(mem_hscx_read(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { - udelay(1); - to--; - } - if (!to) - printk(KERN_WARNING "HiSax: waitforXFW timeout\n"); -} + u8 val; -static inline void -MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u8 data) -{ - unsigned long flags; + val = readb(cs->hw.diva.pci_cfg); + if (!(val & PITA_INT0_STATUS)) + return; /* other shared IRQ */ + writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); /* Reset pending INT0 */ - spin_lock_irqsave(&diva_lock, flags); - MemwaitforCEC(cs, hscx); - mem_hscx_write(cs, hscx, HSCX_CMDR, data); - spin_unlock_irqrestore(&diva_lock, flags); + ipac_irq(intno, dev_id, regs); } static void -Memhscx_empty_fifo(struct BCState *bcs, int count) +diva_ipacx_pci_irq(int intno, void *dev_id, struct pt_regs *regs) { - u8 *ptr; - struct IsdnCardState *cs = bcs->cs; - unsigned long flags; - int cnt; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "hscx_empty_fifo"); + struct IsdnCardState *cs = dev_id; + u8 val; - if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "hscx_empty_fifo: incoming packet too large"); - MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); - bcs->hw.hscx.rcvidx = 0; - return; - } - spin_lock_irqsave(&diva_lock, flags); - ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; - cnt = count; - while (cnt--) - *ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0); - MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); - ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; - bcs->hw.hscx.rcvidx += count; - spin_unlock_irqrestore(&diva_lock, flags); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "hscx_empty_fifo %c cnt %d", - bcs->hw.hscx.hscx ? 'B' : 'A', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } + val = readb(cs->hw.diva.pci_cfg); + if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ + interrupt_ipacx(cs); // handler for chip + writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); // Reset PLX interrupt } static void -Memhscx_fill_fifo(struct BCState *bcs) +diva_release(struct IsdnCardState *cs) { - struct IsdnCardState *cs = bcs->cs; - int more, count; - int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; - unsigned char *p; - - p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); - if (!p) - return; - - MemwaitforXFW(cs, bcs->hw.hscx.hscx); - while (count--) - memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0, - *p++); - MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); -} - -static struct bc_l1_ops mem_hscx_l1_ops = { - .fill_fifo = Memhscx_fill_fifo, -}; + del_timer(&cs->hw.diva.tl); + if (cs->hw.diva.cfg_reg) + byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ -static inline void -Memhscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) -{ - u8 r; - struct BCState *bcs = cs->bcs + hscx; - struct sk_buff *skb; - int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; - int count; - - if (!test_bit(BC_FLG_INIT, &bcs->Flag)) - return; - - if (val & 0x80) { /* RME */ - r = mem_hscx_read(cs, hscx, HSCX_RSTA); - if ((r & 0xf0) != 0xa0) { - if (!(r & 0x80)) - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX invalid frame"); - if ((r & 0x40) && bcs->mode) - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX RDO mode=%d", - bcs->mode); - if (!(r & 0x20)) - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX CRC error"); - MemWriteHSCXCMDR(cs, hscx, 0x80); - } else { - count = mem_hscx_read(cs, hscx, HSCX_RBCL) & ( - test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); - if (count == 0) - count = fifo_size; - Memhscx_empty_fifo(bcs, count); - if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { - if (cs->debug & L1_DEB_HSCX_FIFO) - debugl1(cs, "HX Frame %d", count); - if (!(skb = dev_alloc_skb(count))) - printk(KERN_WARNING "HSCX: receive out of memory\n"); - else { - memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); - skb_queue_tail(&bcs->rqueue, skb); - } - } - } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); - } - if (val & 0x40) { /* RPF */ - Memhscx_empty_fifo(bcs, fifo_size); - if (bcs->mode == L1_MODE_TRANS) { - /* receive audio data */ - if (!(skb = dev_alloc_skb(fifo_size))) - printk(KERN_WARNING "HiSax: receive out of memory\n"); - else { - memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); - skb_queue_tail(&bcs->rqueue, skb); - } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); - } - } - if (val & 0x10) { - xmit_xpr_b(bcs);/* XPR */ - } + hisax_release_resources(cs); } static void -Memhscx_reset_xmit(struct BCState *bcs) +diva_ipac_pci_release(struct IsdnCardState *cs) { - MemWriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01); + writel(0, cs->hw.diva.pci_cfg); /* disable INT0/1 */ + writel(2, cs->hw.diva.pci_cfg); /* reset pending INT0 */ + hisax_release_resources(cs); } -static inline void -Memhscx_int_main(struct IsdnCardState *cs, u8 val) -{ - - u8 exval; - struct BCState *bcs; - - if (val & 0x01) { // EXB - bcs = cs->bcs + 1; - exval = mem_hscx_read(cs, 1, HSCX_EXIR); - if (exval & 0x40) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX B EXIR %x", exval); - xmit_xdu_b(bcs, Memhscx_reset_xmit); - } - } - if (val & 0xf8) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX B interrupt %x", val); - Memhscx_interrupt(cs, val, 1); - } - if (val & 0x02) { // EXA - bcs = cs->bcs; - exval = mem_hscx_read(cs, 0, HSCX_EXIR); - if (exval & 0x40) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX A EXIR %x", exval); - xmit_xdu_b(bcs, Memhscx_reset_xmit); - } - } - if (val & 0x04) { // ICA - exval = mem_hscx_read(cs, 0, HSCX_ISTA); - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX A interrupt %x", exval); - Memhscx_interrupt(cs, exval, 0); - } -} - -static void -diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs) +static int +diva_ipac_isa_reset(struct IsdnCardState *cs) { - struct IsdnCardState *cs = dev_id; - u8 ista,val; - int icnt=5; - u8 *cfg; - - if (!cs) { - printk(KERN_WARNING "Diva: Spurious interrupt!\n"); - return; - } - cfg = (u8 *) cs->hw.diva.pci_cfg; - val = *cfg; - if (!(val & PITA_INT0_STATUS)) - return; /* other shared IRQ */ - *cfg = PITA_INT0_STATUS; /* Reset pending INT0 */ - ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); -Start_IPACPCI: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) - Memhscx_int_main(cs, val); - } - if (ista & 0x20) { - val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80); - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPACPCI; - } - if (!icnt) - printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n"); - memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF); - memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); + return 0; } -static void -diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs) +static int +diva_ipac_pci_reset(struct IsdnCardState *cs) { - struct IsdnCardState *cs = dev_id; - u8 val; - u8 *cfg; + unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG; - if (!cs) { - printk(KERN_WARNING "Diva: Spurious interrupt!\n"); - return; - } - cfg = (u8 *) cs->hw.diva.pci_cfg; - val = *cfg; - if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ - interrupt_ipacx(cs); // handler for chip - *cfg = PITA_INT0_STATUS; // Reset PLX interrupt + writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writel(PITA_PARA_MPX_MODE, misc_reg); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); + return 0; } -void -release_io_diva(struct IsdnCardState *cs) +static int +diva_ipacx_pci_reset(struct IsdnCardState *cs) { - int bytecnt; + unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG; - if ((cs->subtyp == DIVA_IPAC_PCI) || - (cs->subtyp == DIVA_IPACX_PCI) ) { - u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg; - - *cfg = 0; /* disable INT0/1 */ - *cfg = 2; /* reset pending INT0 */ - iounmap((void *)cs->hw.diva.cfg_reg); - iounmap((void *)cs->hw.diva.pci_cfg); - return; - } else if (cs->subtyp != DIVA_IPAC_ISA) { - del_timer(&cs->hw.diva.tl); - if (cs->hw.diva.cfg_reg) - byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ - } - if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) - bytecnt = 8; - else - bytecnt = 32; - if (cs->hw.diva.cfg_reg) { - release_region(cs->hw.diva.cfg_reg, bytecnt); - } + writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET, misc_reg); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + ipacx_dc_write(cs, IPACX_MASK, 0xff); // Interrupts off + return 0; } -static void -reset_diva(struct IsdnCardState *cs) +static int +diva_reset(struct IsdnCardState *cs) { - if (cs->subtyp == DIVA_IPAC_ISA) { - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); - } else if (cs->subtyp == DIVA_IPAC_PCI) { - unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + - PITA_MISC_REG); - *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - *ireg = PITA_PARA_MPX_MODE; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); - } else if (cs->subtyp == DIVA_IPACX_PCI) { - unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + - PITA_MISC_REG); - *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - ipacx_dc_write(cs, IPACX_MASK, 0xff); // Interrupts off - } else { /* DIVA 2.0 */ - cs->hw.diva.ctrl_reg = 0; /* Reset On */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - if (cs->subtyp == DIVA_ISA) - cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; - else { - /* Workaround PCI9060 */ - byteout(cs->hw.diva.pci_cfg + 0x69, 9); - cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; - } - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + /* DIVA 2.0 */ + cs->hw.diva.ctrl_reg = 0; /* Reset On */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + if (cs->subtyp == DIVA_ISA) { + cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; + } else { + /* Workaround PCI9060 */ + byteout(cs->hw.diva.pci_cfg + 0x69, 9); + cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; } + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + return 0; } -#define DIVA_ASSIGN 1 - static void diva_led_handler(struct IsdnCardState *cs) { int blink = 0; -// if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI)) - if ((cs->subtyp == DIVA_IPAC_ISA) || - (cs->subtyp == DIVA_IPAC_PCI) || - (cs->subtyp == DIVA_IPACX_PCI) ) - return; - del_timer(&cs->hw.diva.tl); - if (cs->hw.diva.status & DIVA_ASSIGN) + if (cs->status & 0x0001) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_A : DIVA_PCI_LED_A; else { @@ -783,10 +456,10 @@ DIVA_ISA_LED_A : DIVA_PCI_LED_A; blink = 250; } - if (cs->hw.diva.status & 0xf000) + if (cs->status & 0xf000) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; - else if (cs->hw.diva.status & 0x0f00) { + else if (cs->status & 0x0f00) { cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; blink = 500; @@ -795,75 +468,53 @@ DIVA_ISA_LED_B : DIVA_PCI_LED_B); byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - if (blink) { - init_timer(&cs->hw.diva.tl); - cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000); - add_timer(&cs->hw.diva.tl); - } + if (blink) + mod_timer(&cs->hw.diva.tl, jiffies + (blink * HZ) / 1000); } -static int -Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +diva_ipacx_pci_init(struct IsdnCardState *cs) { - u_int *ireg; + writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg); + init_ipacx(cs, 3); // init chip and enable interrupts +} - switch (mt) { - case CARD_RESET: - reset_diva(cs); - return(0); - case CARD_RELEASE: - release_io_diva(cs); - return(0); - case CARD_INIT: - if (cs->subtyp == DIVA_IPACX_PCI) { - ireg = (unsigned int *)cs->hw.diva.pci_cfg; - *ireg = PITA_INT0_ENABLE; - init_ipacx(cs, 3); // init chip and enable interrupts - return (0); - } - if (cs->subtyp == DIVA_IPAC_PCI) { - ireg = (unsigned int *)cs->hw.diva.pci_cfg; - *ireg = PITA_INT0_ENABLE; - } - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - case (MDL_REMOVE | REQUEST): - cs->hw.diva.status = 0; - break; - case (MDL_ASSIGN | REQUEST): - cs->hw.diva.status |= DIVA_ASSIGN; - break; - case MDL_INFO_SETUP: - if ((long)arg) - cs->hw.diva.status |= 0x0200; - else - cs->hw.diva.status |= 0x0100; - break; - case MDL_INFO_CONN: - if ((long)arg) - cs->hw.diva.status |= 0x2000; - else - cs->hw.diva.status |= 0x1000; - break; - case MDL_INFO_REL: - if ((long)arg) { - cs->hw.diva.status &= ~0x2000; - cs->hw.diva.status &= ~0x0200; - } else { - cs->hw.diva.status &= ~0x1000; - cs->hw.diva.status &= ~0x0100; - } - break; - } - if ((cs->subtyp != DIVA_IPAC_ISA) && - (cs->subtyp != DIVA_IPAC_PCI) && - (cs->subtyp != DIVA_IPACX_PCI) ) - diva_led_handler(cs); - return(0); +static void +diva_ipac_pci_init(struct IsdnCardState *cs) +{ + writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg); + ipac_init(cs); } +static struct card_ops diva_ops = { + .init = inithscxisac, + .reset = diva_reset, + .release = diva_release, + .led_handler = diva_led_handler, + .irq_func = diva_interrupt, +}; + +static struct card_ops diva_ipac_isa_ops = { + .init = ipac_init, + .reset = diva_ipac_isa_reset, + .release = hisax_release_resources, + .irq_func = ipac_irq, +}; + +static struct card_ops diva_ipac_pci_ops = { + .init = diva_ipac_pci_init, + .reset = diva_ipac_pci_reset, + .release = diva_ipac_pci_release, + .irq_func = diva_ipac_pci_irq, +}; + +static struct card_ops diva_ipacx_pci_ops = { + .init = diva_ipacx_pci_init, + .reset = diva_ipacx_pci_reset, + .release = diva_ipac_pci_release, + .irq_func = diva_ipacx_pci_irq, +}; + static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL; @@ -891,7 +542,7 @@ }; static struct isapnp_device_id *pdev = &diva_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif @@ -905,9 +556,6 @@ strcpy(tmp, Diva_revision); printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_DIEHLDIVA) - return(0); - cs->hw.diva.status = 0; if (card->para[1]) { cs->hw.diva.ctrl_reg = 0; cs->hw.diva.cfg_reg = card->para[1]; @@ -921,7 +569,6 @@ cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; - test_and_set_bit(HW_IPAC, &cs->HW_Flags); } else { cs->subtyp = DIVA_ISA; cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; @@ -934,31 +581,38 @@ } else { #ifdef __ISAPNP__ if (isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; while(pdev->card_vendor) { - if ((pb = isapnp_find_card(pdev->card_vendor, - pdev->card_device, pnp_c))) { + if ((pb = pnp_find_card(pdev->card_vendor, + pdev->card_device, + pnp_c))) { pnp_c = pb; pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - pdev->vendor, pdev->function, pd))) { + if ((pd = pnp_find_dev(pnp_c, + pdev->vendor, + pdev->function, + pd))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)pdev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = - pd->resource[0].start; - card->para[0] = - pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "Diva PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "Diva PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", - card->para[0], card->para[1]); - pd->deactivate(pd); + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); return(0); } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); cs->hw.diva.cfg_reg = card->para[1]; cs->irq = card->para[0]; if (pdev->function == ISAPNP_FUNCTION(0xA1)) { @@ -972,7 +626,6 @@ card->para[1] + DIVA_IPAC_ADR; cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; - test_and_set_bit(HW_IPAC, &cs->HW_Flags); } else { cs->subtyp = DIVA_ISA; cs->hw.diva.ctrl = @@ -1001,11 +654,6 @@ } #endif #if CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "Diva: no PCI bus present\n"); - return(0); - } - cs->subtyp = 0; if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { @@ -1027,10 +675,8 @@ return(0); cs->subtyp = DIVA_IPAC_PCI; cs->irq = dev_diva201->irq; - cs->hw.diva.pci_cfg = - (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); - cs->hw.diva.cfg_reg = - (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); + cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva"); + cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva"); } else { printk(KERN_WARNING "Diva: No PCI card found\n"); return(0); @@ -1038,18 +684,14 @@ if (!cs->irq) { printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); - return(0); + goto err; } if (!cs->hw.diva.cfg_reg) { printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); - return(0); + goto err; } cs->irq_flags |= SA_SHIRQ; -#else - printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); - printk(KERN_WARNING "Diva: unable to config DIVA PCI\n"); - return (0); #endif /* CONFIG_PCI */ if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_IPACX_PCI) ) { @@ -1058,7 +700,6 @@ cs->hw.diva.hscx = 0; cs->hw.diva.isac_adr = 0; cs->hw.diva.hscx_adr = 0; - test_and_set_bit(HW_IPAC, &cs->HW_Flags); bytecnt = 0; } else { cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; @@ -1086,51 +727,36 @@ cs->hw.diva.pci_cfg); if ((cs->subtyp != DIVA_IPAC_PCI) && (cs->subtyp != DIVA_IPACX_PCI) ) { - if (check_region(cs->hw.diva.cfg_reg, bytecnt)) { - printk(KERN_WARNING - "HiSax: %s config port %lx-%lx already in use\n", - CardType[card->typ], - cs->hw.diva.cfg_reg, - cs->hw.diva.cfg_reg + bytecnt); - return (0); - } else { - request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn"); - } + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) + return 0; } - reset_diva(cs); - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &Diva_card_msg; if (cs->subtyp == DIVA_IPAC_ISA) { - cs->dc_hw_ops = &ipac_dc_ops; - cs->irq_func = &diva_irq_ipac_isa; - val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID); - printk(KERN_INFO "Diva: IPAC version %x\n", val); + diva_ipac_isa_reset(cs); + cs->card_ops = &diva_ipac_isa_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; } else if (cs->subtyp == DIVA_IPAC_PCI) { - cs->dc_hw_ops = &mem_ipac_dc_ops; - cs->bc_hw_ops = &mem_hscx_ops; - cs->bc_l1_ops = &mem_hscx_l1_ops; - cs->irq_func = &diva_irq_ipac_pci; - val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID); - printk(KERN_INFO "Diva: IPAC version %x\n", val); + diva_ipac_pci_reset(cs); + cs->card_ops = &diva_ipac_pci_ops; + if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops)) + goto err; } else if (cs->subtyp == DIVA_IPACX_PCI) { - cs->dc_hw_ops = &ipacx_dc_ops; - cs->bc_hw_ops = &ipacx_bc_ops; - cs->irq_func = &diva_irq_ipacx_pci; - printk(KERN_INFO "Diva: IPACX Design Id: %x\n", - ipacx_dc_read(cs, IPACX_ID) &0x3F); + diva_ipacx_pci_reset(cs); + cs->card_ops = &diva_ipacx_pci_ops; + if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops)) + goto err; } else { /* DIVA 2.0 */ + diva_reset(cs); cs->hw.diva.tl.function = (void *) diva_led_handler; cs->hw.diva.tl.data = (long) cs; init_timer(&cs->hw.diva.tl); - cs->dc_hw_ops = &isac_ops; - cs->irq_func = &diva_interrupt; - ISACVersion(cs, "Diva:"); - if (HscxVersion(cs, "Diva:")) { - printk(KERN_WARNING - "Diva: wrong HSCX versions check IO address\n"); - release_io_diva(cs); - return (0); - } - } - return (1); + cs->card_ops = &diva_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + } + return 1; + err: + diva_release(cs); + return 0; + } diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/elsa.c Mon Jan 13 10:18:05 2003 @@ -106,7 +106,6 @@ /* Status Flags */ #define ELSA_TIMER_AKTIV 1 #define ELSA_BAD_PWR 2 -#define ELSA_ASSIGN 4 #define RS_ISR_PASS_LIMIT 256 #define _INLINE_ inline @@ -212,37 +211,6 @@ }; static u8 -ipac_dc_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, cs->hw.elsa.isac, offset+0x80); -} - -static void -ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - writereg(cs, cs->hw.elsa.isac, offset|0x80, value); -} - -static void -ipac_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size) -{ - readfifo(cs, cs->hw.elsa.isac, 0x80, data, size); -} - -static void -ipac_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size) -{ - writefifo(cs, cs->hw.elsa.isac, 0x80, data, size); -} - -static struct dc_hw_ops ipac_dc_ops = { - .read_reg = ipac_dc_read, - .write_reg = ipac_dc_write, - .read_fifo = ipac_dc_read_fifo, - .write_fifo = ipac_dc_write_fifo, -}; - -static u8 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) { return readreg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0)); @@ -274,6 +242,35 @@ }; static inline u8 +ipac_read(struct IsdnCardState *cs, u8 offset) +{ + return readreg(cs, cs->hw.elsa.isac, offset); +} + +static inline void +ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +{ + writereg(cs, cs->hw.elsa.isac, offset, value); +} + +static inline void +ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +{ + readfifo(cs, cs->hw.elsa.isac, offset, data, size); +} + +static inline void +ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +{ + writefifo(cs, cs->hw.elsa.isac, offset, data, size); +} + +/* This will generate ipac_dc_ops and ipac_bc_ops using the functions + * above */ + +BUILD_IPAC_OPS(ipac); + +static inline u8 readitac(struct IsdnCardState *cs, u8 off) { u8 ret; @@ -315,53 +312,26 @@ { struct IsdnCardState *cs = dev_id; u8 val; - int icnt=5; - spin_lock(&cs->lock); if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed causing us to just crash the kernel. bad. */ printk(KERN_WARNING "Elsa: card not available!\n"); - goto unlock; + return; } #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs,"IIR %02x", val); + spin_lock(&cs->lock); rs_interrupt_elsa(intno, cs); + spin_unlock(&cs->lock); } } #endif - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) { - hscx_int_main(cs, val); - } - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) { - isac_interrupt(cs, val); - } - val = hscx_read(cs, 1, HSCX_ISTA); - if (val && icnt) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - icnt--; - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val && icnt) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - icnt--; - goto Start_ISAC; - } - if (!icnt) - printk(KERN_WARNING"ELSA IRQ LOOP\n"); - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); + hscxisac_irq(intno, dev_id, regs); + if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) { if (!TimerRun(cs)) { /* Timer Restart */ @@ -381,19 +351,13 @@ #endif if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0x00); - hscx_write(cs, 0, HSCX_MASK, 0x00); - hscx_write(cs, 1, HSCX_MASK, 0x00); - isac_write(cs, ISAC_MASK, 0x00); - unlock: - spin_unlock(&cs->lock); } static void elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 ista,val; - int icnt=5; + u8 val; if (!cs) { printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); @@ -410,51 +374,18 @@ val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs,"IIR %02x", val); + spin_lock(&cs->lock); rs_interrupt_elsa(intno, cs); + spin_unlock(&cs->lock); } } #endif - ista = readreg(cs, cs->hw.elsa.isac, IPAC_ISTA); -Start_IPAC: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = hscx_read(cs, 1, HSCX_ISTA); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) - hscx_int_main(cs, val); - } - if (ista & 0x20) { - val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe; - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = readreg(cs, cs->hw.elsa.isac, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPAC; - } - if (!icnt) - printk(KERN_WARNING "ELSA IRQ LOOP\n"); - writereg(cs, cs->hw.elsa.isac, IPAC_MASK, 0xFF); - writereg(cs, cs->hw.elsa.isac, IPAC_MASK, 0xC0); + ipac_irq(intno, dev_id, regs); } -void -release_io_elsa(struct IsdnCardState *cs) +static void +elsa_release(struct IsdnCardState *cs) { - int bytecnt = 8; - del_timer(&cs->hw.elsa.tl); #if ARCOFI_USE clear_arcofi(cs); @@ -464,32 +395,27 @@ if (cs->subtyp == ELSA_QS1000PCI) { byteout(cs->hw.elsa.cfg + 0x4c, 0x01); /* disable IRQ */ writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); - bytecnt = 2; - release_region(cs->hw.elsa.cfg, 0x80); } if (cs->subtyp == ELSA_QS3000PCI) { byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */ writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); - release_region(cs->hw.elsa.cfg, 0x80); } if (cs->subtyp == ELSA_PCMCIA_IPAC) { writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); } +#if ARCOFI_USE if ((cs->subtyp == ELSA_PCFPRO) || (cs->subtyp == ELSA_QS3000) || (cs->subtyp == ELSA_PCF) || (cs->subtyp == ELSA_QS3000PCI)) { - bytecnt = 16; -#if ARCOFI_USE release_modem(cs); -#endif } - if (cs->hw.elsa.base) - release_region(cs->hw.elsa.base, bytecnt); +#endif + hisax_release_resources(cs); } -static void -reset_elsa(struct IsdnCardState *cs) +static int +elsa_reset(struct IsdnCardState *cs) { if (cs->hw.elsa.timer) { /* Wait 1 Timer */ @@ -531,6 +457,7 @@ else if (cs->subtyp == ELSA_QS3000PCI) byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */ } + return 0; } #if ARCOFI_USE @@ -597,28 +524,14 @@ "Elsa: %s detected modem at 0x%lx\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); - release_region(cs->hw.elsa.base, 8); - if (!request_region(cs->hw.elsa.base, 16,"elsa isdn modem")) { - printk(KERN_WARNING - "HiSax: %s config port %lx-%lx already in use\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base + 8, - cs->hw.elsa.base + 16); - } + request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem"); } else if (cs->subtyp==ELSA_PCC16) { cs->subtyp = ELSA_PCF; printk(KERN_INFO "Elsa: %s detected modem at 0x%lx\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); - release_region(cs->hw.elsa.base, 8); - if (!request_region(cs->hw.elsa.base, 16,"elsa isdn modem")) { - printk(KERN_WARNING - "HiSax: %s config port %lx-%lx already in use\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base + 8, - cs->hw.elsa.base + 16); - } + request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem"); } else printk(KERN_INFO "Elsa: %s detected modem at 0x%lx\n", @@ -639,8 +552,15 @@ if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC) return; - del_timer(&cs->hw.elsa.tl); - if (cs->hw.elsa.status & ELSA_ASSIGN) + + if (cs->typ == ISDN_CTYPE_ELSA) { + int pwr = bytein(cs->hw.elsa.ale); + if (pwr & 0x08) + cs->hw.elsa.status |= ELSA_BAD_PWR; + else + cs->hw.elsa.status &= ~ELSA_BAD_PWR; + } + if (cs->status & 0x0001) cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED; else if (cs->hw.elsa.status & ELSA_BAD_PWR) cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED; @@ -648,9 +568,9 @@ cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED; blink = 250; } - if (cs->hw.elsa.status & 0xf000) + if (cs->status & 0xf000) cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED; - else if (cs->hw.elsa.status & 0x0f00) { + else if (cs->status & 0x0f00) { cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED; blink = 500; } else @@ -666,128 +586,110 @@ writereg(cs, cs->hw.elsa.isac, IPAC_ATX, led); } else byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - if (blink) { - init_timer(&cs->hw.elsa.tl); - cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000); - add_timer(&cs->hw.elsa.tl); - } -} -static int -Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - int ret = 0; + if (blink) + mod_timer(&cs->hw.elsa.tl, jiffies + (blink * HZ) / 1000); +} - switch (mt) { - case CARD_RESET: - reset_elsa(cs); - return(0); - case CARD_RELEASE: - release_io_elsa(cs); - return(0); - case CARD_INIT: - cs->debug |= L1_DEB_IPAC; - if ((cs->subtyp == ELSA_QS1000) || - (cs->subtyp == ELSA_QS3000)) - { - byteout(cs->hw.elsa.timer, 0); - } - if (cs->hw.elsa.trig) - byteout(cs->hw.elsa.trig, 0xff); - inithscxisac(cs); - return(0); - case CARD_TEST: - if ((cs->subtyp == ELSA_PCMCIA) || - (cs->subtyp == ELSA_PCMCIA_IPAC) || - (cs->subtyp == ELSA_QS1000PCI)) { - return(0); - } else if (cs->subtyp == ELSA_QS3000PCI) { - ret = 0; - } else { - cs->hw.elsa.counter = 0; - cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT; - cs->hw.elsa.status |= ELSA_TIMER_AKTIV; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - byteout(cs->hw.elsa.timer, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((110*HZ)/1000); - cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; - printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", - cs->hw.elsa.counter); - if ((cs->hw.elsa.counter > 10) && - (cs->hw.elsa.counter < 16)) { - printk(KERN_INFO "Elsa: timer and irq OK\n"); - ret = 0; - } else { - printk(KERN_WARNING - "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", - cs->hw.elsa.counter, cs->irq); - ret = 1; - } - } -#if ARCOFI_USE - if (check_arcofi(cs)) { - init_modem(cs); - } -#endif - elsa_led_handler(cs); - return(ret); - case (MDL_REMOVE | REQUEST): - cs->hw.elsa.status &= 0; - break; - case (MDL_ASSIGN | REQUEST): - cs->hw.elsa.status |= ELSA_ASSIGN; - break; - case MDL_INFO_SETUP: - if ((long) arg) - cs->hw.elsa.status |= 0x0200; - else - cs->hw.elsa.status |= 0x0100; - break; - case MDL_INFO_CONN: - if ((long) arg) - cs->hw.elsa.status |= 0x2000; - else - cs->hw.elsa.status |= 0x1000; - break; - case MDL_INFO_REL: - if ((long) arg) { - cs->hw.elsa.status &= ~0x2000; - cs->hw.elsa.status &= ~0x0200; - } else { - cs->hw.elsa.status &= ~0x1000; - cs->hw.elsa.status &= ~0x0100; - } - break; #if ARCOFI_USE - case CARD_AUX_IND: - if (cs->hw.elsa.MFlag) { - int len; - u8 *msg; - - if (!arg) - return(0); - msg = arg; - len = *msg; - msg++; - modem_write_cmd(cs, msg, len); - } - break; +static void +elsa_aux_ind(struct IsdnCardState *cs, void *arg) +{ + if (cs->hw.elsa.MFlag) { + int len; + u8 *msg; + + if (!arg) + return; + msg = arg; + len = *msg; + msg++; + modem_write_cmd(cs, msg, len); + } +} +#else +#define elsa_aux_ind NULL #endif + +static void +elsa_init(struct IsdnCardState *cs) +{ + if (cs->subtyp == ELSA_QS1000 || cs->subtyp == ELSA_QS3000) + byteout(cs->hw.elsa.timer, 0); + + if (cs->hw.elsa.trig) + byteout(cs->hw.elsa.trig, 0xff); + + inithscxisac(cs); +} + +static void +elsa_ipac_init(struct IsdnCardState *cs) +{ + if (cs->hw.elsa.trig) + byteout(cs->hw.elsa.trig, 0xff); + + ipac_init(cs); +} + +static void +elsa_test(struct IsdnCardState *cs) +{ + if ((cs->subtyp == ELSA_PCMCIA) || + (cs->subtyp == ELSA_PCMCIA_IPAC) || + (cs->subtyp == ELSA_QS1000PCI)) { + return; + } + if (cs->subtyp != ELSA_QS3000PCI) { + cs->hw.elsa.counter = 0; + cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT; + cs->hw.elsa.status |= ELSA_TIMER_AKTIV; + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + byteout(cs->hw.elsa.timer, 0); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((110*HZ)/1000); + cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; + printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", + cs->hw.elsa.counter); + if ((cs->hw.elsa.counter > 10) && + (cs->hw.elsa.counter < 16)) { + printk(KERN_INFO "Elsa: timer and irq OK\n"); + } else { + printk(KERN_WARNING + "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", + cs->hw.elsa.counter, cs->irq); + } } - if (cs->typ == ISDN_CTYPE_ELSA) { - int pwr = bytein(cs->hw.elsa.ale); - if (pwr & 0x08) - cs->hw.elsa.status |= ELSA_BAD_PWR; - else - cs->hw.elsa.status &= ~ELSA_BAD_PWR; +#if ARCOFI_USE + if (check_arcofi(cs)) { + init_modem(cs); } +#endif elsa_led_handler(cs); - return(ret); } +static struct card_ops elsa_ops = { + .init = elsa_init, + .test = elsa_test, + .reset = elsa_reset, + .release = elsa_release, + .aux_ind = elsa_aux_ind, + .led_handler = elsa_led_handler, + .irq_func = elsa_interrupt, +}; + +static struct card_ops elsa_ipac_ops = { + .init = elsa_ipac_init, + .test = elsa_test, + .reset = elsa_reset, + .release = elsa_release, + .aux_ind = elsa_aux_ind, + .led_handler = elsa_led_handler, + .irq_func = elsa_interrupt_ipac, +}; + static unsigned char probe_elsa_adr(unsigned int adr, int typ) { @@ -863,7 +765,7 @@ }; static struct isapnp_device_id *pdev = &elsa_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit @@ -943,31 +845,39 @@ } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; while(pdev->card_vendor) { - if ((pb = isapnp_find_card(pdev->card_vendor, - pdev->card_device, pnp_c))) { + if ((pb = pnp_find_card(pdev->card_vendor, + pdev->card_device, + pnp_c))) { pnp_c = pb; pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - pdev->vendor, pdev->function, pd))) { + if ((pd = pnp_find_dev(pnp_c, + pdev->vendor, + pdev->function, + pd))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)pdev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = - pd->resource[0].start; - card->para[0] = - pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "Elsa PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + pnp_device_detach(pd); + printk(KERN_ERR "Elsa PnP: activate failed\n"); + return 0; + } + if (!pnp_port_valid(pd, 0) || + !pnp_irq_valid(pd, 0)) { printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n", - card->para[0], card->para[1]); - pd->deactivate(pd); + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); return(0); } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); if (pdev->function == ISAPNP_FUNCTION(0x133)) cs->subtyp = ELSA_QS1000; else @@ -1016,7 +926,6 @@ cs->subtyp = ELSA_PCMCIA_IPAC; cs->hw.elsa.isac = cs->hw.elsa.base + 2; cs->hw.elsa.hscx = cs->hw.elsa.base + 2; - test_and_set_bit(HW_IPAC, &cs->HW_Flags); } else { cs->subtyp = ELSA_PCMCIA; cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; @@ -1033,10 +942,6 @@ cs->irq); } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { #if CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "Elsa: no PCI bus present\n"); - return(0); - } cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { @@ -1076,7 +981,6 @@ cs->hw.elsa.ale = cs->hw.elsa.base; cs->hw.elsa.isac = cs->hw.elsa.base +1; cs->hw.elsa.hscx = cs->hw.elsa.base +1; - test_and_set_bit(HW_IPAC, &cs->HW_Flags); cs->hw.elsa.timer = 0; cs->hw.elsa.trig = 0; cs->irq_flags |= SA_SHIRQ; @@ -1086,10 +990,6 @@ cs->hw.elsa.base, cs->hw.elsa.cfg, cs->irq); -#else - printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n"); - printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n"); - return (0); #endif /* CONFIG_PCI */ } else return (0); @@ -1121,29 +1021,17 @@ reserved for us by the card manager. So we do not check it here, it would fail. */ if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA) - if (!request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) { - printk(KERN_WARNING - "HiSax: %s config port %#lx-%#lx already in use\n", - CardType[card->typ], - cs->hw.elsa.base, - cs->hw.elsa.base + bytecnt); - return (0); - } + if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) + goto err; - if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { - if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) { - printk(KERN_WARNING - "HiSax: %s pci port %x-%x already in use\n", - CardType[card->typ], - cs->hw.elsa.cfg, - cs->hw.elsa.cfg + 0x80); - release_region(cs->hw.elsa.base, bytecnt); - return (0); - } - } + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) + if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) + goto err; + #if ARCOFI_USE init_arcofi(cs); #endif + cs->hw.elsa.tl.function = (void *) elsa_led_handler; cs->hw.elsa.tl.data = (long) cs; init_timer(&cs->hw.elsa.tl); @@ -1156,36 +1044,25 @@ if (!TimerRun(cs)) { printk(KERN_WARNING "Elsa: timer do not start\n"); - release_io_elsa(cs); - return (0); + goto err; } } HZDELAY(1); /* wait >=10 ms */ if (TimerRun(cs)) { printk(KERN_WARNING "Elsa: timer do not run down\n"); - release_io_elsa(cs); - return (0); + goto err; } printk(KERN_INFO "Elsa: timer OK; resetting card\n"); } - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &Elsa_card_msg; - reset_elsa(cs); + elsa_reset(cs); if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { - cs->dc_hw_ops = &ipac_dc_ops; - cs->irq_func = &elsa_interrupt_ipac; - val = readreg(cs, cs->hw.elsa.isac, IPAC_ID); - printk(KERN_INFO "Elsa: IPAC version %x\n", val); + cs->card_ops = &elsa_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; } else { - cs->dc_hw_ops = &isac_ops; - cs->irq_func = &elsa_interrupt; - ISACVersion(cs, "Elsa:"); - if (HscxVersion(cs, "Elsa:")) { - printk(KERN_WARNING - "Elsa: wrong HSCX versions check IO address\n"); - release_io_elsa(cs); - return (0); - } + cs->card_ops = &elsa_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; } if (cs->subtyp == ELSA_PC) { val = readitac(cs, ITAC_SYS); @@ -1196,5 +1073,8 @@ writeitac(cs, ITAC_SCIE, 0); writeitac(cs, ITAC_STIE, 0); } - return (1); + return 1; + err: + elsa_release(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c --- a/drivers/isdn/hisax/elsa_ser.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/elsa_ser.c Mon Jan 13 10:18:05 2003 @@ -375,11 +375,6 @@ } } -static struct bc_l1_ops modem_l1_ops = { - .fill_fifo = modem_fill, -}; - - static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs) { int status, iir, msr; @@ -424,10 +419,10 @@ { modehscx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hscx.rcvbuf) { + if (bcs->rcvbuf) { if (bcs->mode != L1_MODE_MODEM) - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; + kfree(bcs->rcvbuf); + bcs->rcvbuf = NULL; } skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); @@ -597,23 +592,23 @@ if (open_hscxstate(st->l1.hardware, bcs)) return (-1); st->l1.l2l1 = hscx_l2l1; - // bcs->cs->BC_Send_Data = hscx_fill_fifo; + // bcs->cs->BC_Send_Data = hscx_fill_fifo; FIXME break; case L1_MODE_MODEM: bcs->mode = L1_MODE_MODEM; if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf; + bcs->rcvbuf = bcs->cs->hw.elsa.rcvbuf; skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; - bcs->hw.hscx.rcvidx = 0; + bcs->rcvidx = 0; bcs->tx_cnt = 0; bcs->cs->hw.elsa.bcs = bcs; st->l1.l2l1 = modem_l2l1; - bcs->cs->bc_l1_ops = &modem_l1_ops; +// bcs->cs->bc_l1_ops = &modem_l1_ops; break; } st->l1.bcs = bcs; @@ -623,13 +618,17 @@ return (0); } +static struct bc_l1_ops modem_l1_ops = { + .fill_fifo = modem_fill, + .open = setstack_elsa, + .close = close_elsastate, +}; + void -init_modem(struct IsdnCardState *cs) { +init_modem(struct IsdnCardState *cs) +{ + cs->bc_l1_ops = &modem_l1_ops; - cs->bcs[0].BC_SetStack = setstack_elsa; - cs->bcs[1].BC_SetStack = setstack_elsa; - cs->bcs[0].BC_Close = close_elsastate; - cs->bcs[1].BC_Close = close_elsastate; if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF, GFP_ATOMIC))) { printk(KERN_WARNING diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c --- a/drivers/isdn/hisax/enternow_pci.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/enternow_pci.c Mon Jan 13 10:18:07 2003 @@ -110,13 +110,14 @@ } -static struct dc_hw_ops enternow_ops = { +static struct dc_hw_ops amd7930_ops = { .read_reg = ReadByteAmd7930, .write_reg = WriteByteAmd7930, }; -void -enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) { +static void +enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) +{ if (!val) OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00); else @@ -152,72 +153,60 @@ OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off } - -static int -enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +enpci_bc_activate(struct IsdnCardState *cs, int chan) { - BYTE *chan; - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt); + debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", chan); + + cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (chan + 1)), "MDL_BC_ASSIGN"); + /* at least one b-channel in use, LED 2 on */ + cs->hw.njet.auxd |= TJ_AMD_IRQ << 2; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); +} - switch (mt) { - case CARD_RESET: - reset_enpci(cs); - Amd7930_init(cs); - break; - case CARD_RELEASE: - release_io_netjet(cs); - break; - case CARD_INIT: - inittiger(cs); - Amd7930_init(cs); - break; - case CARD_TEST: - break; - case MDL_ASSIGN: - /* TEI assigned, LED1 on */ - cs->hw.njet.auxd = TJ_AMD_IRQ << 1; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); - break; - case MDL_REMOVE: - /* TEI removed, LEDs off */ - cs->hw.njet.auxd = 0; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00); - break; - case MDL_BC_ASSIGN: - /* activate B-channel */ - chan = (BYTE *)arg; - - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan); - - cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN"); - /* at least one b-channel in use, LED 2 on */ - cs->hw.njet.auxd |= TJ_AMD_IRQ << 2; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); - break; - case MDL_BC_RELEASE: - /* deactivate B-channel */ - chan = (BYTE *)arg; - - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan); - - cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(*chan + 1)), "MDL_BC_RELEASE"); - /* no b-channel active -> LED2 off */ - if (!(cs->dc.amd7930.lmr1 & 3)) { - cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2); - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); - } - break; - default: - break; +static void +enpci_bc_deactivate(struct IsdnCardState *cs, int chan) +{ + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", chan); + + cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(chan + 1)), "MDL_BC_RELEASE"); + /* no b-channel active -> LED2 off */ + if (!(cs->dc.amd7930.lmr1 & 3)) { + cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2); + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + } +} +static void +enpci_led_handler(struct IsdnCardState *cs) +{ + if (cs->status & 0x0001) { + /* TEI assigned, LED1 on */ + cs->hw.njet.auxd = TJ_AMD_IRQ << 1; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + } else { + /* TEI removed, LEDs off */ + cs->hw.njet.auxd = 0; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00); } - return(0); } +static void +enpci_init(struct IsdnCardState *cs) +{ + inittiger(cs); + Amd7930_init(cs); +} + +static int +enpci_reset(struct IsdnCardState *cs) +{ + reset_enpci(cs); + Amd7930_init(cs); + return 0; +} static void enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) @@ -266,6 +255,13 @@ spin_unlock(&cs->lock); } +static struct card_ops enpci_ops = { + .init = enpci_init, + .reset = enpci_reset, + .release = netjet_release, + .led_handler = enpci_led_handler, + .irq_func = enpci_interrupt, +}; static struct pci_dev *dev_netjet __initdata = NULL; @@ -273,25 +269,16 @@ int __init setup_enternow_pci(struct IsdnCard *card) { - int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; -#if CONFIG_PCI #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, enternow_pci_rev); printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_ENTERNOW) - return(0); - for ( ;; ) - { - if (!pci_present()) { - printk(KERN_ERR "enter:now PCI: no PCI bus present\n"); - return(0); - } + for ( ;; ) { if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { if (pci_enable_device(dev_netjet)) @@ -344,61 +331,19 @@ break; } -#else - - printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n"); - printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n"); - return (0); - -#endif /* CONFIG_PCI */ - - bytecnt = 256; - printk(KERN_INFO "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", cs->hw.njet.base, cs->irq); - if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) { - printk(KERN_WARNING - "HiSax: %s config port %lx-%lx already in use\n", - CardType[card->typ], - cs->hw.njet.base, - cs->hw.njet.base + bytecnt); - return (0); - } + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN")) + return 0; reset_enpci(cs); cs->hw.njet.last_is0 = 0; - cs->dc_hw_ops = &enternow_ops; - cs->dc.amd7930.setIrqMask = &enpci_setIrqMask; + cs->hw.njet.bc_activate = enpci_bc_activate; + cs->hw.njet.bc_deactivate = enpci_bc_deactivate; + amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask); - cs->cardmsg = &enpci_card_msg; - cs->irq_func = &enpci_interrupt; cs->irq_flags |= SA_SHIRQ; + cs->card_ops = &enpci_ops; - return (1); + return 1; } - - - - - - - - - - - - - - - - - - - - - - - - - - diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c --- a/drivers/isdn/hisax/gazel.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/gazel.c Mon Jan 13 10:18:06 2003 @@ -69,431 +69,313 @@ outsb(adr, data, size); } -static inline u8 -readreg_ipac(struct IsdnCardState *cs, u_short off) -{ - register u8 ret; - unsigned long flags; - - spin_lock_irqsave(&gazel_lock, flags); - byteout(cs->hw.gazel.ipac, off); - ret = bytein(cs->hw.gazel.ipac + 4); - spin_unlock_irqrestore(&gazel_lock, flags); - return ret; -} - -static inline void -writereg_ipac(struct IsdnCardState *cs, u_short off, u8 data) +static u8 +r685_isac_read(struct IsdnCardState *cs, u8 off) { - unsigned long flags; - - spin_lock_irqsave(&gazel_lock, flags); - byteout(cs->hw.gazel.ipac, off); - byteout(cs->hw.gazel.ipac + 4, data); - spin_unlock_irqrestore(&gazel_lock, flags); + return readreg(cs->hw.gazel.isac, off); } - -static inline void -read_fifo_ipac(struct IsdnCardState *cs, u_short off, u8 * data, int size) +static u8 +r647_isac_read(struct IsdnCardState *cs, u8 off) { - byteout(cs->hw.gazel.ipac, off); - insb(cs->hw.gazel.ipac + 4, data, size); + return readreg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf)); } static void -write_fifo_ipac(struct IsdnCardState *cs, u_short off, u8 * data, int size) +r685_isac_write(struct IsdnCardState *cs, u8 off, u8 value) { - byteout(cs->hw.gazel.ipac, off); - outsb(cs->hw.gazel.ipac + 4, data, size); -} - -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) -{ - u_short off2 = offset; - - switch (cs->subtyp) { - case R647: - off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); - case R685: - return (readreg(cs->hw.gazel.isac, off2)); - case R753: - case R742: - return (readreg_ipac(cs, 0x80 + off2)); - } - return 0; + writereg(cs->hw.gazel.isac, off, value); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +r647_isac_write(struct IsdnCardState *cs, u8 off, u8 value) { - u_short off2 = offset; - - switch (cs->subtyp) { - case R647: - off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); - case R685: - writereg(cs->hw.gazel.isac, off2, value); - break; - case R753: - case R742: - writereg_ipac(cs, 0x80 + off2, value); - break; - } + writereg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf), value); } static void isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) { - switch (cs->subtyp) { - case R647: - case R685: - read_fifo(cs->hw.gazel.isacfifo, data, size); - break; - case R753: - case R742: - read_fifo_ipac(cs, 0x80, data, size); - break; - } + read_fifo(cs->hw.gazel.isacfifo, data, size); } static void isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) { - switch (cs->subtyp) { - case R647: - case R685: - write_fifo(cs->hw.gazel.isacfifo, data, size); - break; - case R753: - case R742: - write_fifo_ipac(cs, 0x80, data, size); - break; - } + write_fifo(cs->hw.gazel.isacfifo, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, +static struct dc_hw_ops r685_isac_ops = { + .read_reg = r685_isac_read, + .write_reg = r685_isac_write, .read_fifo = isac_read_fifo, .write_fifo = isac_write_fifo, }; +static struct dc_hw_ops r647_isac_ops = { + .read_reg = r647_isac_read, + .write_reg = r647_isac_write, + .read_fifo = isac_read_fifo, + .write_fifo = isac_write_fifo, +}; + static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +r685_hscx_read(struct IsdnCardState *cs, int hscx, u8 off) { - u_short off2 = offset; + return readreg(cs->hw.gazel.hscx[hscx], off); +} - switch (cs->subtyp) { - case R647: - off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); - case R685: - return readreg(cs->hw.gazel.hscx[hscx], off2); - case R753: - case R742: - return readreg_ipac(cs, hscx * 0x40 + off2); - } - return 0; +static u8 +r647_hscx_read(struct IsdnCardState *cs, int hscx, u8 off) +{ + return readreg(cs->hw.gazel.hscx[hscx], + (off << 8 & 0xf000) | (off & 0xf)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +r685_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value) { - u_short off2 = offset; + writereg(cs->hw.gazel.hscx[hscx], off, value); +} - switch (cs->subtyp) { - case R647: - off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); - case R685: - writereg(cs->hw.gazel.hscx[hscx], off2, value); - break; - case R753: - case R742: - writereg_ipac(cs, hscx * 0x40 + off2, value); - break; - } +static void +r647_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value) +{ + writereg(cs->hw.gazel.hscx[hscx], + (off << 8 & 0xf000) | (off & 0xf), value); } static void hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) { - switch (cs->subtyp) { - case R647: - case R685: - read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); - break; - case R753: - case R742: - read_fifo_ipac(cs, hscx * 0x40, data, size); - break; - } + read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); } static void hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) { - switch (cs->subtyp) { - case R647: - case R685: - write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); - break; - case R753: - case R742: - write_fifo_ipac(cs, hscx * 0x40, data, size); - break; - } + write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, +static struct bc_hw_ops r685_hscx_ops = { + .read_reg = r685_hscx_read, + .write_reg = r685_hscx_write, .read_fifo = hscx_read_fifo, .write_fifo = hscx_write_fifo, }; -static void -gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs) +static struct bc_hw_ops r647_hscx_ops = { + .read_reg = r647_hscx_read, + .write_reg = r647_hscx_write, + .read_fifo = hscx_read_fifo, + .write_fifo = hscx_write_fifo, +}; + +static inline u8 +ipac_read(struct IsdnCardState *cs, u_short off) { -#define MAXCOUNT 5 - struct IsdnCardState *cs = dev_id; - u8 valisac, valhscx; - int count = 0; - - spin_lock(&cs->lock); - do { - valhscx = hscx_read(cs, 1, HSCX_ISTA); - if (valhscx) - hscx_int_main(cs, valhscx); - valisac = isac_read(cs, ISAC_ISTA); - if (valisac) - isac_interrupt(cs, valisac); - count++; - } while ((valhscx || valisac) && (count < MAXCOUNT)); - - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); -} + register u8 ret; + unsigned long flags; + spin_lock_irqsave(&gazel_lock, flags); + byteout(cs->hw.gazel.ipac, off); + ret = bytein(cs->hw.gazel.ipac + 4); + spin_unlock_irqrestore(&gazel_lock, flags); + return ret; +} -static void -gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +static inline void +ipac_write(struct IsdnCardState *cs, u_short off, u8 data) { - struct IsdnCardState *cs = dev_id; - u8 ista, val; - int count = 0; - - if (!cs) { - printk(KERN_WARNING "Gazel: Spurious interrupt!\n"); - return; - } - ista = readreg_ipac(cs, IPAC_ISTA); - do { - if (ista & 0x0f) { - val = hscx_read(cs, 1, HSCX_ISTA); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) { - hscx_int_main(cs, val); - } - } - if (ista & 0x20) { - val = isac_read(cs, ISAC_ISTA) & 0xfe; - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = readreg_ipac(cs, IPAC_ISTA); - count++; - } - while ((ista & 0x3f) && (count < MAXCOUNT)); + unsigned long flags; - writereg_ipac(cs, IPAC_MASK, 0xFF); - writereg_ipac(cs, IPAC_MASK, 0xC0); + spin_lock_irqsave(&gazel_lock, flags); + byteout(cs->hw.gazel.ipac, off); + byteout(cs->hw.gazel.ipac + 4, data); + spin_unlock_irqrestore(&gazel_lock, flags); } -void -release_io_gazel(struct IsdnCardState *cs) + + +static inline void +ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) { - unsigned int i; + byteout(cs->hw.gazel.ipac, off); + insb(cs->hw.gazel.ipac + 4, data, size); +} - switch (cs->subtyp) { - case R647: - for (i = 0x0000; i < 0xC000; i += 0x1000) - release_region(i + cs->hw.gazel.hscx[0], 16); - release_region(0xC000 + cs->hw.gazel.hscx[0], 1); - break; +static inline void +ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) +{ + byteout(cs->hw.gazel.ipac, off); + outsb(cs->hw.gazel.ipac + 4, data, size); +} - case R685: - release_region(cs->hw.gazel.hscx[0], 0x100); - release_region(cs->hw.gazel.cfg_reg, 0x80); - break; +/* This will generate ipac_dc_ops and ipac_bc_ops using the functions + * above */ - case R753: - release_region(cs->hw.gazel.ipac, 0x8); - release_region(cs->hw.gazel.cfg_reg, 0x80); - break; +BUILD_IPAC_OPS(ipac); - case R742: - release_region(cs->hw.gazel.ipac, 8); - break; - } +static int +r647_reset(struct IsdnCardState *cs) +{ + writereg(cs->hw.gazel.cfg_reg, 0, 0); + HZDELAY(10); + writereg(cs->hw.gazel.cfg_reg, 0, 1); + HZDELAY(2); + return 0; } static int -reset_gazel(struct IsdnCardState *cs) +r685_reset(struct IsdnCardState *cs) { unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; - switch (cs->subtyp) { - case R647: - writereg(addr, 0, 0); - HZDELAY(10); - writereg(addr, 0, 1); - HZDELAY(2); - break; - case R685: - plxcntrl = inl(addr + PLX_CNTRL); - plxcntrl |= (RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - plxcntrl &= ~(RESET_9050 + RESET_GAZEL); - HZDELAY(4); - outl(plxcntrl, addr + PLX_CNTRL); - HZDELAY(10); - outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); - break; - case R753: - if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags)) - /* we can't read, assume the default */ - plxcntrl = 0x18784db6; - else - plxcntrl = inl(addr + PLX_CNTRL); - plxcntrl |= (RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - writereg_ipac(cs, IPAC_POTA2, 0x20); - HZDELAY(4); - plxcntrl &= ~(RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - HZDELAY(10); - writereg_ipac(cs, IPAC_POTA2, 0x00); - writereg_ipac(cs, IPAC_ACFG, 0xff); - writereg_ipac(cs, IPAC_AOE, 0x0); - writereg_ipac(cs, IPAC_MASK, 0xff); - writereg_ipac(cs, IPAC_CONF, 0x1); - outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); - writereg_ipac(cs, IPAC_MASK, 0xc0); - break; - case R742: - writereg_ipac(cs, IPAC_POTA2, 0x20); - HZDELAY(4); - writereg_ipac(cs, IPAC_POTA2, 0x00); - writereg_ipac(cs, IPAC_ACFG, 0xff); - writereg_ipac(cs, IPAC_AOE, 0x0); - writereg_ipac(cs, IPAC_MASK, 0xff); - writereg_ipac(cs, IPAC_CONF, 0x1); - writereg_ipac(cs, IPAC_MASK, 0xc0); - break; - } - return (0); + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + HZDELAY(4); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); + return 0; } static int -Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg) +r753_reset(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - reset_gazel(cs); - return (0); - case CARD_RELEASE: - release_io_gazel(cs); - return (0); - case CARD_INIT: - inithscxisac(cs); - if ((cs->subtyp==R647)||(cs->subtyp==R685)) { - int i; - for (i=0;i<(2+MAX_WAITING_CALLS);i++) { - cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; - cs->bcs[i].hw.hscx.tsaxr1 = 0x23; - } - } - return (0); - case CARD_TEST: - return (0); - } - return (0); + unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; + + if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags)) + /* we can't read, assume the default */ + plxcntrl = 0x18784db6; + else + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + ipac_write(cs, IPAC_POTA2, 0x20); + HZDELAY(4); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + ipac_write(cs, IPAC_POTA2, 0x00); + ipac_write(cs, IPAC_ACFG, 0xff); + ipac_write(cs, IPAC_AOE, 0x0); + ipac_write(cs, IPAC_MASK, 0xff); + ipac_write(cs, IPAC_CONF, 0x1); + outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); + ipac_write(cs, IPAC_MASK, 0xc0); + return 0; } static int -reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs) +r742_reset(struct IsdnCardState *cs) { - unsigned int i, base = 0, adr = 0, len = 0; - - switch (cs->subtyp) { - case R647: - base = cs->hw.gazel.hscx[0]; - for (i = 0x0000; i < 0xC000; i += 0x1000) { - if (!request_region(adr = (i + base), len = 16, "gazel")) { - int j; - - for (j = 0x0000; j < i; j += 0x1000) - release_region ((j + base), len); - goto error; - } - } - if (!request_region(adr = (0xC000 + base), len = 1, "gazel")) { - for (i = 0x0000; i < 0xC000; i += 0x1000) - release_region ((i + base), 16); - goto error; - } - - break; - - case R685: - if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel")) - goto error; - if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { - release_region (cs->hw.gazel.hscx[0], 0x100); - goto error; - } + ipac_write(cs, IPAC_POTA2, 0x20); + HZDELAY(4); + ipac_write(cs, IPAC_POTA2, 0x00); + ipac_write(cs, IPAC_ACFG, 0xff); + ipac_write(cs, IPAC_AOE, 0x0); + ipac_write(cs, IPAC_MASK, 0xff); + ipac_write(cs, IPAC_CONF, 0x1); + ipac_write(cs, IPAC_MASK, 0xc0); + return 0; +} - break; +static void +gazel_init(struct IsdnCardState *cs) +{ + int i; - case R753: - if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) - goto error; - if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { - release_region (cs->hw.gazel.ipac, 0x8); - goto error; - } + for (i = 0; i < 2; i++) { + cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; + cs->bcs[i].hw.hscx.tsaxr1 = 0x23; + } + inithscxisac(cs); +} - break; +static int +r647_reserve_regions(struct IsdnCardState *cs) +{ + int i, base = cs->hw.gazel.hscx[0]; - case R742: - if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) - goto error; - break; + for (i = 0; i < 0xc000; i += 0x1000) { + if (!request_io(&cs->rs, i + base, 16, "gazel")) + goto err; } + if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel")) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} +static int +r685_reserve_regions(struct IsdnCardState *cs) +{ + if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel")) + goto err; + if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) + goto err; return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} - error: - printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n", - CardType[cs->typ], adr, adr + len); - return 1; +static int +r742_reserve_regions(struct IsdnCardState *cs) +{ + if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int +r753_reserve_regions(struct IsdnCardState *cs) +{ + if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) + goto err; + if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; } +static struct card_ops r647_ops = { + .init = gazel_init, + .reset = r647_reset, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; + +static struct card_ops r685_ops = { + .init = gazel_init, + .reset = r685_reset, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; + +static struct card_ops r742_ops = { + .init = ipac_init, + .reset = r742_reset, + .release = hisax_release_resources, + .irq_func = ipac_irq, +}; + +static struct card_ops r753_ops = { + .init = ipac_init, + .reset = r753_reset, + .release = hisax_release_resources, + .irq_func = ipac_irq, +}; + static int __init setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) { @@ -503,7 +385,7 @@ // R647 returns FF if not present or not started // eventually needs improvment cs->hw.gazel.ipac = card->para[1]; - if (readreg_ipac(cs, IPAC_ID) == 1) + if (ipac_read(cs, IPAC_ID) == 1) cs->subtyp = R742; else cs->subtyp = R647; @@ -518,27 +400,25 @@ cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; switch (cs->subtyp) { - case R647: - printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO - "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - - break; - case R742: - printk(KERN_INFO "Gazel: Card ISA R742 found\n"); - test_and_set_bit(HW_IPAC, &cs->HW_Flags); - printk(KERN_INFO - "Gazel: config irq:%d ipac:0x%X\n", - cs->irq, cs->hw.gazel.ipac); - break; + case R647: + printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + + return r647_reserve_regions(cs); + case R742: + printk(KERN_INFO "Gazel: Card ISA R742 found\n"); + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X\n", + cs->irq, cs->hw.gazel.ipac); + return r742_reserve_regions(cs); } - - return (0); + return 0; } static struct pci_dev *dev_tel __initdata = NULL; @@ -572,22 +452,22 @@ break; else { switch (seekcard) { - case PCI_DEVICE_ID_PLX_R685: - seekcard = PCI_DEVICE_ID_PLX_R753; - break; - case PCI_DEVICE_ID_PLX_R753: - seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; - break; + case PCI_DEVICE_ID_PLX_R685: + seekcard = PCI_DEVICE_ID_PLX_R753; + break; + case PCI_DEVICE_ID_PLX_R753: + seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; + break; } } } if (!found) { printk(KERN_WARNING "Gazel: No PCI card found\n"); - return (1); + return -ENODEV; } if (!pci_irq) { printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); - return 1; + return -ENODEV; } cs->hw.gazel.pciaddr[0] = pci_ioaddr0; cs->hw.gazel.pciaddr[1] = pci_ioaddr1; @@ -605,41 +485,39 @@ cs->irq_flags |= SA_SHIRQ; switch (seekcard) { - case PCI_DEVICE_ID_PLX_R685: - printk(KERN_INFO "Gazel: Card PCI R685 found\n"); - cs->subtyp = R685; - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO - "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - break; - case PCI_DEVICE_ID_PLX_R753: - case PCI_DEVICE_ID_PLX_DJINN_ITOO: - printk(KERN_INFO "Gazel: Card PCI R753 found\n"); - cs->subtyp = R753; - test_and_set_bit(HW_IPAC, &cs->HW_Flags); - printk(KERN_INFO - "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); - /* - * Erratum for PLX9050, revision 1: - * If bit 7 of BAR 0/1 is set, local config registers - * can not be read (write is okay) - */ - if (cs->hw.gazel.cfg_reg & 0x80) { - pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev); - if (pci_rev == 1) { - printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n"); - set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } + case PCI_DEVICE_ID_PLX_R685: + printk(KERN_INFO "Gazel: Card PCI R685 found\n"); + cs->subtyp = R685; + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + return r685_reserve_regions(cs); + case PCI_DEVICE_ID_PLX_R753: + case PCI_DEVICE_ID_PLX_DJINN_ITOO: + printk(KERN_INFO "Gazel: Card PCI R753 found\n"); + cs->subtyp = R753; + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); + /* + * Erratum for PLX9050, revision 1: + * If bit 7 of BAR 0/1 is set, local config registers + * can not be read (write is okay) + */ + if (cs->hw.gazel.cfg_reg & 0x80) { + pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev); + if (pci_rev == 1) { + printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n"); + set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); } - break; + } + return r753_reserve_regions(cs); } - - return (0); + return 0; } int __init @@ -647,59 +525,46 @@ { struct IsdnCardState *cs = card->cs; char tmp[64]; - u8 val; strcpy(tmp, gazel_revision); printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_GAZEL) - return (0); - if (card->para[0]) { if (setup_gazelisa(card, cs)) return (0); } else { - -#if CONFIG_PCI if (setup_gazelpci(cs)) return (0); -#else - printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n"); - return (0); -#endif /* CONFIG_PCI */ - } - - if (reserve_regions(card, cs)) { - return (0); - } - if (reset_gazel(cs)) { - printk(KERN_WARNING "Gazel: wrong IRQ\n"); - release_io_gazel(cs); - return (0); } - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &Gazel_card_msg; switch (cs->subtyp) { - case R647: - case R685: - cs->irq_func = &gazel_interrupt; - ISACVersion(cs, "Gazel:"); - if (HscxVersion(cs, "Gazel:")) { - printk(KERN_WARNING - "Gazel: wrong HSCX versions check IO address\n"); - release_io_gazel(cs); - return (0); - } - break; - case R742: - case R753: - cs->irq_func = &gazel_interrupt_ipac; - val = readreg_ipac(cs, IPAC_ID); - printk(KERN_INFO "Gazel: IPAC version %x\n", val); - break; + case R647: + case R685: + if (cs->subtyp == R647) { + cs->card_ops = &r647_ops; + if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) + goto err; + } else { + cs->card_ops = &r685_ops; + if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) + goto err; + } + cs->card_ops->reset(cs); + break; + case R742: + case R753: + if (cs->subtyp == R742) { + cs->card_ops = &r742_ops; + } else { + cs->card_ops = &r753_ops; + } + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + cs->card_ops->reset(cs); + break; } - return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c --- a/drivers/isdn/hisax/hfc_2bds0.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/hfc_2bds0.c Mon Jan 13 10:18:05 2003 @@ -824,10 +824,11 @@ } } -void +static int setstack_hfcd(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCD_l1hw; + return 0; } static void @@ -850,25 +851,30 @@ return(send); } +static struct bc_l1_ops hfcd_bc_l1_ops = { + .fill_fifo = hfc_fill_fifo, + .open = setstack_2b, + .close = close_2bs0, +}; + +static struct dc_l1_ops hfcd_dc_l1_ops = { + .fill_fifo = hfc_fill_dfifo, + .open = setstack_hfcd, + .bh_func = hfcd_bh, + .dbusy_func = hfc_dbusy_timer, +}; + void __init init2bds0(struct IsdnCardState *cs) { - cs->setstack_d = setstack_hfcd; - cs->dbusytimer.function = (void *) hfc_dbusy_timer; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); - INIT_WORK(&cs->work, hfcd_bh, cs); + dc_l1_init(cs, &hfcd_dc_l1_ops); + cs->bc_l1_ops = &hfcd_bc_l1_ops; if (!cs->hw.hfcD.send) cs->hw.hfcD.send = init_send_hfcd(16); if (!cs->bcs[0].hw.hfc.send) cs->bcs[0].hw.hfc.send = init_send_hfcd(32); if (!cs->bcs[1].hw.hfc.send) cs->bcs[1].hw.hfc.send = init_send_hfcd(32); - cs->DC_Send_Data = hfc_fill_dfifo; - cs->bcs[0].BC_SetStack = setstack_2b; - cs->bcs[1].BC_SetStack = setstack_2b; - cs->bcs[0].BC_Close = close_2bs0; - cs->bcs[1].BC_Close = close_2bs0; mode_2bs0(cs->bcs, 0, 0); mode_2bs0(cs->bcs + 1, 0, 1); } diff -Nru a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c --- a/drivers/isdn/hisax/hfc_2bs0.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/hfc_2bs0.c Mon Jan 13 10:18:05 2003 @@ -546,6 +546,8 @@ static struct bc_l1_ops hfc_l1_ops = { .fill_fifo = hfc_fill_fifo, + .open = setstack_hfc, + .close = close_hfcstate, }; void __init @@ -554,10 +556,6 @@ init_send(&cs->bcs[0]); init_send(&cs->bcs[1]); cs->bc_l1_ops = &hfc_l1_ops; - cs->bcs[0].BC_SetStack = setstack_hfc; - cs->bcs[1].BC_SetStack = setstack_hfc; - cs->bcs[0].BC_Close = close_hfcstate; - cs->bcs[1].BC_Close = close_hfcstate; mode_hfc(cs->bcs, 0, 0); mode_hfc(cs->bcs + 1, 0, 0); } @@ -573,4 +571,11 @@ kfree(cs->bcs[1].hw.hfc.send); cs->bcs[1].hw.hfc.send = NULL; } +} + +int +hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops) +{ + cs->bc_hw_ops = hfc_ops; + return 0; } diff -Nru a/drivers/isdn/hisax/hfc_2bs0.h b/drivers/isdn/hisax/hfc_2bs0.h --- a/drivers/isdn/hisax/hfc_2bs0.h Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/hfc_2bs0.h Mon Jan 13 10:18:05 2003 @@ -58,3 +58,4 @@ extern void main_irq_hfc(struct BCState *bcs); extern void inithfc(struct IsdnCardState *cs); extern void releasehfc(struct IsdnCardState *cs); +extern int hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops); diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c --- a/drivers/isdn/hisax/hfc_pci.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/hfc_pci.c Mon Jan 13 10:18:06 2003 @@ -65,13 +65,11 @@ }; -#if CONFIG_PCI - /******************************************/ /* free hardware resources used by driver */ /******************************************/ -void -release_io_hfcpci(struct IsdnCardState *cs) +static void +hfcpci_release(struct IsdnCardState *cs) { printk(KERN_INFO "HiSax: release hfcpci at %p\n", cs->hw.hfcpci.pci_io); @@ -83,16 +81,16 @@ Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ pci_disable_device(cs->hw.hfcpci.pdev); del_timer(&cs->hw.hfcpci.timer); - iounmap(cs->hw.hfcpci.pci_io); pci_free_consistent(cs->hw.hfcpci.pdev, 32768, cs->hw.hfcpci.fifos, cs->hw.hfcpci.fifos_dma); + hisax_release_resources(cs); } /********************************************************************************/ /* function called to reset the HFC PCI chip. A complete software reset of chip */ /* and fifos is done. */ /********************************************************************************/ -static void -reset_hfcpci(struct IsdnCardState *cs) +static int +hfcpci_reset(struct IsdnCardState *cs) { pci_disable_device(cs->hw.hfcpci.pdev); cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ @@ -159,6 +157,8 @@ cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); if (Read_hfc(cs, HFCPCI_INT_S2)); + + return 0; } /***************************************************/ @@ -1047,10 +1047,11 @@ /***********************************************/ /* called during init setting l1 stack pointer */ /***********************************************/ -void +static int setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCPCI_l1hw; + return 0; } /***************************************************************/ @@ -1335,8 +1336,17 @@ DChannel_proc_xmt(cs); } -static struct bc_l1_ops hfcpci_l1_ops = { +static struct bc_l1_ops hfcpci_bc_l1_ops = { .fill_fifo = hfcpci_fill_fifo, + .open = setstack_2b, + .close = close_hfcpci, +}; + +static struct dc_l1_ops hfcpci_dc_l1_ops = { + .fill_fifo = hfcpci_fill_dfifo, + .open = setstack_hfcpci, + .bh_func = hfcpci_bh, + .dbusy_func = hfcpci_dbusy_timer, }; /********************************/ @@ -1345,60 +1355,36 @@ void __init inithfcpci(struct IsdnCardState *cs) { - cs->setstack_d = setstack_hfcpci; - cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); - INIT_WORK(&cs->work, hfcpci_bh, cs); - cs->bc_l1_ops = &hfcpci_l1_ops; - cs->DC_Send_Data = hfcpci_fill_dfifo; - cs->bcs[0].BC_SetStack = setstack_2b; - cs->bcs[1].BC_SetStack = setstack_2b; - cs->bcs[0].BC_Close = close_hfcpci; - cs->bcs[1].BC_Close = close_hfcpci; + dc_l1_init(cs, &hfcpci_dc_l1_ops); + cs->bc_l1_ops = &hfcpci_bc_l1_ops; mode_hfcpci(cs->bcs, 0, 0); mode_hfcpci(cs->bcs + 1, 0, 1); } - - -/*******************************************/ -/* handle card messages from control layer */ -/*******************************************/ -static int -hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +hfcpci_init(struct IsdnCardState *cs) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFCPCI: card_msg %x", mt); - switch (mt) { - case CARD_RESET: - reset_hfcpci(cs); - return (0); - case CARD_RELEASE: - release_io_hfcpci(cs); - return (0); - case CARD_INIT: - inithfcpci(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ - /* now switch timer interrupt off */ - cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - /* reinit mode reg */ - Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); - return (0); - case CARD_TEST: - return (0); - } - return (0); + inithfcpci(cs); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + /* now switch timer interrupt off */ + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + /* reinit mode reg */ + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); } +static struct card_ops hfcpci_ops = { + .init = hfcpci_init, + .reset = hfcpci_reset, + .release = hfcpci_release, + .irq_func = hfcpci_interrupt, +}; + /* this variable is used as card index when more than one cards are present */ static struct pci_dev *dev_hfcpci __initdata = NULL; -#endif /* CONFIG_PCI */ - int __init setup_hfcpci(struct IsdnCard *card) { @@ -1409,86 +1395,78 @@ strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); -#if CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; - if (cs->typ == ISDN_CTYPE_HFC_PCI) { - i = 0; - while (id_list[i].vendor_id) { - tmp_hfcpci = pci_find_device(id_list[i].vendor_id, - id_list[i].device_id, - dev_hfcpci); - i++; - if (tmp_hfcpci) { - if (pci_enable_device(tmp_hfcpci)) - continue; - pci_set_master(tmp_hfcpci); - if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) - continue; - else - break; - } - } + i = 0; + while (id_list[i].vendor_id) { + tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + id_list[i].device_id, + dev_hfcpci); + i++; if (tmp_hfcpci) { - i--; - dev_hfcpci = tmp_hfcpci; /* old device */ - cs->irq = dev_hfcpci->irq; - cs->hw.hfcpci.pdev = tmp_hfcpci; - if (!cs->irq) { - printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); - return (0); - } - cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start; - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); - } else { - printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); - return (0); + if (pci_enable_device(tmp_hfcpci)) + continue; + pci_set_master(tmp_hfcpci); + if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) + continue; + else + break; } - if (!cs->hw.hfcpci.pci_io) { - printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); + } + + if (tmp_hfcpci) { + i--; + dev_hfcpci = tmp_hfcpci; /* old device */ + cs->irq = dev_hfcpci->irq; + cs->hw.hfcpci.pdev = tmp_hfcpci; + if (!cs->irq) { + printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); return (0); } - /* Allocate memory for FIFOS */ - cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma); - if (!cs->hw.hfcpci.fifos) { - printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); - return 0; - } - pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, - (u_int)cs->hw.hfcpci.fifos_dma); - cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); - printk(KERN_INFO - "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", - (u_int) cs->hw.hfcpci.pci_io, - (u_int) cs->hw.hfcpci.fifos, - (u_int) cs->hw.hfcpci.fifos_dma, - cs->irq, HZ); - printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); - cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcpci.int_m1 = 0; - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); - /* At this point the needed PCI config is done */ - /* fifos are still not enabled */ - } else - return (0); /* no valid card type */ - + printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); + } else { + printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); + return (0); + } + /* Allocate memory for FIFOS */ + cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma); + if (!cs->hw.hfcpci.fifos) { + printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); + return 0; + } + pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, + (u_int)cs->hw.hfcpci.fifos_dma); + cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci"); + if (!cs->hw.hfcpci.pci_io) + goto err; + + printk(KERN_INFO + "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", + (u_int) cs->hw.hfcpci.pci_io, + (u_int) cs->hw.hfcpci.fifos, + (u_int) cs->hw.hfcpci.fifos_dma, + cs->irq, HZ); + printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); + cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcpci.int_m1 = 0; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + /* At this point the needed PCI config is done */ + /* fifos are still not enabled */ - cs->irq_func = &hfcpci_interrupt; cs->irq_flags |= SA_SHIRQ; cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; cs->hw.hfcpci.timer.data = (long) cs; init_timer(&cs->hw.hfcpci.timer); - reset_hfcpci(cs); - cs->cardmsg = &hfcpci_card_msg; + hfcpci_reset(cs); cs->auxcmd = &hfcpci_auxcmd; - return (1); -#else - printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n"); - return (0); -#endif /* CONFIG_PCI */ + cs->card_ops = &hfcpci_ops; + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c --- a/drivers/isdn/hisax/hfc_sx.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/hfc_sx.c Mon Jan 13 10:18:05 2003 @@ -308,8 +308,8 @@ /******************************************/ /* free hardware resources used by driver */ /******************************************/ -void -release_io_hfcsx(struct IsdnCardState *cs) +static void +hfcsx_release(struct IsdnCardState *cs) { cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); @@ -318,7 +318,7 @@ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */ del_timer(&cs->hw.hfcsx.timer); - release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */ + hisax_release_resources(cs); kfree(cs->hw.hfcsx.extra); cs->hw.hfcsx.extra = NULL; } @@ -347,8 +347,8 @@ /* function called to reset the HFC SX chip. A complete software reset of chip */ /* and fifos is done. */ /********************************************************************************/ -static void -reset_hfcsx(struct IsdnCardState *cs) +static int +hfcsx_reset(struct IsdnCardState *cs) { cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); @@ -415,6 +415,7 @@ cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE; Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); if (Read_hfc(cs, HFCSX_INT_S2)); + return 0; } /***************************************************/ @@ -838,10 +839,11 @@ /***********************************************/ /* called during init setting l1 stack pointer */ /***********************************************/ -void +static int setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCSX_l1hw; + return 0; } /***************************************************************/ @@ -1112,8 +1114,17 @@ DChannel_proc_xmt(cs); } -static struct bc_l1_ops hfcsx_l1_ops = { +static struct bc_l1_ops hfcsx_bc_l1_ops = { .fill_fifo = hfcsx_fill_fifo, + .open = setstack_2b, + .close = close_hfcsx, +}; + +static struct dc_l1_ops hfcsx_dc_l1_ops = { + .fill_fifo = hfcsx_fill_dfifo, + .open = setstack_hfcsx, + .bh_func = hfcsx_bh, + .dbusy_func = hfcsx_dbusy_timer, }; /********************************/ @@ -1122,54 +1133,32 @@ void __devinit inithfcsx(struct IsdnCardState *cs) { - cs->setstack_d = setstack_hfcsx; - cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); - INIT_WORK(&cs->work, hfcsx_bh, cs); - cs->bc_l1_ops = &hfcsx_l1_ops; - cs->DC_Send_Data = hfcsx_fill_dfifo; - cs->bcs[0].BC_SetStack = setstack_2b; - cs->bcs[1].BC_SetStack = setstack_2b; - cs->bcs[0].BC_Close = close_hfcsx; - cs->bcs[1].BC_Close = close_hfcsx; + dc_l1_init(cs, &hfcsx_dc_l1_ops); + cs->bc_l1_ops = &hfcsx_bc_l1_ops; mode_hfcsx(cs->bcs, 0, 0); mode_hfcsx(cs->bcs + 1, 0, 1); } - - -/*******************************************/ -/* handle card messages from control layer */ -/*******************************************/ -static int -hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +hfcsx_init(struct IsdnCardState *cs) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFCSX: card_msg %x", mt); - switch (mt) { - case CARD_RESET: - reset_hfcsx(cs); - return (0); - case CARD_RELEASE: - release_io_hfcsx(cs); - return (0); - case CARD_INIT: - inithfcsx(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ - /* now switch timer interrupt off */ - cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - /* reinit mode reg */ - Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); - return (0); - case CARD_TEST: - return (0); - } - return (0); + inithfcsx(cs); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + /* now switch timer interrupt off */ + cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + /* reinit mode reg */ + Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); } +static struct card_ops hfcsx_ops = { + .init = hfcsx_init, + .reset = hfcsx_reset, + .release = hfcsx_release, + .irq_func = hfcsx_interrupt, +}; + #ifdef __ISAPNP__ static struct isapnp_device_id hfc_ids[] __initdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), @@ -1179,7 +1168,7 @@ }; static struct isapnp_device_id *hdev = &hfc_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit @@ -1192,29 +1181,38 @@ printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp)); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; while(hdev->card_vendor) { - if ((pb = isapnp_find_card(hdev->card_vendor, - hdev->card_device, pnp_c))) { + if ((pb = pnp_find_card(hdev->card_vendor, + hdev->card_device, + pnp_c))) { pnp_c = pb; pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - hdev->vendor, hdev->function, pd))) { + if ((pd = pnp_find_dev(pnp_c, + hdev->vendor, + hdev->function, + pd))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)hdev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = pd->resource[0].start; - card->para[0] = pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "HFC PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "HFC PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", - card->para[0], card->para[1]); - pd->deactivate(pd); + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); return(0); } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); @@ -1234,61 +1232,48 @@ cs->hw.hfcsx.int_s1 = 0; cs->dc.hfcsx.ph_state = 0; cs->hw.hfcsx.fifo = 255; - if ((cs->typ == ISDN_CTYPE_HFC_SX) || - (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) { - if ((!cs->hw.hfcsx.base) || - check_region((cs->hw.hfcsx.base), 2)) { - printk(KERN_WARNING - "HiSax: HFC-SX io-base %#lx already in use\n", - cs->hw.hfcsx.base); - return(0); - } else { - request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn"); - } - byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); - byteout(cs->hw.hfcsx.base + 1, - ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); - udelay(10); - cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); - switch (cs->hw.hfcsx.chip >> 4) { - case 1: - tmp[0] ='+'; - break; - case 9: - tmp[0] ='P'; - break; - default: - printk(KERN_WARNING - "HFC-SX: invalid chip id 0x%x\n", - cs->hw.hfcsx.chip >> 4); - release_region(cs->hw.hfcsx.base, 2); - return(0); - } - if (!ccd_sp_irqtab[cs->irq & 0xF]) { - printk(KERN_WARNING - "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF); - release_region(cs->hw.hfcsx.base, 2); - return(0); - } - if (!(cs->hw.hfcsx.extra = (void *) - kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) { - release_region(cs->hw.hfcsx.base, 2); - printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); - return(0); - } - - printk(KERN_INFO - "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", - tmp[0], (u_int) cs->hw.hfcsx.base, - cs->irq, HZ); - cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcsx.int_m1 = 0; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); - } else - return (0); /* no valid card type */ - cs->irq_func = &hfcsx_interrupt; + if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn")) + return 0; + byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); + byteout(cs->hw.hfcsx.base + 1, + ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); + udelay(10); + cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); + switch (cs->hw.hfcsx.chip >> 4) { + case 1: + tmp[0] ='+'; + break; + case 9: + tmp[0] ='P'; + break; + default: + printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", + cs->hw.hfcsx.chip >> 4); + hisax_release_resources(cs); + return 0; + } + if (!ccd_sp_irqtab[cs->irq & 0xF]) { + printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n", + cs->irq & 0xF); + hisax_release_resources(cs); + return 0; + } + cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), + GFP_ATOMIC); + if (!cs->hw.hfcsx.extra) { + hisax_release_resources(cs); + printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); + return 0; + } + + printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", + tmp[0], (u_int) cs->hw.hfcsx.base, + cs->irq, HZ); + cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcsx.int_m1 = 0; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; cs->hw.hfcsx.timer.data = (long) cs; @@ -1296,8 +1281,8 @@ cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */ init_timer(&cs->hw.hfcsx.timer); - reset_hfcsx(cs); - cs->cardmsg = &hfcsx_card_msg; + hfcsx_reset(cs); cs->auxcmd = &hfcsx_auxcmd; - return (1); + cs->card_ops = &hfcsx_ops; + return 1; } diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c --- a/drivers/isdn/hisax/hfcscard.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/hfcscard.c Mon Jan 13 10:18:07 2003 @@ -64,17 +64,16 @@ */ } -void -release_io_hfcs(struct IsdnCardState *cs) +static void +hfcs_release(struct IsdnCardState *cs) { release2bds0(cs); del_timer(&cs->hw.hfcD.timer); - if (cs->hw.hfcD.addr) - release_region(cs->hw.hfcD.addr, 2); + hisax_release_resources(cs); } -static void -reset_hfcs(struct IsdnCardState *cs) +static int +hfcs_reset(struct IsdnCardState *cs) { printk(KERN_INFO "HFCS: resetting card\n"); cs->hw.hfcD.cirm = HFCD_RESET; @@ -111,36 +110,29 @@ hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */ cs->hw.hfcD.sctrl = 0; hfcs_write_reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl); + return 0; } -static int -hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +hfcs_init(struct IsdnCardState *cs) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFCS: card_msg %x", mt); - switch (mt) { - case CARD_RESET: - reset_hfcs(cs); - return(0); - case CARD_RELEASE: - release_io_hfcs(cs); - return(0); - case CARD_INIT: - cs->hw.hfcD.timer.expires = jiffies + 75; - add_timer(&cs->hw.hfcD.timer); - init2bds0(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80*HZ)/1000); - cs->hw.hfcD.ctmt |= HFCD_TIM800; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); - hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); - return(0); - case CARD_TEST: - return(0); - } - return(0); + cs->hw.hfcD.timer.expires = jiffies + 75; + add_timer(&cs->hw.hfcD.timer); + init2bds0(cs); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80*HZ)/1000); + cs->hw.hfcD.ctmt |= HFCD_TIM800; + hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); + hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); } +static struct card_ops hfcs_ops = { + .init = hfcs_init, + .reset = hfcs_reset, + .release = hfcs_release, + .irq_func = hfcs_interrupt, +}; + #ifdef __ISAPNP__ static struct isapnp_device_id hfc_ids[] __initdata = { { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114), @@ -168,7 +160,7 @@ }; static struct isapnp_device_id *hdev = &hfc_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __init @@ -182,29 +174,38 @@ #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; while(hdev->card_vendor) { - if ((pb = isapnp_find_card(hdev->card_vendor, - hdev->card_device, pnp_c))) { + if ((pb = pnp_find_card(hdev->card_vendor, + hdev->card_device, + pnp_c))) { pnp_c = pb; pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - hdev->vendor, hdev->function, pd))) { + if ((pd = pnp_find_dev(pnp_c, + hdev->vendor, + hdev->function, + pd))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)hdev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = pd->resource[0].start; - card->para[0] = pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "HFC PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "HFC PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", - card->para[0], card->para[1]); - pd->deactivate(pd); + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); return(0); } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); @@ -235,16 +236,8 @@ cs->hw.hfcD.bfifosize = 7*1024 + 512; } else return (0); - if (check_region((cs->hw.hfcD.addr), 2)) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.hfcD.addr, - cs->hw.hfcD.addr + 2); - return (0); - } else { - request_region(cs->hw.hfcD.addr, 2, "HFCS isdn"); - } + if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn")) + return 0; printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d HZ %d\n", cs->hw.hfcD.addr, @@ -262,8 +255,7 @@ cs->hw.hfcD.timer.function = (void *) hfcs_Timer; cs->hw.hfcD.timer.data = (long) cs; init_timer(&cs->hw.hfcD.timer); - reset_hfcs(cs); - cs->cardmsg = &hfcs_card_msg; - cs->irq_func = &hfcs_interrupt; + hfcs_reset(cs); + cs->card_ops = &hfcs_ops; return (1); } diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h --- a/drivers/isdn/hisax/hisax.h Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/hisax.h Mon Jan 13 10:18:06 2003 @@ -6,6 +6,10 @@ * of the GNU General Public License, incorporated herein by reference. * */ + +#ifndef __HISAX_H__ +#define __HISAX_H__ + #include #include #include @@ -46,11 +50,6 @@ #define HW_INFO4_P10 0x0048 #define HW_RSYNC 0x0060 #define HW_TESTLOOP 0x0070 -#define CARD_RESET 0x00F0 -#define CARD_INIT 0x00F2 -#define CARD_RELEASE 0x00F3 -#define CARD_TEST 0x00F4 -#define CARD_AUX_IND 0x00F5 #define PH_ACTIVATE 0x0100 #define PH_DEACTIVATE 0x0110 @@ -68,14 +67,9 @@ #define DL_FLUSH 0x0224 #define DL_UNIT_DATA 0x0230 -#define MDL_BC_RELEASE 0x0278 // Formula-n enter:now -#define MDL_BC_ASSIGN 0x027C // Formula-n enter:now #define MDL_ASSIGN 0x0280 #define MDL_REMOVE 0x0284 #define MDL_ERROR 0x0288 -#define MDL_INFO_SETUP 0x02E0 -#define MDL_INFO_CONN 0x02E4 -#define MDL_INFO_REL 0x02E8 #define CC_SETUP 0x0300 #define CC_RESUME 0x0304 @@ -150,6 +144,35 @@ /* #define I4L_IRQ_FLAG SA_INTERRUPT */ #define I4L_IRQ_FLAG 0 +struct res { + struct list_head node; + const char *name; + unsigned long start, end; + unsigned long flags; + union { + void *ioremap_addr; + } r_u; +}; + +struct resources { + struct list_head res_head; +}; + +void +resources_init(struct resources *rs); + +void +resources_release(struct resources *rs); + +unsigned long +request_io(struct resources *rs, unsigned long start, int len, + const char *name); + +void * +request_mmio(struct resources *rs, unsigned long start, int len, + const char *name); + + /* * Statemachine */ @@ -349,17 +372,12 @@ }; struct hscx_hw { - int hscx; - int rcvidx; - u8 *rcvbuf; /* B-Channel receive Buffer */ u8 tsaxr0; u8 tsaxr1; }; struct w6692B_hw { int bchan; - int rcvidx; - u8 *rcvbuf; /* B-Channel receive Buffer */ }; struct isar_reg { @@ -407,8 +425,6 @@ struct hdlc_stat_reg sr; } ctrl; u_int stat; - int rcvidx; - u8 *rcvbuf; /* B-Channel receive Buffer */ }; struct hfcB_hw { @@ -479,10 +495,13 @@ struct BCState { int channel; int mode; - long Flag; /* long req'd for set_bit --RR */ + long Flag; struct IsdnCardState *cs; - int tx_cnt; /* B-Channel transmit counter */ - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ + int unit; /* first or second unit (e.g. HSCX) */ + int rcvidx; + u8 *rcvbuf; /* B-Channel receive Buffer */ + int tx_cnt; /* B-Channel transmit counter */ + struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ struct sk_buff_head rqueue; /* B-Channel receive queue */ struct sk_buff_head squeue; /* B-Channel send queue */ struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */ @@ -492,8 +511,6 @@ struct timer_list transbusy; struct work_struct work; unsigned long event; - int (*BC_SetStack) (struct PStack *, struct BCState *); - void (*BC_Close) (struct BCState *); #ifdef ERROR_STATISTIC int err_crc; int err_tx; @@ -570,8 +587,8 @@ struct teles0_hw { unsigned int cfg_reg; - unsigned long membase; unsigned long phymem; + void *membase; }; struct avm_hw { @@ -599,7 +616,6 @@ unsigned int isac; unsigned long hscx_adr; unsigned int hscx; - unsigned int status; struct timer_list tl; u8 ctrl_reg; }; @@ -661,6 +677,8 @@ unsigned char irqstat0; unsigned char last_is0; struct pci_dev *pdev; + void (*bc_activate)(struct IsdnCardState *cs, int bc); + void (*bc_deactivate)(struct IsdnCardState *cs, int bc); }; struct hfcPCI_hw { @@ -737,9 +755,8 @@ struct isurf_hw { unsigned int reset; - unsigned long phymem; - unsigned long isac; - unsigned long isar; + void *isac; + void *isar; struct isar_reg isar_r; }; @@ -861,6 +878,18 @@ struct IsdnCardState; +/* Methods provided by driver for a specific card */ + +struct card_ops { + void (*init) (struct IsdnCardState *); + void (*test) (struct IsdnCardState *); + int (*reset) (struct IsdnCardState *); + void (*release) (struct IsdnCardState *); + void (*aux_ind) (struct IsdnCardState *, void *); + void (*led_handler)(struct IsdnCardState *); + void (*irq_func) (int, void *, struct pt_regs *); +}; + /* Card specific drivers provide methods to access the * chips to the chip drivers */ @@ -878,10 +907,23 @@ void (*write_fifo) (struct IsdnCardState *, u8 *, int); }; -/* Methods provided to shared FIFO handling */ +/* Methods provided to shared B-channel FIFO handling */ struct bc_l1_ops { void (*fill_fifo) (struct BCState *); + int (*open) (struct PStack *, struct BCState *); + void (*close) (struct BCState *); +}; + +/* Methods provided to shared D-channel FIFO handling */ + +struct dc_l1_ops { + void (*fill_fifo) (struct IsdnCardState *); + int (*open) (struct PStack *, struct IsdnCardState *); + void (*close) (struct IsdnCardState *); + + void (*bh_func) (void *); + void (*dbusy_func) (struct IsdnCardState *); }; #define HW_IOM1 0 @@ -900,9 +942,12 @@ unsigned char typ; unsigned char subtyp; spinlock_t lock; + struct card_ops *card_ops; int protocol; + struct resources rs; unsigned int irq; unsigned long irq_flags; + int status; long HW_Flags; int *busy_flag; int chanlimit; /* limited number of B-chans to use */ @@ -942,12 +987,9 @@ u8 *status_end; struct dc_hw_ops *dc_hw_ops; struct bc_hw_ops *bc_hw_ops; + struct dc_l1_ops *dc_l1_ops; struct bc_l1_ops *bc_l1_ops; int (*cardmsg) (struct IsdnCardState *, int, void *); - void (*setstack_d) (struct PStack *, struct IsdnCardState *); - void (*DC_Send_Data) (struct IsdnCardState *); - void (*DC_Close) (struct IsdnCardState *); - void (*irq_func) (int, void *, struct pt_regs *); int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *); struct Channel channel[2+MAX_WAITING_CALLS]; struct BCState bcs[2+MAX_WAITING_CALLS]; @@ -979,6 +1021,9 @@ #endif }; +void +hisax_release_resources(struct IsdnCardState *cs); + #define MON0_RX 1 #define MON1_RX 2 #define MON0_TX 4 @@ -1363,9 +1408,6 @@ void LogFrame(struct IsdnCardState *cs, u8 * p, int size); void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir); void iecpy(u8 * dest, u8 * iestart, int ieoffset); -#ifdef ISDN_CHIP_ISAC -void setstack_isac(struct PStack *st, struct IsdnCardState *cs); -#endif /* ISDN_CHIP_ISAC */ #endif /* __KERNEL__ */ #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);} @@ -1424,3 +1466,6 @@ { st->l3.l4l3(st, pr, arg); } + + +#endif diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c --- a/drivers/isdn/hisax/hisax_fcpcipnp.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Mon Jan 13 10:18:07 2003 @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -46,6 +46,9 @@ MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver"); +// FIXME temporary hack until I sort out the new PnP stuff +#define __ISAPNP__ + static struct pci_device_id fcpci_ids[] __devinitdata = { { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1 , PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) "Fritz!Card PCI" }, @@ -55,13 +58,12 @@ }; MODULE_DEVICE_TABLE(pci, fcpci_ids); -static struct isapnp_device_id fcpnp_ids[] __devinitdata = { - { ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), - ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), - (unsigned long) "Fritz!Card PnP" }, - { } +static struct pnp_card_id fcpnp_ids[] __devinitdata = { + { .id = "AVM0900", + .driver_data = (unsigned long) "Fritz!Card PnP", + .devs = { { "AVM0900" } } } }; -MODULE_DEVICE_TABLE(isapnp, fcpnp_ids); +//MODULE_DEVICE_TABLE(pnpc, fcpnp_ids); FIXME static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); @@ -908,50 +910,54 @@ #ifdef __ISAPNP__ -static int __devinit fcpnp_probe(struct pci_dev *pdev, - const struct isapnp_device_id *ent) +static int __devinit fcpnp_probe(struct pnp_card *card, + const struct pnp_card_id *card_id) { struct fritz_adapter *adapter; + struct pnp_dev *pnp_dev; int retval; + retval = -ENODEV; + pnp_dev = pnp_request_card_device(card, card_id->devs[0].id, NULL); + if (!pnp_dev) + goto err; + + if (!pnp_port_valid(pnp_dev, 0) || !pnp_irq_valid(pnp_dev, 0)) + goto err; + retval = -ENOMEM; - adapter = new_adapter(pdev); + adapter = new_adapter((struct pci_dev *)pnp_dev); // FIXME if (!adapter) goto err; - + adapter->type = AVM_FRITZ_PNP; - - pdev->prepare(pdev); - pdev->deactivate(pdev); // why? - pdev->activate(pdev); - adapter->io = pdev->resource[0].start; - adapter->irq = pdev->irq_resource[0].start; - + adapter->io = pnp_port_start(pnp_dev, 0); + adapter->irq = pnp_irq(pnp_dev, 0); + printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n", - (char *) ent->driver_data, adapter->io, adapter->irq); - + (char *) card_id->driver_data, adapter->io, adapter->irq); + retval = fcpcipnp_setup(adapter); if (retval) - goto err_free; - + goto err_delete; + return 0; - err_free: + err_delete: delete_adapter(adapter); err: return retval; } -static void __devexit fcpnp_remove(struct pci_dev *pdev) +static void __devexit fcpnp_remove(struct pnp_card *pcard) { - struct fritz_adapter *adapter = pci_get_drvdata(pdev); + struct fritz_adapter *adapter = pnpc_get_drvdata(pcard); fcpcipnp_release(adapter); - pdev->deactivate(pdev); delete_adapter(adapter); } -static struct isapnp_driver fcpnp_driver = { +static struct pnpc_driver fcpnp_driver = { .name = "fcpnp", .probe = fcpnp_probe, .remove = __devexit_p(fcpnp_remove), @@ -972,7 +978,7 @@ pci_nr_found = retval; #ifdef __ISAPNP__ - retval = isapnp_register_driver(&fcpnp_driver); + retval = pnpc_register_driver(&fcpnp_driver); #else retval = 0; #endif @@ -990,7 +996,7 @@ #if !defined(CONFIG_HOTPLUG) || defined(MODULE) out_unregister_isapnp: #ifdef __ISAPNP__ - isapnp_unregister_driver(&fcpnp_driver); + pnpc_unregister_driver(&fcpnp_driver); #endif #endif out_unregister_pci: @@ -1002,7 +1008,7 @@ static void __exit hisax_fcpcipnp_exit(void) { #ifdef __ISAPNP__ - isapnp_unregister_driver(&fcpnp_driver); + pnpc_unregister_driver(&fcpnp_driver); #endif pci_unregister_driver(&fcpci_driver); } diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c --- a/drivers/isdn/hisax/hisax_hfcpci.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/hisax_hfcpci.c Mon Jan 13 10:18:05 2003 @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -1605,7 +1604,7 @@ static struct pci_driver hfcpci_driver = { .name = "hfcpci", .probe = hfcpci_probe, - .remove = hfcpci_remove, + .remove = __devexit_p(hfcpci_remove), .id_table = hfcpci_ids, }; diff -Nru a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c --- a/drivers/isdn/hisax/hscx.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/hscx.c Mon Jan 13 10:18:05 2003 @@ -25,39 +25,27 @@ hscx_read(struct BCState *bcs, u8 addr) { struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - return cs->bc_hw_ops->read_reg(cs, hscx, addr); + return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr); } static inline void hscx_write(struct BCState *bcs, u8 addr, u8 val) { struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - cs->bc_hw_ops->write_reg(cs, hscx, addr, val); -} - -static inline void -hscx_read_fifo(struct BCState *bcs, u8 *p, int len) -{ - struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - - cs->bc_hw_ops->read_fifo(cs, hscx, p, len); + cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val); } static inline void hscx_write_fifo(struct BCState *bcs, u8 *p, int len) { struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - cs->bc_hw_ops->write_fifo(cs, hscx, p, len); + cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len); } -int __init +static int HscxVersion(struct IsdnCardState *cs, char *s) { int verA, verB; @@ -67,16 +55,16 @@ printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s, HSCXVer[verA], HSCXVer[verB]); if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf)) - return (1); + return 1; else - return (0); + return 0; } void modehscx(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->hw.hscx.hscx; + int hscx = bcs->unit; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hscx %c mode %d ichan %d", @@ -164,52 +152,17 @@ close_hscxstate(struct BCState *bcs) { modehscx(bcs, 0, bcs->channel); - if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hscx.rcvbuf) { - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - skb_queue_purge(&bcs->cmpl_queue); - if (bcs->tx_skb) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - } - } + bc_close(bcs); } int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) { - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for hscx.rcvbuf\n"); - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); - return (1); - } - if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for bcs->blog\n"); - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - return (2); - } - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - skb_queue_head_init(&bcs->cmpl_queue); - } + bc_open(bcs); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; - bcs->hw.hscx.rcvidx = 0; + bcs->rcvidx = 0; bcs->tx_cnt = 0; return (0); } @@ -228,8 +181,12 @@ return (0); } +static void hscx_fill_fifo(struct BCState *bcs); + static struct bc_l1_ops hscx_l1_ops = { .fill_fifo = hscx_fill_fifo, + .open = setstack_hscx, + .close = close_hscxstate, }; void __init @@ -238,12 +195,8 @@ int val, eval; cs->bc_l1_ops = &hscx_l1_ops; - cs->bcs[0].BC_SetStack = setstack_hscx; - cs->bcs[1].BC_SetStack = setstack_hscx; - cs->bcs[0].BC_Close = close_hscxstate; - cs->bcs[1].BC_Close = close_hscxstate; - cs->bcs[0].hw.hscx.hscx = 0; - cs->bcs[1].hw.hscx.hscx = 1; + cs->bcs[0].unit = 0; + cs->bcs[1].unit = 1; cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; cs->bcs[0].hw.hscx.tsaxr1 = 3; cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; @@ -277,11 +230,24 @@ hscx_write(&cs->bcs[1], HSCX_MASK, 0x0); } -void __init +void inithscxisac(struct IsdnCardState *cs) { initisac(cs); inithscx(cs); +} + +int +hscxisac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops, + struct bc_hw_ops *hscx_ops) +{ + isac_setup(cs, isac_ops); + cs->bc_hw_ops = hscx_ops; + if (HscxVersion(cs, "HiSax:")) { + printk(KERN_WARNING "HiSax: invalid HSCX version\n"); + return -ENODEV; + } + return 0; } #include "hscx_irq.c" diff -Nru a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h --- a/drivers/isdn/hisax/hscx.h Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/hscx.h Mon Jan 13 10:18:06 2003 @@ -34,8 +34,10 @@ #define HSCX_RLCR 0x2e #define HSCX_MASK 0x20 -extern int HscxVersion(struct IsdnCardState *cs, char *s); extern void modehscx(struct BCState *bcs, int mode, int bc); extern void inithscxisac(struct IsdnCardState *cs); extern void hscx_int_main(struct IsdnCardState *cs, u8 val); -extern void hscx_fill_fifo(struct BCState *bcs); +extern void hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs); +extern int hscxisac_setup(struct IsdnCardState *cs, + struct dc_hw_ops *isac_ops, + struct bc_hw_ops *hscx_ops); diff -Nru a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c --- a/drivers/isdn/hisax/hscx_irq.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/hscx_irq.c Mon Jan 13 10:18:07 2003 @@ -26,7 +26,7 @@ } -static inline void +static void waitforXFW(struct BCState *bcs) { int to = 50; @@ -50,71 +50,25 @@ static void hscx_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr; - struct IsdnCardState *cs = bcs->cs; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "hscx_empty_fifo"); - - if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "hscx_empty_fifo: incoming packet too large"); - WriteHSCXCMDR(bcs, 0x80); - bcs->hw.hscx.rcvidx = 0; - return; - } - ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; - bcs->hw.hscx.rcvidx += count; - hscx_read_fifo(bcs, ptr, count); + recv_empty_fifo_b(bcs, count); WriteHSCXCMDR(bcs, 0x80); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "hscx_empty_fifo %c cnt %d", - bcs->hw.hscx.hscx ? 'B' : 'A', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } } -void +static void hscx_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; int more, count; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; - u8 *ptr; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "hscx_fill_fifo"); + u8 *p; - if (!bcs->tx_skb) - return; - if (bcs->tx_skb->len <= 0) + p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); + if (!p) return; - more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; - if (bcs->tx_skb->len > fifo_size) { - more = !0; - count = fifo_size; - } else - count = bcs->tx_skb->len; - waitforXFW(bcs); - ptr = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, count); - bcs->tx_cnt -= count; - bcs->count += count; - hscx_write_fifo(bcs, ptr, count); + hscx_write_fifo(bcs, p, count); WriteHSCXCMDR(bcs, more ? 0x8 : 0xa); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "hscx_fill_fifo %c cnt %d", - bcs->hw.hscx.hscx ? 'B' : 'A', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } } static inline void @@ -122,7 +76,6 @@ { u8 r; struct BCState *bcs = cs->bcs + hscx; - struct sk_buff *skb; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; int count; @@ -155,39 +108,19 @@ #endif } WriteHSCXCMDR(bcs, 0x80); + bcs->rcvidx = 0; } else { - count = hscx_read(bcs, HSCX_RBCL) & ( - test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); + count = hscx_read(bcs, HSCX_RBCL) & (fifo_size-1); if (count == 0) count = fifo_size; + hscx_empty_fifo(bcs, count); - if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { - if (cs->debug & L1_DEB_HSCX_FIFO) - debugl1(cs, "HX Frame %d", count); - if (!(skb = dev_alloc_skb(count))) - printk(KERN_WARNING "HSCX: receive out of memory\n"); - else { - memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); - skb_queue_tail(&bcs->rqueue, skb); - } - } + recv_rme_b(bcs); } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ hscx_empty_fifo(bcs, fifo_size); - if (bcs->mode == L1_MODE_TRANS) { - /* receive audio data */ - if (!(skb = dev_alloc_skb(fifo_size))) - printk(KERN_WARNING "HiSax: receive out of memory\n"); - else { - memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); - skb_queue_tail(&bcs->rqueue, skb); - } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); - } + recv_rpf_b(bcs); } if (val & 0x10) { xmit_xpr_b(bcs); @@ -203,11 +136,9 @@ void hscx_int_main(struct IsdnCardState *cs, u8 val) { - u8 exval; struct BCState *bcs; - spin_lock(&cs->lock); if (val & 0x01) { bcs = cs->bcs + 1; exval = hscx_read(bcs, HSCX_EXIR); @@ -238,5 +169,57 @@ debugl1(cs, "HSCX A interrupt %x", exval); hscx_interrupt(cs, exval, 0); } +} + +/* ====================================================================== */ + +static inline u8 +isac_read(struct IsdnCardState *cs, u8 addr) +{ + return cs->dc_hw_ops->read_reg(cs, addr); +} + +static inline void +isac_write(struct IsdnCardState *cs, u8 addr, u8 val) +{ + cs->dc_hw_ops->write_reg(cs, addr, val); +} + +void +hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u8 val; + int count = 0; + + spin_lock(&cs->lock); + val = hscx_read(&cs->bcs[1], HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = isac_read(cs, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = hscx_read(&cs->bcs[1], HSCX_ISTA); + if (val && count < 5) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = isac_read(cs, ISAC_ISTA); + if (val && count < 5) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF); + hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF); + isac_write(cs, ISAC_MASK, 0xFF); + isac_write(cs, ISAC_MASK, 0x0); + hscx_write(&cs->bcs[0], HSCX_MASK, 0x0); + hscx_write(&cs->bcs[1], HSCX_MASK, 0x0); spin_unlock(&cs->lock); } + diff -Nru a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c --- a/drivers/isdn/hisax/icc.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/icc.c Mon Jan 13 10:18:05 2003 @@ -23,7 +23,6 @@ #define DBUSY_TIMER_VALUE 80 #define ARCOFI_USE 0 -static spinlock_t icc_lock = SPIN_LOCK_UNLOCKED; static inline u8 icc_read_reg(struct IsdnCardState *cs, u8 addr) @@ -52,7 +51,7 @@ static char *ICCVer[] __initdata = {"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"}; -void +static void ICCVersion(struct IsdnCardState *cs, char *s) { int val; @@ -137,33 +136,8 @@ void icc_empty_fifo(struct IsdnCardState *cs, int count) { - u8 *ptr; - unsigned long flags; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, "icc_empty_fifo"); - - if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "icc_empty_fifo overrun %d", - cs->rcvidx + count); - icc_write_reg(cs, ICC_CMDR, 0x80); - cs->rcvidx = 0; - return; - } - ptr = cs->rcvbuf + cs->rcvidx; - cs->rcvidx += count; - spin_lock_irqsave(&icc_lock, flags); - icc_read_fifo(cs, ptr, count); + recv_empty_fifo_d(cs, count); icc_write_reg(cs, ICC_CMDR, 0x80); - spin_unlock_irqrestore(&icc_lock, flags); - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "icc_empty_fifo cnt %d", count); - QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); - } } static void @@ -171,13 +145,11 @@ { int count, more; unsigned char *p; - unsigned long flags; p = xmit_fill_fifo_d(cs, 32, &count, &more); if (!p) return; - spin_lock_irqsave(&icc_lock, flags); icc_write_fifo(cs, p, count); icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { @@ -187,16 +159,13 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); - spin_unlock_irqrestore(&icc_lock, flags); } void icc_interrupt(struct IsdnCardState *cs, u8 val) { u8 exval, v1; - struct sk_buff *skb; unsigned int count; - unsigned long flags; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC interrupt %x", val); @@ -218,25 +187,14 @@ #endif } icc_write_reg(cs, ICC_CMDR, 0x80); + cs->rcvidx = 0; } else { count = icc_read_reg(cs, ICC_RBCL) & 0x1f; if (count == 0) count = 32; icc_empty_fifo(cs, count); - spin_lock_irqsave(&icc_lock, flags); - if ((count = cs->rcvidx) > 0) { - cs->rcvidx = 0; - if (!(skb = alloc_skb(count, GFP_ATOMIC))) - printk(KERN_WARNING "HiSax: D receive out of memory\n"); - else { - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - } - } - spin_unlock_irqrestore(&icc_lock, flags); + recv_rme_d(cs); } - cs->rcvidx = 0; - sched_d_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ icc_empty_fifo(cs, 32); @@ -485,10 +443,11 @@ } } -void +static int setstack_icc(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = ICC_l1hw; + return 0; } void @@ -534,25 +493,27 @@ debugl1(cs, "D-Channel Busy no skb"); } icc_write_reg(cs, ICC_CMDR, 0x01); /* Transmitter reset */ - cs->irq_func(cs->irq, cs, NULL); + cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ } } } +static struct dc_l1_ops icc_l1_ops = { + .fill_fifo = icc_fill_fifo, + .open = setstack_icc, + .close = DC_Close_icc, + .bh_func = icc_bh, + .dbusy_func = dbusy_timer_handler, +}; + void __init initicc(struct IsdnCardState *cs) { int val, eval; - INIT_WORK(&cs->work, icc_bh, cs); - cs->setstack_d = setstack_icc; - cs->DC_Send_Data = icc_fill_fifo; - cs->DC_Close = DC_Close_icc; + dc_l1_init(cs, &icc_l1_ops); cs->dc.icc.mon_tx = NULL; cs->dc.icc.mon_rx = NULL; - cs->dbusytimer.function = (void *) dbusy_timer_handler; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); val = icc_read_reg(cs, ICC_STAR); debugl1(cs, "ICC STAR %x", val); @@ -596,4 +557,12 @@ ph_command(cs, ICC_CMD_RES); icc_write_reg(cs, ICC_MASK, 0x0); ph_command(cs, ICC_CMD_DI); +} + +int +icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops) +{ + cs->dc_hw_ops = icc_ops; + ICCVersion(cs, "HiSax:"); + return 0; } diff -Nru a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h --- a/drivers/isdn/hisax/icc.h Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/icc.h Mon Jan 13 10:18:07 2003 @@ -65,6 +65,6 @@ #define ICC_IND_AIL 0xE #define ICC_IND_DC 0xF -extern void ICCVersion(struct IsdnCardState *cs, char *s); +extern int icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops); extern void initicc(struct IsdnCardState *cs); extern void icc_interrupt(struct IsdnCardState *cs, u8 val); diff -Nru a/drivers/isdn/hisax/ipac.c b/drivers/isdn/hisax/ipac.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/ipac.c Mon Jan 13 10:18:07 2003 @@ -0,0 +1,105 @@ +#include "hisax.h" +#include "isdnl1.h" +#include "ipac.h" +#include "hscx.h" +#include "isac.h" + +static inline u8 +ipac_dc_read(struct IsdnCardState *cs, u8 addr) +{ + return cs->dc_hw_ops->read_reg(cs, addr); +} + +static inline void +ipac_dc_write(struct IsdnCardState *cs, u8 addr, u8 val) +{ + cs->dc_hw_ops->write_reg(cs, addr, val); +} + +static inline u8 +ipac_bc_read(struct IsdnCardState *cs, int hscx, u8 addr) +{ + return cs->bc_hw_ops->read_reg(cs, hscx, addr); +} + +static inline void +ipac_bc_write(struct IsdnCardState *cs, int hscx, u8 addr, u8 val) +{ + cs->bc_hw_ops->write_reg(cs, hscx, addr, val); +} + +static inline u8 +ipac_read(struct IsdnCardState *cs, u8 offset) +{ + return ipac_dc_read(cs, offset - 0x80); +} + +static inline void +ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +{ + ipac_dc_write(cs, offset - 0x80, value); +} + +void +ipac_init(struct IsdnCardState *cs) +{ + set_bit(HW_IPAC, &cs->HW_Flags); + inithscxisac(cs); +} + +void +ipac_irq(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u8 ista, val, icnt = 5; + + spin_lock(&cs->lock); + ista = ipac_read(cs, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = ipac_bc_read(cs, 1, HSCX_ISTA); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe; + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = ipac_read(cs, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "IRQ LOOP\n"); + + ipac_write(cs, IPAC_MASK, 0xFF); + ipac_write(cs, IPAC_MASK, 0xC0); + spin_unlock(&cs->lock); +} + +int +ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops, + struct bc_hw_ops *ipac_bc_ops) +{ + u8 val; + + cs->dc_hw_ops = ipac_dc_ops; + cs->bc_hw_ops = ipac_bc_ops; + val = ipac_read(cs, IPAC_ID); + printk(KERN_INFO "HiSax: IPAC version %#x\n", val); +} diff -Nru a/drivers/isdn/hisax/ipac.h b/drivers/isdn/hisax/ipac.h --- a/drivers/isdn/hisax/ipac.h Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/ipac.h Mon Jan 13 10:18:07 2003 @@ -27,3 +27,76 @@ #define IPAC_PCFG 0xCA #define IPAC_SCFG 0xCB #define IPAC_TIMR2 0xCC + +void ipac_init(struct IsdnCardState *cs); +void ipac_irq(int intno, void *dev_id, struct pt_regs *regs); +int ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops, + struct bc_hw_ops *ipac_bc_ops); + +/* Macro to build the needed D- and B-Channel access routines given + * access functions for the IPAC */ + +#define BUILD_IPAC_OPS(ipac) \ + \ +static u8 \ +ipac ## _dc_read(struct IsdnCardState *cs, u8 offset) \ +{ \ + return ipac ## _read(cs, offset+0x80); \ +} \ + \ +static void \ +ipac ## _dc_write(struct IsdnCardState *cs, u8 offset, u8 value) \ +{ \ + ipac ## _write(cs, offset+0x80, value); \ +} \ + \ +static void \ +ipac ## _dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size) \ +{ \ + ipac ## _readfifo(cs, 0x80, data, size); \ +} \ + \ +static void \ +ipac ## _dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size) \ +{ \ + ipac ## _writefifo(cs, 0x80, data, size); \ +} \ + \ +static struct dc_hw_ops ipac ## _dc_ops = { \ + .read_reg = ipac ## _dc_read, \ + .write_reg = ipac ## _dc_write, \ + .read_fifo = ipac ## _dc_read_fifo, \ + .write_fifo = ipac ## _dc_write_fifo, \ +}; \ + \ +static u8 \ +ipac ## _bc_read(struct IsdnCardState *cs, int hscx, u8 offset) \ +{ \ + return ipac ## _read(cs, offset + (hscx ? 0x40 : 0)); \ +} \ + \ +static void \ +ipac ## _bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) \ +{ \ + ipac ## _write(cs, offset + (hscx ? 0x40 : 0), value); \ +} \ + \ +static void \ +ipac ## _bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) \ +{ \ + ipac ## _readfifo(cs, hscx ? 0x40 : 0, data, size); \ +} \ + \ +static void \ +ipac ## _bc_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)\ +{ \ + ipac ## _writefifo(cs, hscx ? 0x40 : 0, data, size); \ +} \ + \ +static struct bc_hw_ops ipac ## _bc_ops = { \ + .read_reg = ipac ## _bc_read, \ + .write_reg = ipac ## _bc_write, \ + .read_fifo = ipac ## _bc_read_fifo, \ + .write_fifo = ipac ## _bc_write_fifo, \ +} + diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c --- a/drivers/isdn/hisax/ipacx.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/ipacx.c Mon Jan 13 10:18:06 2003 @@ -41,10 +41,8 @@ static void dch_empty_fifo(struct IsdnCardState *cs, int count); static void dch_fill_fifo(struct IsdnCardState *cs); static inline void dch_int(struct IsdnCardState *cs); -static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs); -static void __devinit dch_init(struct IsdnCardState *cs); static void bch_l2l1(struct PStack *st, int pr, void *arg); -static void bch_empty_fifo(struct BCState *bcs, int count); +static void ipacx_bc_empty_fifo(struct BCState *bcs, int count); static void bch_int(struct IsdnCardState *cs, u8 hscx); static void bch_mode(struct BCState *bcs, int mode, int bc); static void bch_close_state(struct BCState *bcs); @@ -57,18 +55,16 @@ ipacx_bc_read_reg(struct BCState *bcs, u8 addr) { struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - return cs->bc_hw_ops->read_reg(cs, hscx, addr); + return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr); } static inline void ipacx_bc_write_reg(struct BCState *bcs, u8 addr, u8 val) { struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - cs->bc_hw_ops->write_reg(cs, hscx, addr, val); + cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val); } static inline u8 @@ -305,33 +301,8 @@ static void dch_empty_fifo(struct IsdnCardState *cs, int count) { - u8 *ptr; - - if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) - debugl1(cs, "dch_empty_fifo()"); - - // message too large, remove - if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { - if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_empty_fifo() incoming message too large"); - ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC - cs->rcvidx = 0; - return; - } - - ptr = cs->rcvbuf + cs->rcvidx; - cs->rcvidx += count; - - ipacx_read_fifo(cs, ptr, count); + recv_empty_fifo_d(cs, count); ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC - - if (cs->debug &L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "dch_empty_fifo() cnt %d", count); - QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); - } } //---------------------------------------------------------- @@ -372,7 +343,6 @@ static inline void dch_int(struct IsdnCardState *cs) { - struct sk_buff *skb; u8 istad, rstad; int count; @@ -383,32 +353,25 @@ if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if (!(rstad &0x80)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): invalid frame"); + debugl1(cs, "dch_int(): invalid frame"); if ((rstad &0x40)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): RDO"); + debugl1(cs, "dch_int(): RDO"); if (!(rstad &0x20)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): CRC error"); - ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC + debugl1(cs, "dch_int(): CRC error"); + ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC + cs->rcvidx = 0; } else { // received frame ok count = ipacx_read_reg(cs, IPACX_RBCLD); - if (count) count--; // RSTAB is last byte + // FIXME this looks flaky + if (count) count--; // RSTAB is last byte count &= D_FIFO_SIZE-1; - if (count == 0) count = D_FIFO_SIZE; + if (count == 0) + count = D_FIFO_SIZE; dch_empty_fifo(cs, count); - if ((count = cs->rcvidx) > 0) { - cs->rcvidx = 0; - if (!(skb = dev_alloc_skb(count))) - printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n"); - else { - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - } - } - } - cs->rcvidx = 0; - sched_d_event(cs, D_RCVBUFREADY); + recv_rme_d(cs); + } } if (istad &0x40) { // RPF @@ -431,12 +394,20 @@ //---------------------------------------------------------- //---------------------------------------------------------- -static void __devinit +static int dch_setstack(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = dch_l2l1; + return 0; } +static struct dc_l1_ops ipacx_dc_l1_ops = { + .fill_fifo = dch_fill_fifo, + .open = dch_setstack, + .bh_func = dch_bh, + .dbusy_func = dbusy_timer_handler, +}; + //---------------------------------------------------------- //---------------------------------------------------------- static void __devinit @@ -444,17 +415,12 @@ { printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n"); - INIT_WORK(&cs->work, dch_bh, cs); - cs->setstack_d = dch_setstack; - cs->DC_Send_Data = dch_fill_fifo; - cs->dbusytimer.function = (void *) dbusy_timer_handler; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); + dc_l1_init(cs, &ipacx_dc_l1_ops); - ipacx_write_reg(cs, IPACX_TR_CONF0, 0x00); // clear LDD - ipacx_write_reg(cs, IPACX_TR_CONF2, 0x00); // enable transmitter - ipacx_write_reg(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go - ipacx_write_reg(cs, IPACX_MON_CR, 0x00); // disable monitor channel + ipacx_write_reg(cs, IPACX_TR_CONF0, 0x00); // clear LDD + ipacx_write_reg(cs, IPACX_TR_CONF2, 0x00); // enable transmitter + ipacx_write_reg(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go + ipacx_write_reg(cs, IPACX_MON_CR, 0x00); // disable monitor channel } @@ -501,49 +467,17 @@ // Read B channel fifo to receive buffer //---------------------------------------------------------- static void -bch_empty_fifo(struct BCState *bcs, int count) +ipacx_bc_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr, hscx; - struct IsdnCardState *cs; - int cnt; - - cs = bcs->cs; - hscx = bcs->hw.hscx.hscx; - if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) - debugl1(cs, "bch_empty_fifo()"); - - // message too large, remove - if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { - if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_empty_fifo() incoming packet too large"); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC - bcs->hw.hscx.rcvidx = 0; - return; - } - - // Read data uninterruptible - ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; - cnt = count; - while (cnt--) *ptr++ = ipacx_bc_read_reg(bcs, IPACX_RFIFOB); + recv_empty_fifo_b(bcs, count); ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC - - ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; - bcs->hw.hscx.rcvidx += count; - - if (cs->debug &L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } } //---------------------------------------------------------- // Fill buffer to transmit FIFO //---------------------------------------------------------- -void -ipacx_fill_fifo(struct BCState *bcs) +static void +ipacx_bc_fill_fifo(struct BCState *bcs) { int more, count; unsigned char *p; @@ -573,7 +507,6 @@ { u8 istab; struct BCState *bcs; - struct sk_buff *skb; int count; u8 rstab; @@ -586,48 +519,28 @@ if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if (!(rstab &0x80)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: invalid frame", hscx); + debugl1(cs, "bch_int() B-%d: invalid frame", hscx); if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); + debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); if (!(rstab &0x20)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: CRC error", hscx); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC - } - else { // received frame ok + debugl1(cs, "bch_int() B-%d: CRC error", hscx); + ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC + bcs->rcvidx = 0; + } else { // received frame ok count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1); - if (count == 0) count = B_FIFO_SIZE; - bch_empty_fifo(bcs, count); - if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { - if (cs->debug &L1_DEB_HSCX_FIFO) - debugl1(cs, "bch_int Frame %d", count); - if (!(skb = dev_alloc_skb(count))) - printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n"); - else { - memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); - skb_queue_tail(&bcs->rqueue, skb); - } - } + if (count == 0) + count = B_FIFO_SIZE; + + ipacx_bc_empty_fifo(bcs, count); + recv_rme_b(bcs); } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); } if (istab &0x40) { // RPF - bch_empty_fifo(bcs, B_FIFO_SIZE); - - if (bcs->mode == L1_MODE_TRANS) { // queue every chunk - // receive transparent audio data - if (!(skb = dev_alloc_skb(B_FIFO_SIZE))) - printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n"); - else { - memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE); - skb_queue_tail(&bcs->rqueue, skb); - } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); - } + ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE); + recv_rpf_b(bcs); } if (istab &0x20) { // RFO @@ -651,7 +564,7 @@ bch_mode(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->hw.hscx.hscx; + int hscx = bcs->unit; bc = bc ? 1 : 0; // in case bc is greater than 1 if (cs->debug & L1_DEB_HSCX) @@ -699,23 +612,7 @@ bch_close_state(struct BCState *bcs) { bch_mode(bcs, 0, bcs->channel); - if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hscx.rcvbuf) { - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - if (bcs->tx_skb) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - clear_bit(BC_FLG_BUSY, &bcs->Flag); - } - } + bc_close(bcs); } //---------------------------------------------------------- @@ -723,30 +620,7 @@ static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) { - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax open_bchstate(): No memory for hscx.rcvbuf\n"); - clear_bit(BC_FLG_INIT, &bcs->Flag); - return (1); - } - if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax open_bchstate: No memory for bcs->blog\n"); - clear_bit(BC_FLG_INIT, &bcs->Flag); - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - return (2); - } - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - } - bcs->tx_skb = NULL; - clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->event = 0; - bcs->hw.hscx.rcvidx = 0; - bcs->tx_cnt = 0; - return (0); + return bc_open(bcs); } //---------------------------------------------------------- @@ -769,9 +643,7 @@ static void __devinit bch_init(struct IsdnCardState *cs, int hscx) { - cs->bcs[hscx].BC_SetStack = bch_setstack; - cs->bcs[hscx].BC_Close = bch_close_state; - cs->bcs[hscx].hw.hscx.hscx = hscx; + cs->bcs[hscx].unit = hscx; cs->bcs[hscx].cs = cs; bch_mode(cs->bcs + hscx, 0, hscx); } @@ -821,7 +693,9 @@ } static struct bc_l1_ops ipacx_bc_l1_ops = { - .fill_fifo = ipacx_fill_fifo, + .fill_fifo = ipacx_bc_fill_fifo, + .open = bch_setstack, + .close = bch_close_state, }; //---------------------------------------------------------- @@ -852,5 +726,15 @@ } } -//----------------- end of file ----------------------- +int +ipacx_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipacx_dc_ops, + struct bc_hw_ops *ipacx_bc_ops) +{ + u8 val; + + cs->dc_hw_ops = ipacx_dc_ops; + cs->bc_hw_ops = ipacx_bc_ops; + val = ipacx_read_reg(cs, IPACX_ID) & 0x3f; + printk(KERN_INFO "HiSax: IPACX Design Id: %#x\n", val); +} diff -Nru a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h --- a/drivers/isdn/hisax/ipacx.h Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/ipacx.h Mon Jan 13 10:18:05 2003 @@ -157,6 +157,8 @@ extern void init_ipacx(struct IsdnCardState *cs, int part); extern void interrupt_ipacx(struct IsdnCardState *cs); -extern void ipacx_fill_fifo(struct BCState *bcs); +extern int ipacx_setup(struct IsdnCardState *cs, + struct dc_hw_ops *ipacx_dc_ops, + struct bc_hw_ops *ipacx_bc_ops); #endif diff -Nru a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c --- a/drivers/isdn/hisax/isac.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/isac.c Mon Jan 13 10:18:05 2003 @@ -40,18 +40,12 @@ } static inline void -isac_read_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->read_fifo(cs, p, len); -} - -static inline void isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len) { return cs->dc_hw_ops->write_fifo(cs, p, len); } -void +static void ISACVersion(struct IsdnCardState *cs, char *s) { int val; @@ -140,30 +134,8 @@ void isac_empty_fifo(struct IsdnCardState *cs, int count) { - u8 *ptr; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, "isac_empty_fifo"); - - if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "isac_empty_fifo overrun %d", - cs->rcvidx + count); - isac_write(cs, ISAC_CMDR, 0x80); - cs->rcvidx = 0; - return; - } - ptr = cs->rcvbuf + cs->rcvidx; - cs->rcvidx += count; - isac_read_fifo(cs, ptr, count); + recv_empty_fifo_d(cs, count); isac_write(cs, ISAC_CMDR, 0x80); - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "isac_empty_fifo cnt %d", count); - QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); - } } static void @@ -191,7 +163,6 @@ isac_interrupt(struct IsdnCardState *cs, u8 val) { u8 exval, v1; - struct sk_buff *skb; unsigned int count; if (cs->debug & L1_DEB_ISAC) @@ -214,20 +185,13 @@ #endif } isac_write(cs, ISAC_CMDR, 0x80); + cs->rcvidx = 0; } else { count = isac_read(cs, ISAC_RBCL) & 0x1f; if (count == 0) count = 32; isac_empty_fifo(cs, count); - if ((count = cs->rcvidx) > 0) { - cs->rcvidx = 0; - if (!(skb = alloc_skb(count, GFP_ATOMIC))) - printk(KERN_WARNING "HiSax: D receive out of memory\n"); - else { - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - } - } + recv_rme_d(cs); } cs->rcvidx = 0; sched_d_event(cs, D_RCVBUFREADY); @@ -477,13 +441,14 @@ } } -void +static int setstack_isac(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = ISAC_l1hw; + return 0; } -void +static void DC_Close_isac(struct IsdnCardState *cs) { if (cs->dc.isac.mon_rx) { kfree(cs->dc.isac.mon_rx); @@ -526,16 +491,26 @@ debugl1(cs, "D-Channel Busy no skb"); } isac_write(cs, ISAC_CMDR, 0x01); /* Transmitter reset */ - cs->irq_func(cs->irq, cs, NULL); + cs->card_ops->irq_func(cs->irq, cs, NULL); } } } +static struct dc_l1_ops isac_l1_ops = { + .fill_fifo = isac_fill_fifo, + .open = setstack_isac, + .close = DC_Close_isac, + .bh_func = isac_bh, + .dbusy_func = dbusy_timer_handler, +}; + void __devinit initisac(struct IsdnCardState *cs) { int val, eval; + dc_l1_init(cs, &isac_l1_ops); + val = isac_read(cs, ISAC_STAR); debugl1(cs, "ISAC STAR %x", val); val = isac_read(cs, ISAC_MODE); @@ -551,16 +526,8 @@ /* Disable all IRQ */ isac_write(cs, ISAC_MASK, 0xFF); - INIT_WORK(&cs->work, isac_bh, cs); - cs->setstack_d = setstack_isac; - cs->DC_Send_Data = isac_fill_fifo; - cs->DC_Close = DC_Close_isac; cs->dc.isac.mon_tx = NULL; cs->dc.isac.mon_rx = NULL; - cs->dbusytimer.function = (void *) dbusy_timer_handler; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); - isac_write(cs, ISAC_MASK, 0xff); cs->dc.isac.mocr = 0xaa; if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ @@ -591,4 +558,12 @@ /* RESET Receiver and Transmitter */ isac_write(cs, ISAC_CMDR, 0x41); +} + +int +isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops) +{ + cs->dc_hw_ops = isac_ops; + ISACVersion(cs, "HiSax:"); + return 0; } diff -Nru a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h --- a/drivers/isdn/hisax/isac.h Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/isac.h Mon Jan 13 10:18:07 2003 @@ -63,6 +63,6 @@ #define ISAC_IND_AI10 0xD #define ISAC_IND_DID 0xF -extern void ISACVersion(struct IsdnCardState *cs, char *s); extern void initisac(struct IsdnCardState *cs); extern void isac_interrupt(struct IsdnCardState *cs, u8 val); +extern int isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops); diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c --- a/drivers/isdn/hisax/isar.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/isar.c Mon Jan 13 10:18:06 2003 @@ -25,7 +25,7 @@ const u8 faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; #define FAXMODCNT 13 -void isar_setup(struct IsdnCardState *cs); +static void __isar_setup(struct IsdnCardState *cs); static void isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para); static inline void ll_deliver_faxstat(struct BCState *bcs, u8 status); static spinlock_t isar_lock = SPIN_LOCK_UNLOCKED; @@ -165,7 +165,7 @@ return(1); } -int +static int ISARVersion(struct IsdnCardState *cs, char *s) { int ver; @@ -174,7 +174,7 @@ u8 len; int debug; - cs->cardmsg(cs, CARD_RESET, NULL); + cs->card_ops->reset(cs); /* disable ISAR IRQ */ isar_write_reg(cs, 0, ISAR_IRQBIT, 0); debug = cs->debug; @@ -420,7 +420,7 @@ } } cs->debug = debug; - isar_setup(cs); + __isar_setup(cs); ret = 0; reterror: cs->debug = debug; @@ -1531,7 +1531,7 @@ } void -isar_setup(struct IsdnCardState *cs) +__isar_setup(struct IsdnCardState *cs) { u8 msg; int i; @@ -1745,14 +1745,19 @@ static struct bc_l1_ops isar_l1_ops = { .fill_fifo = isar_fill_fifo, + .open = setstack_isar, + .close = close_isarstate, }; void __devinit initisar(struct IsdnCardState *cs) { cs->bc_l1_ops = &isar_l1_ops; - cs->bcs[0].BC_SetStack = setstack_isar; - cs->bcs[1].BC_SetStack = setstack_isar; - cs->bcs[0].BC_Close = close_isarstate; - cs->bcs[1].BC_Close = close_isarstate; +} + +int +isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops) +{ + cs->bc_hw_ops = isar_ops; + return ISARVersion(cs, "HiSax:"); } diff -Nru a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h --- a/drivers/isdn/hisax/isar.h Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/isar.h Mon Jan 13 10:18:05 2003 @@ -207,8 +207,8 @@ #define STFAX_ESCAPE 5 #define STFAX_SILDET 6 -extern int ISARVersion(struct IsdnCardState *cs, char *s); extern void isar_int_main(struct IsdnCardState *cs); extern void initisar(struct IsdnCardState *cs); extern void isar_fill_fifo(struct BCState *bcs); extern int isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic); +extern int isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops); diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c --- a/drivers/isdn/hisax/isdnl1.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/isdnl1.c Mon Jan 13 10:18:05 2003 @@ -358,8 +358,6 @@ bcs->cs = cs; bcs->channel = bc; INIT_WORK(&bcs->work, BChannel_bh, bcs); - bcs->BC_SetStack = NULL; - bcs->BC_Close = NULL; bcs->Flag = 0; } @@ -907,8 +905,18 @@ setstack_manager(st); st->l1.stlistp = &(cs->stlist); st->l1.l2l1 = dch_l2l1; - if (cs->setstack_d) - cs->setstack_d(st, cs); + if (cs->dc_l1_ops->open) + cs->dc_l1_ops->open(st, cs); +} + +void +dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops) +{ + cs->dc_l1_ops = ops; + INIT_WORK(&cs->work, ops->bh_func, cs); + init_timer(&cs->dbusytimer); + cs->dbusytimer.function = (void *)(unsigned long) ops->dbusy_func; + cs->dbusytimer.data = (unsigned long) cs; } void diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h --- a/drivers/isdn/hisax/isdnl1.h Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/isdnl1.h Mon Jan 13 10:18:07 2003 @@ -7,6 +7,9 @@ * */ +#ifndef __ISDNL1_H__ +#define __ISDNL1_H__ + #define D_RCVBUFREADY 0 #define D_XMTBUFREADY 1 #define D_L1STATECHANGE 2 @@ -31,12 +34,20 @@ extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg); extern void l1_msg_b(struct PStack *st, int pr, void *arg); +void dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops); + static inline void fill_fifo_b(struct BCState *bcs) { bcs->cs->bc_l1_ops->fill_fifo(bcs); } +static inline void +fill_fifo_d(struct IsdnCardState *cs) +{ + cs->dc_l1_ops->fill_fifo(cs); +} + #ifdef L2FRAME_DEBUG extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); #endif @@ -94,7 +105,7 @@ cs->tx_skb = skb_dequeue(&cs->sq); if (cs->tx_skb) { cs->tx_cnt = 0; - cs->DC_Send_Data(cs); + fill_fifo_d(cs); } else { sched_d_event(cs, D_XMTBUFREADY); } @@ -141,7 +152,7 @@ if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0); #endif - cs->DC_Send_Data(cs); + fill_fifo_d(cs); } spin_unlock_irqrestore(&cs->lock, flags); } @@ -183,7 +194,7 @@ #endif cs->tx_skb = skb; cs->tx_cnt = 0; - cs->DC_Send_Data(cs); + fill_fifo_d(cs); } spin_unlock_irqrestore(&cs->lock, flags); } @@ -296,7 +307,7 @@ if (cs->tx_skb) { /* last frame not done yet? */ if (cs->tx_skb->len) { - cs->DC_Send_Data(cs); + fill_fifo_d(cs); return; } xmit_complete_d(cs); @@ -372,7 +383,7 @@ char *t = bcs->blog; t += sprintf(t, "%s %c cnt %d", __FUNCTION__, - bcs->hw.hscx.hscx ? 'B' : 'A', *count); + bcs->unit ? 'B' : 'A', *count); QuickHex(t, p, *count); debugl1(cs, bcs->blog); } @@ -413,3 +424,174 @@ } return p; } + +static inline void +recv_empty_fifo_d(struct IsdnCardState *cs, int count) +{ + u8 *p; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, __FUNCTION__); + + if (cs->rcvidx + count > MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "%s: incoming packet too large", __FUNCTION__); + cs->rcvidx = 0; + return; + } + p = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + cs->dc_hw_ops->read_fifo(cs, p, count); + + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "%s cnt %d", __FUNCTION__, count); + QuickHex(t, p, count); + debugl1(cs, cs->dlog); + } +} + +static inline void +recv_empty_fifo_b(struct BCState *bcs, int count) +{ + u8 *p; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, __FUNCTION__); + + if (bcs->rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "%s: incoming packet too large", __FUNCTION__); + bcs->rcvidx = 0; + return; + } + p = bcs->rcvbuf + bcs->rcvidx; + bcs->rcvidx += count; + cs->bc_hw_ops->read_fifo(cs, bcs->unit, p, count); + + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "%s %c cnt %d", __FUNCTION__, + bcs->unit ? 'B' : 'A', count); + QuickHex(t, p, count); + debugl1(cs, bcs->blog); + } +} + +/* RME - receive message end */ +static inline void +recv_rme_d(struct IsdnCardState *cs) +{ + struct sk_buff *skb; + int count; + + count = cs->rcvidx - 1; + cs->rcvidx = 0; + if (count == 0) + return; + + skb = dev_alloc_skb(count); + if (!skb) { + printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); + return; + } + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + sched_d_event(cs, D_RCVBUFREADY); +} + +static inline void +recv_rme_b(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + struct sk_buff *skb; + int count; + + count = bcs->rcvidx - 1; + bcs->rcvidx = 0; + if (count == 0) + return; + + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + + skb = dev_alloc_skb(count); + if (!skb) { + printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); + return; + } + memcpy(skb_put(skb, count), bcs->rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + sched_b_event(bcs, B_RCVBUFREADY); +} + +/* RPF - receive pull full */ +static inline void +recv_rpf_b(struct BCState *bcs) +{ + if (bcs->mode != L1_MODE_TRANS) + return; + + recv_rme_b(bcs); +} + +static inline int +bc_open(struct BCState *bcs) +{ + if (test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) + return 0; + + bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC); + if (!bcs->rcvbuf) + goto err; + + bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC); + if (!bcs->blog) + goto err_rcvbuf; + + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + skb_queue_head_init(&bcs->cmpl_queue); + + clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = NULL; + bcs->rcvidx = 0; + bcs->tx_cnt = 0; + bcs->event = 0; + + return 0; + + err_rcvbuf: + kfree(bcs->rcvbuf); + err: + clear_bit(BC_FLG_INIT, &bcs->Flag); + printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); + return -ENOMEM;; +} + +static inline void +bc_close(struct BCState *bcs) +{ + if (!test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) + return; + + kfree(bcs->rcvbuf); + bcs->rcvbuf = NULL; + + kfree(bcs->blog); + bcs->blog = NULL; + + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + skb_queue_purge(&bcs->cmpl_queue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + clear_bit(BC_FLG_BUSY, &bcs->Flag); + } +} + +#endif diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c --- a/drivers/isdn/hisax/isurf.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/isurf.c Mon Jan 13 10:18:06 2003 @@ -132,14 +132,6 @@ spin_unlock(&cs->lock); } -void -release_io_isurf(struct IsdnCardState *cs) -{ - release_region(cs->hw.isurf.reset, 1); - iounmap((unsigned char *)cs->hw.isurf.isar); - release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); -} - static void reset_isurf(struct IsdnCardState *cs, u8 chips) { @@ -154,27 +146,6 @@ } static int -ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - reset_isurf(cs, ISURF_RESET); - return(0); - case CARD_RELEASE: - release_io_isurf(cs); - return(0); - case CARD_INIT: - writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb(); - initisac(cs); - initisar(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} - -static int isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { int ret; @@ -190,56 +161,82 @@ return(isar_auxcmd(cs, ic)); } +static void +isurf_init(struct IsdnCardState *cs) +{ + writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); + initisac(cs); + initisar(cs); +} + +static int +isurf_reset(struct IsdnCardState *cs) +{ + reset_isurf(cs, ISURF_RESET); + return 0; +} + +static struct card_ops isurf_ops = { + .init = isurf_init, + .reset = isurf_reset, + .release = hisax_release_resources, + .irq_func = isurf_interrupt, +}; + #ifdef __ISAPNP__ -static struct pci_bus *pnp_surf __devinitdata = NULL; +static struct pnp_card *pnp_surf __devinitdata = NULL; #endif int __init setup_isurf(struct IsdnCard *card) { - int ver; struct IsdnCardState *cs = card->cs; + unsigned long phymem; char tmp[64]; strcpy(tmp, ISurf_revision); printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_ISURF) - return(0); if (card->para[1] && card->para[2]) { cs->hw.isurf.reset = card->para[1]; - cs->hw.isurf.phymem = card->para[2]; + phymem = card->para[2]; cs->irq = card->para[0]; } else { #ifdef __ISAPNP__ - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; if (isapnp_present()) { cs->subtyp = 0; - if ((pb = isapnp_find_card( + if ((pb = pnp_find_card( ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0010), pnp_surf))) { pnp_surf = pb; pd = NULL; - if (!(pd = isapnp_find_dev(pnp_surf, + if (!(pd = pnp_find_dev(pnp_surf, ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0010), pd))) { printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); return (0); } - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - cs->hw.isurf.reset = pd->resource[0].start; - cs->hw.isurf.phymem = pd->resource[1].start; - cs->irq = pd->irq_resource[0].start; - if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) { - printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n", - cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem); - pd->deactivate(pd); + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "ISurfPnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "ISurfPnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { + printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n", + pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); + pnp_device_detach(pd); return(0); } + cs->hw.isurf.reset = pnp_port_start(pd, 0); + phymem = pnp_port_start(pd, 1); + cs->irq = pnp_irq(pd, 0); } else { printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); return(0); @@ -254,50 +251,31 @@ return (0); #endif } - if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) { - printk(KERN_WARNING - "HiSax: %s config port %x already in use\n", - CardType[card->typ], - cs->hw.isurf.reset); - return (0); - } - if (check_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE)) { - printk(KERN_WARNING - "HiSax: %s memory region %lx-%lx already in use\n", - CardType[card->typ], - cs->hw.isurf.phymem, - cs->hw.isurf.phymem + ISURF_IOMEM_SIZE); - release_region(cs->hw.isurf.reset, 1); - return (0); - } else { - request_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE, - "isurf iomem"); - } - cs->hw.isurf.isar = - (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); + if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn")) + goto err; + cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem"); + if (!cs->hw.isurf.isar) + goto err; + cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n", cs->hw.isurf.reset, - cs->hw.isurf.phymem, + card->para[2], cs->irq); - cs->cardmsg = &ISurf_card_msg; - cs->irq_func = &isurf_interrupt; cs->auxcmd = &isurf_auxcmd; - cs->dc_hw_ops = &isac_ops; + cs->card_ops = &isurf_ops; cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; reset_isurf(cs, ISURF_RESET); test_and_set_bit(HW_ISAR, &cs->HW_Flags); - ISACVersion(cs, "ISurf:"); - cs->bc_hw_ops = &isar_ops; - ver = ISARVersion(cs, "ISurf:"); - if (ver < 0) { - printk(KERN_WARNING - "ISurf: wrong ISAR version (ret = %d)\n", ver); - release_io_isurf(cs); - return (0); - } - return (1); + isac_setup(cs, &isac_ops); + if (isar_setup(cs, &isar_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; + } diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c --- a/drivers/isdn/hisax/ix1_micro.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/ix1_micro.c Mon Jan 13 10:18:07 2003 @@ -140,50 +140,7 @@ .write_fifo = hscx_write_fifo, }; -static void -ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 val; - - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); -} - -void -release_io_ix1micro(struct IsdnCardState *cs) -{ - if (cs->hw.ix1.cfg_reg) - release_region(cs->hw.ix1.cfg_reg, 4); -} - -static void +static int ix1_reset(struct IsdnCardState *cs) { int cnt; @@ -195,26 +152,15 @@ HZDELAY(1); /* wait >=10 ms */ } byteout(cs->hw.ix1.cfg_reg + SPECIAL_PORT_OFFSET, 0); + return 0; } -static int -ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - ix1_reset(cs); - return(0); - case CARD_RELEASE: - release_io_ix1micro(cs); - return(0); - case CARD_INIT: - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} +static struct card_ops ix1_ops = { + .init = inithscxisac, + .reset = ix1_reset, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; #ifdef __ISAPNP__ static struct isapnp_device_id itk_ids[] __initdata = { @@ -228,7 +174,7 @@ }; static struct isapnp_device_id *idev = &itk_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif @@ -240,34 +186,41 @@ strcpy(tmp, ix1_revision); printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_IX1MICROR2) - return (0); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; while(idev->card_vendor) { - if ((pb = isapnp_find_card(idev->card_vendor, - idev->card_device, pnp_c))) { + if ((pb = pnp_find_card(idev->card_vendor, + idev->card_device, + pnp_c))) { pnp_c = pb; pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - idev->vendor, idev->function, pd))) { + if ((pd = pnp_find_dev(pnp_c, + idev->vendor, + idev->function, + pd))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)idev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = pd->resource[0].start; - card->para[0] = pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "ITK PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "ITK PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_port_valid(pd, 0) || !pnp_irq_valid(pd, 0)) { printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n", - card->para[0], card->para[1]); - pd->deactivate(pd); + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); return(0); } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "ITK PnP: PnP error card found, no device\n"); @@ -288,32 +241,17 @@ cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; cs->hw.ix1.cfg_reg = card->para[1]; cs->irq = card->para[0]; - if (cs->hw.ix1.cfg_reg) { - if (check_region((cs->hw.ix1.cfg_reg), 4)) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.ix1.cfg_reg, - cs->hw.ix1.cfg_reg + 4); - return (0); - } else - request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"); - } - printk(KERN_INFO - "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.ix1.cfg_reg); + if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) + goto err; + + printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); ix1_reset(cs); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &ix1_card_msg; - cs->irq_func = &ix1micro_interrupt; - ISACVersion(cs, "ix1-Micro:"); - if (HscxVersion(cs, "ix1-Micro:")) { - printk(KERN_WARNING - "ix1-Micro: wrong HSCX versions check IO address\n"); - release_io_ix1micro(cs); - return (0); - } - return (1); + cs->card_ops = &ix1_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c --- a/drivers/isdn/hisax/jade.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/jade.c Mon Jan 13 10:18:05 2003 @@ -33,24 +33,14 @@ } static inline void -jade_read_fifo(struct BCState *bcs, u8 *p, int len) -{ - struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - - cs->bc_hw_ops->read_fifo(cs, hscx, p, len); -} - -static inline void jade_write_fifo(struct BCState *bcs, u8 *p, int len) { struct IsdnCardState *cs = bcs->cs; - u8 hscx = bcs->hw.hscx.hscx; - cs->bc_hw_ops->write_fifo(cs, hscx, p, len); + cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len); } -int __init +static int JadeVersion(struct IsdnCardState *cs, char *s) { int ver,i; @@ -112,7 +102,7 @@ modejade(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int jade = bcs->hw.hscx.hscx; + int jade = bcs->unit; if (cs->debug & L1_DEB_HSCX) { char tmp[40]; @@ -199,53 +189,14 @@ void close_jadestate(struct BCState *bcs) { - modejade(bcs, 0, bcs->channel); - if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hscx.rcvbuf) { - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - if (bcs->tx_skb) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - } - } + modejade(bcs, 0, bcs->channel); + bc_close(bcs); } static int open_jadestate(struct IsdnCardState *cs, struct BCState *bcs) { - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for hscx.rcvbuf\n"); - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); - return (1); - } - if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for bcs->blog\n"); - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - return (2); - } - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - } - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->event = 0; - bcs->hw.hscx.rcvidx = 0; - bcs->tx_cnt = 0; - return (0); + return bc_open(bcs);; } @@ -263,8 +214,12 @@ return (0); } +static void jade_fill_fifo(struct BCState *bcs); + static struct bc_l1_ops jade_l1_ops = { .fill_fifo = jade_fill_fifo, + .open = setstack_jade, + .close = close_jadestate, }; void __init @@ -273,12 +228,8 @@ int val; cs->bc_l1_ops = &jade_l1_ops; - cs->bcs[0].BC_SetStack = setstack_jade; - cs->bcs[1].BC_SetStack = setstack_jade; - cs->bcs[0].BC_Close = close_jadestate; - cs->bcs[1].BC_Close = close_jadestate; - cs->bcs[0].hw.hscx.hscx = 0; - cs->bcs[1].hw.hscx.hscx = 1; + cs->bcs[0].unit = 0; + cs->bcs[1].unit = 1; jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00); jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00); @@ -317,6 +268,13 @@ /* once again TRANSPARENT */ modejade(cs->bcs, 0, 0); modejade(cs->bcs + 1, 0, 0); +} + +int +jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops) +{ + cs->bc_hw_ops = jade_ops; + return JadeVersion(cs, "HiSax:"); } #include "jade_irq.c" diff -Nru a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h --- a/drivers/isdn/hisax/jade.h Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/jade.h Mon Jan 13 10:18:05 2003 @@ -127,12 +127,10 @@ #define jade_TXAUDIOCH1CFG 0x17 #define jade_TXAUDIOCH2CFG 0x1A -extern int JadeVersion(struct IsdnCardState *cs, char *s); extern void jade_sched_event(struct BCState *bcs, int event); extern void modejade(struct BCState *bcs, int mode, int bc); extern void initjade(struct IsdnCardState *cs); -extern void jade_int_main(struct IsdnCardState *cs, u_char val, int jade); -extern void jade_fill_fifo(struct BCState *bcs); - +extern void jade_int_main(struct IsdnCardState *cs, u8 val, int jade); +extern int jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops); #endif /* __JADE_H__ */ diff -Nru a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c --- a/drivers/isdn/hisax/jade_irq.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/jade_irq.c Mon Jan 13 10:18:05 2003 @@ -9,7 +9,6 @@ * of the GNU General Public License, incorporated herein by reference. * */ -static spinlock_t jade_irq_lock = SPIN_LOCK_UNLOCKED; static inline void waitforCEC(struct IsdnCardState *cs, int jade, int reg) @@ -26,20 +25,17 @@ static inline void -waitforXFW(struct IsdnCardState *cs, int jade) +waitforXFW(struct BCState *bcs) { - /* Does not work on older jade versions, don't care */ } static inline void -WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u8 data) +WriteJADECMDR(struct BCState *bcs, int reg, u8 data) { - unsigned long flags; + int jade = bcs->unit; - spin_lock_irqsave(&jade_irq_lock, flags); - waitforCEC(cs, jade, reg); - jade_write_reg(cs, jade, reg, data); - spin_unlock_irqrestore(&jade_irq_lock, flags); + waitforCEC(bcs->cs, jade, reg); + jade_write_reg(bcs->cs, jade, reg, data); } @@ -47,49 +43,24 @@ static void jade_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr; - struct IsdnCardState *cs = bcs->cs; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "jade_empty_fifo"); - - if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "jade_empty_fifo: incoming packet too large"); - WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); - bcs->hw.hscx.rcvidx = 0; - return; - } - ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; - bcs->hw.hscx.rcvidx += count; - jade_read_fifo(bcs, ptr, count); - WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "jade_empty_fifo %c cnt %d", - bcs->hw.hscx.hscx ? 'B' : 'A', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } + recv_empty_fifo_b(bcs, count); + WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC); } -void +static void jade_fill_fifo(struct BCState *bcs) { - struct IsdnCardState *cs = bcs->cs; int more, count; int fifo_size = 32; - int hscx = bcs->hw.hscx.hscx; unsigned char *p; p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); if (!p) return; - waitforXFW(cs, hscx); + waitforXFW(bcs); jade_write_fifo(bcs, p, count); - WriteJADECMDR(cs, hscx, jade_HDLC_XCMD, + WriteJADECMDR(bcs, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); } @@ -99,7 +70,6 @@ { u8 r; struct BCState *bcs = cs->bcs + jade; - struct sk_buff *skb; int fifo_size = 32; int count; int i_jade = (int) jade; /* To satisfy the compiler */ @@ -119,39 +89,20 @@ if (!(r & 0x20)) if (cs->debug & L1_DEB_WARN) debugl1(cs, "JADE %c CRC error", 'A'+jade); - WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC); + WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC); + bcs->rcvidx = 0; } else { count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F; if (count == 0) count = fifo_size; + jade_empty_fifo(bcs, count); - if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { - if (cs->debug & L1_DEB_HSCX_FIFO) - debugl1(cs, "HX Frame %d", count); - if (!(skb = dev_alloc_skb(count))) - printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A")); - else { - memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); - skb_queue_tail(&bcs->rqueue, skb); - } - } + recv_rme_b(bcs); } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ jade_empty_fifo(bcs, fifo_size); - if (bcs->mode == L1_MODE_TRANS) { - /* receive audio data */ - if (!(skb = dev_alloc_skb(fifo_size))) - printk(KERN_WARNING "HiSax: receive out of memory\n"); - else { - memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); - skb_queue_tail(&bcs->rqueue, skb); - } - bcs->hw.hscx.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); - } + recv_rpf_b(bcs); } if (val & 0x10) { /* XPR */ xmit_xpr_b(bcs); @@ -161,7 +112,7 @@ static void reset_xmit(struct BCState *bcs) { - WriteJADECMDR(bcs->cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES); + WriteJADECMDR(bcs, jade_HDLC_XCMD, jadeXCMD_XRES); } void diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c --- a/drivers/isdn/hisax/mic.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/mic.c Mon Jan 13 10:18:07 2003 @@ -132,111 +132,37 @@ .write_fifo = hscx_write_fifo, }; -static void -mic_interrupt(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 val; - - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); -} - -void -release_io_mic(struct IsdnCardState *cs) -{ - int bytecnt = 8; - - if (cs->hw.mic.cfg_reg) - release_region(cs->hw.mic.cfg_reg, bytecnt); -} - -static int -mic_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - return(0); - case CARD_RELEASE: - release_io_mic(cs); - return(0); - case CARD_INIT: - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} +static struct card_ops mic_ops = { + .init = inithscxisac, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; int __init setup_mic(struct IsdnCard *card) { - int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, mic_revision); printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_MIC) - return (0); - bytecnt = 8; cs->hw.mic.cfg_reg = card->para[1]; cs->irq = card->para[0]; cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; - if (!request_region((cs->hw.mic.cfg_reg), bytecnt, "mic isdn")) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.mic.cfg_reg, - cs->hw.mic.cfg_reg + bytecnt); - return (0); - } - - printk(KERN_INFO - "mic: defined at 0x%x IRQ %d\n", - cs->hw.mic.cfg_reg, - cs->irq); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &mic_card_msg; - cs->irq_func = &mic_interrupt; - ISACVersion(cs, "mic:"); - if (HscxVersion(cs, "mic:")) { - printk(KERN_WARNING - "mic: wrong HSCX versions check IO address\n"); - release_io_mic(cs); - return (0); - } - return (1); + if (!request_io(&cs->rs, cs->hw.mic.cfg_reg, 8, "mic isdn")) + goto err; + + printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", + cs->hw.mic.cfg_reg, cs->irq); + cs->card_ops = &mic_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c --- a/drivers/isdn/hisax/netjet.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/netjet.c Mon Jan 13 10:18:05 2003 @@ -839,6 +839,7 @@ tiger_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; + struct IsdnCardState *cs = st->l1.bcs->cs; switch (pr) { case (PH_DATA | REQUEST): @@ -853,13 +854,13 @@ case (PH_ACTIVATE | REQUEST): test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc); - /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */ - st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc)); + if (cs->hw.njet.bc_activate) + (cs->hw.njet.bc_activate)(cs, st->l1.bc); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): - /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */ - st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc)); + if (cs->hw.njet.bc_deactivate) + (cs->hw.njet.bc_deactivate)(cs, st->l1.bc); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): @@ -937,6 +938,8 @@ static struct bc_l1_ops netjet_l1_ops = { .fill_fifo = netjet_fill_dma, + .open = setstack_tiger, + .close = close_tigerstate, }; void __init @@ -994,13 +997,9 @@ inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); cs->hw.njet.last_is0 = 0; - cs->bcs[0].BC_SetStack = setstack_tiger; - cs->bcs[1].BC_SetStack = setstack_tiger; - cs->bcs[0].BC_Close = close_tigerstate; - cs->bcs[1].BC_Close = close_tigerstate; } -void +static void releasetiger(struct IsdnCardState *cs) { if (cs->bcs[0].hw.tiger.send) { @@ -1026,11 +1025,11 @@ } void -release_io_netjet(struct IsdnCardState *cs) +netjet_release(struct IsdnCardState *cs) { byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); byteout(cs->hw.njet.base + NETJET_IRQMASK1, 0); releasetiger(cs); - release_region(cs->hw.njet.base, 256); + hisax_release_resources(cs); } diff -Nru a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h --- a/drivers/isdn/hisax/netjet.h Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/netjet.h Mon Jan 13 10:18:07 2003 @@ -70,5 +70,5 @@ void netjet_fill_dma(struct BCState *bcs); void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs); void inittiger(struct IsdnCardState *cs); -void release_io_netjet(struct IsdnCardState *cs); +void netjet_release(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/niccy.c Mon Jan 13 10:18:05 2003 @@ -155,9 +155,7 @@ niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; - spin_lock(&cs->lock); if (cs->subtyp == NICCY_PCI) { int ival; ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); @@ -165,37 +163,11 @@ return; outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); } - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); + hscxisac_irq(intno, dev_id, regs); } void -release_io_niccy(struct IsdnCardState *cs) +niccy_release(struct IsdnCardState *cs) { if (cs->subtyp == NICCY_PCI) { int val; @@ -203,15 +175,11 @@ val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); val &= PCI_IRQ_DISABLE; outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); - release_region(cs->hw.niccy.cfg_reg, 0x40); - release_region(cs->hw.niccy.isac, 4); - } else { - release_region(cs->hw.niccy.isac, 2); - release_region(cs->hw.niccy.isac_ale, 2); } + hisax_release_resources(cs); } -static void +static int niccy_reset(struct IsdnCardState *cs) { if (cs->subtyp == NICCY_PCI) { @@ -221,31 +189,19 @@ val |= PCI_IRQ_ENABLE; outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); } - inithscxisac(cs); + return 0; } -static int -niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - niccy_reset(cs); - return(0); - case CARD_RELEASE: - release_io_niccy(cs); - return(0); - case CARD_INIT: - niccy_reset(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} +static struct card_ops niccy_ops = { + .init = inithscxisac, + .reset = niccy_reset, + .release = niccy_release, + .irq_func = niccy_interrupt, +}; static struct pci_dev *niccy_dev __initdata = NULL; #ifdef __ISAPNP__ -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __init @@ -256,36 +212,40 @@ strcpy(tmp, niccy_revision); printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_NICCY) - return (0); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; - if ((pb = isapnp_find_card( + if ((pb = pnp_find_card( ISAPNP_VENDOR('S', 'D', 'A'), ISAPNP_FUNCTION(0x0150), pnp_c))) { pnp_c = pb; pd = NULL; - if (!(pd = isapnp_find_dev(pnp_c, + if (!(pd = pnp_find_dev(pnp_c, ISAPNP_VENDOR('S', 'D', 'A'), ISAPNP_FUNCTION(0x0150), pd))) { printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n"); return (0); } - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = pd->resource[0].start; - card->para[2] = pd->resource[1].start; - card->para[0] = pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1] || !card->para[2]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "NiccyPnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "NiccyPnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n", - card->para[0], card->para[1], card->para[2]); - pd->deactivate(pd); + pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); + pnp_device_detach(pd); return(0); } + card->para[1] = pnp_port_start(pd, 0); + card->para[2] = pnp_port_start(pd, 1); + card->para[0] = pnp_irq(pd, 0); } else { printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n"); } @@ -299,30 +259,13 @@ cs->hw.niccy.cfg_reg = 0; cs->subtyp = NICCY_PNP; cs->irq = card->para[0]; - if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) { - printk(KERN_WARNING - "HiSax: %s data port %x-%x already in use\n", - CardType[card->typ], - cs->hw.niccy.isac, - cs->hw.niccy.isac + 1); - return (0); - } - if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) { - printk(KERN_WARNING - "HiSax: %s address port %x-%x already in use\n", - CardType[card->typ], - cs->hw.niccy.isac_ale, - cs->hw.niccy.isac_ale + 1); - release_region(cs->hw.niccy.isac, 2); - return (0); - } + if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data")) + goto err; + if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr")) + goto err; } else { #if CONFIG_PCI u_int pci_ioaddr; - if (!pci_present()) { - printk(KERN_ERR "Niccy: no PCI bus present\n"); - return(0); - } cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { @@ -354,43 +297,21 @@ cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; - if (!request_region(cs->hw.niccy.isac, 4, "niccy")) { - printk(KERN_WARNING - "HiSax: %s data port %x-%x already in use\n", - CardType[card->typ], - cs->hw.niccy.isac, - cs->hw.niccy.isac + 4); - return (0); - } - if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) { - printk(KERN_WARNING - "HiSax: %s pci port %x-%x already in use\n", - CardType[card->typ], - cs->hw.niccy.cfg_reg, - cs->hw.niccy.cfg_reg + 0x40); - release_region(cs->hw.niccy.isac, 4); - return (0); - } -#else - printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); - printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); - return (0); + + if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy")) + goto err; + if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) + goto err; #endif /* CONFIG_PCI */ } - printk(KERN_INFO - "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", + printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &niccy_card_msg; - cs->irq_func = &niccy_interrupt; - ISACVersion(cs, "Niccy:"); - if (HscxVersion(cs, "Niccy:")) { - printk(KERN_WARNING - "Niccy: wrong HSCX versions check IO address\n"); - release_io_niccy(cs); - return (0); - } - return (1); + cs->card_ops = &niccy_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + niccy_release(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c --- a/drivers/isdn/hisax/nj_s.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/nj_s.c Mon Jan 13 10:18:05 2003 @@ -18,7 +18,7 @@ const char *NETjet_S_revision = "$Revision: 2.7.6.6 $"; static void -netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) +nj_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; u8 val, sval; @@ -72,8 +72,8 @@ spin_unlock(&cs->lock); } -static void -reset_netjet_s(struct IsdnCardState *cs) +static int +nj_s_reset(struct IsdnCardState *cs) { cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); @@ -89,34 +89,28 @@ byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + return 0; } -static int -NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +nj_s_init(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - reset_netjet_s(cs); - return(0); - case CARD_RELEASE: - release_io_netjet(cs); - return(0); - case CARD_INIT: - inittiger(cs); - initisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); + inittiger(cs); + initisac(cs); } +static struct card_ops nj_s_ops = { + .init = nj_s_init, + .reset = nj_s_reset, + .release = netjet_release, + .irq_func = nj_s_interrupt, +}; + static struct pci_dev *dev_netjet __initdata = NULL; int __init setup_netjet_s(struct IsdnCard *card) { - int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -125,17 +119,8 @@ #endif strcpy(tmp, NETjet_S_revision); printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_NETJET_S) - return(0); -#if CONFIG_PCI - - for ( ;; ) - { - if (!pci_present()) { - printk(KERN_ERR "Netjet: no PCI bus present\n"); - return(0); - } + for ( ;; ) { if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { if (pci_enable_device(dev_netjet)) @@ -202,34 +187,15 @@ } break; } -#else - - printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n"); - printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n"); - return (0); - -#endif /* CONFIG_PCI */ - - bytecnt = 256; - printk(KERN_INFO "NETjet-S: PCI card configured at %#lx IRQ %d\n", cs->hw.njet.base, cs->irq); - if (check_region(cs->hw.njet.base, bytecnt)) { - printk(KERN_WARNING - "HiSax: %s config port %#lx-%#lx already in use\n", - CardType[card->typ], - cs->hw.njet.base, - cs->hw.njet.base + bytecnt); - return (0); - } else { - request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn"); - } - reset_netjet_s(cs); - cs->dc_hw_ops = &netjet_dc_ops; - cs->cardmsg = &NETjet_S_card_msg; - cs->irq_func = &netjet_s_interrupt; + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) + return 0; + + nj_s_reset(cs); cs->irq_flags |= SA_SHIRQ; - ISACVersion(cs, "NETjet-S:"); - return (1); + cs->card_ops = &nj_s_ops; + isac_setup(cs, &netjet_dc_ops); + return 1; } diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c --- a/drivers/isdn/hisax/nj_u.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/nj_u.c Mon Jan 13 10:18:05 2003 @@ -18,7 +18,7 @@ const char *NETjet_U_revision = "$Revision: 2.8.6.6 $"; static void -netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs) +nj_u_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; u8 val, sval; @@ -72,8 +72,8 @@ spin_unlock(&cs->lock); } -static void -reset_netjet_u(struct IsdnCardState *cs) +static int +nj_u_reset(struct IsdnCardState *cs) { cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); @@ -91,56 +91,39 @@ byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + return 0; } -static int -NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +nj_u_init(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - reset_netjet_u(cs); - return(0); - case CARD_RELEASE: - release_io_netjet(cs); - return(0); - case CARD_INIT: - inittiger(cs); - initicc(cs); - /* Reenable all IRQ */ - NETjet_WriteIC(cs, ICC_MASK, 0); - return(0); - case CARD_TEST: - return(0); - } - return(0); + inittiger(cs); + initicc(cs); + /* Reenable all IRQ */ + NETjet_WriteIC(cs, ICC_MASK, 0); } +static struct card_ops nj_u_ops = { + .init = nj_u_init, + .reset = nj_u_reset, + .release = netjet_release, + .irq_func = nj_u_interrupt, +}; + static struct pci_dev *dev_netjet __initdata = NULL; int __init setup_netjet_u(struct IsdnCard *card) { - int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; -#if CONFIG_PCI -#endif #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_U_revision); printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_NETJET_U) - return(0); - -#if CONFIG_PCI - for ( ;; ) - { - if (!pci_present()) { - printk(KERN_ERR "Netjet: no PCI bus present\n"); - return(0); - } + for ( ;; ) { if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { if (pci_enable_device(dev_netjet)) @@ -200,32 +183,15 @@ } break; } -#else - - printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n"); - printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n"); - return (0); - -#endif /* CONFIG_PCI */ - - bytecnt = 256; - printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n", cs->hw.njet.base, cs->irq); - if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) { - printk(KERN_WARNING - "HiSax: %s config port %#lx-%#lx already in use\n", - CardType[card->typ], - cs->hw.njet.base, - cs->hw.njet.base + bytecnt); - return (0); - } - reset_netjet_u(cs); - cs->dc_hw_ops = &netjet_dc_ops; - cs->cardmsg = &NETjet_U_card_msg; - cs->irq_func = &netjet_u_interrupt; + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) + return 0; + + nj_u_reset(cs); cs->irq_flags |= SA_SHIRQ; - ICCVersion(cs, "NETspider-U:"); - return (1); + cs->card_ops = &nj_u_ops; + icc_setup(cs, &netjet_dc_ops); + return 1; } diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c --- a/drivers/isdn/hisax/s0box.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/s0box.c Mon Jan 13 10:18:05 2003 @@ -166,70 +166,11 @@ .write_fifo = hscx_write_fifo, }; -static void -s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs) -{ -#define MAXCOUNT 5 - struct IsdnCardState *cs = dev_id; - u8 val; - int count = 0; - - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - count++; - val = hscx_read(cs, 1, HSCX_ISTA); - if (val && count < MAXCOUNT) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val && count < MAXCOUNT) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - if (count >= MAXCOUNT) - printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count); - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); -} - -void -release_io_s0box(struct IsdnCardState *cs) -{ - release_region(cs->hw.teles3.cfg_reg, 8); -} - -static int -S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - break; - case CARD_RELEASE: - release_io_s0box(cs); - break; - case CARD_INIT: - inithscxisac(cs); - break; - case CARD_TEST: - break; - } - return(0); -} +static struct card_ops s0box_ops = { + .init = inithscxisac, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; int __init setup_s0box(struct IsdnCard *card) @@ -239,9 +180,6 @@ strcpy(tmp, s0box_revision); printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_S0BOX) - return (0); - cs->hw.teles3.cfg_reg = card->para[1]; cs->hw.teles3.hscx[0] = -0x20; cs->hw.teles3.hscx[1] = 0x0; @@ -250,14 +188,8 @@ cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; cs->irq = card->para[0]; - if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) { - printk(KERN_WARNING - "HiSax: %s ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.teles3.cfg_reg, - cs->hw.teles3.cfg_reg + 7); - return 0; - } + if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O")) + goto err; printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n", CardType[cs->typ], cs->irq, @@ -265,16 +197,11 @@ printk(KERN_INFO "HiSax: hscx A:0x%x hscx B:0x%x\n", cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &S0Box_card_msg; - cs->irq_func = &s0box_interrupt; - ISACVersion(cs, "S0Box:"); - if (HscxVersion(cs, "S0Box:")) { - printk(KERN_WARNING - "S0Box: wrong HSCX versions check IO address\n"); - release_io_s0box(cs); - return (0); - } - return (1); + cs->card_ops = &s0box_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c --- a/drivers/isdn/hisax/saphir.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/saphir.c Mon Jan 13 10:18:05 2003 @@ -136,42 +136,9 @@ saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - /* Watchdog */ - if (cs->hw.saphir.timer.function) - mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); - else - printk(KERN_WARNING "saphir: Spurious timer!\n"); - - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); + hscxisac_irq(intno, dev_id, regs); + mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); } static void @@ -182,14 +149,13 @@ mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); } -void -release_io_saphir(struct IsdnCardState *cs) +static void +saphir_release(struct IsdnCardState *cs) { byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff); del_timer_sync(&cs->hw.saphir.timer); cs->hw.saphir.timer.function = NULL; - if (cs->hw.saphir.cfg_reg) - release_region(cs->hw.saphir.cfg_reg, 6); + hisax_release_resources(cs); } static int @@ -228,25 +194,12 @@ return (0); } -static int -saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - saphir_reset(cs); - return(0); - case CARD_RELEASE: - release_io_saphir(cs); - return(0); - case CARD_INIT: - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} - +static struct card_ops saphir_ops = { + .init = inithscxisac, + .reset = saphir_reset, + .release = saphir_release, + .irq_func = saphir_interrupt, +}; int __init setup_saphir(struct IsdnCard *card) @@ -259,20 +212,15 @@ if (cs->typ != ISDN_CTYPE_HSTSAPHIR) return (0); + init_timer(&cs->hw.saphir.timer); /* IO-Ports */ cs->hw.saphir.cfg_reg = card->para[1]; cs->hw.saphir.isac = card->para[1] + ISAC_DATA; cs->hw.saphir.hscx = card->para[1] + HSCX_DATA; cs->hw.saphir.ale = card->para[1] + ADDRESS_REG; cs->irq = card->para[0]; - if (!request_region((cs->hw.saphir.cfg_reg), 6, "saphir")) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.saphir.cfg_reg, - cs->hw.saphir.cfg_reg + 5); - return (0); - } + if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir")) + goto err; printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", @@ -281,23 +229,17 @@ cs->hw.saphir.timer.function = (void *) SaphirWatchDog; cs->hw.saphir.timer.data = (long) cs; - init_timer(&cs->hw.saphir.timer); cs->hw.saphir.timer.expires = jiffies + 4*HZ; add_timer(&cs->hw.saphir.timer); - if (saphir_reset(cs)) { - release_io_saphir(cs); - return (0); - } - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &saphir_card_msg; - cs->irq_func = &saphir_interrupt; - ISACVersion(cs, "saphir:"); - if (HscxVersion(cs, "saphir:")) { - printk(KERN_WARNING - "saphir: wrong HSCX versions check IO address\n"); - release_io_saphir(cs); - return (0); - } - return (1); + if (saphir_reset(cs)) + goto err; + + cs->card_ops = &saphir_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + + return 1; + err: + saphir_release(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c --- a/drivers/isdn/hisax/sedlbauer.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/sedlbauer.c Mon Jan 13 10:18:07 2003 @@ -189,37 +189,6 @@ }; static u8 -ipac_dc_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, cs->hw.sedl.isac, offset|0x80); -} - -static void -ipac_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - writereg(cs, cs->hw.sedl.isac, offset|0x80, value); -} - -static void -ipac_dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - readfifo(cs, cs->hw.sedl.isac, 0x80, data, size); -} - -static void -ipac_dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - writefifo(cs, cs->hw.sedl.isac, 0x80, data, size); -} - -static struct dc_hw_ops ipac_dc_ops = { - .read_reg = ipac_dc_read, - .write_reg = ipac_dc_write, - .read_fifo = ipac_dc_read_fifo, - .write_fifo = ipac_dc_write_fifo, -}; - -static u8 hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) { return readreg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0)); @@ -250,6 +219,36 @@ .write_fifo = hscx_write_fifo, }; +static inline u8 +ipac_read(struct IsdnCardState *cs, u8 offset) +{ + return readreg(cs, cs->hw.sedl.isac, offset); +} + +static inline void +ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +{ + writereg(cs, cs->hw.sedl.isac, offset, value); +} + +static inline void +ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +{ + readfifo(cs, cs->hw.sedl.isac, offset, data, size); +} + +static inline void +ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +{ + writefifo(cs, cs->hw.sedl.isac, offset, data, size); +} + +/* This will generate ipac_dc_ops and ipac_bc_ops using the functions + * above */ + +BUILD_IPAC_OPS(ipac); + + /* ISAR access routines * mode = 0 access with IRQ on * mode = 1 access with IRQ off @@ -289,12 +288,6 @@ sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; - - if (!cs) { - printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n"); - return; - } if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed @@ -302,84 +295,11 @@ printk(KERN_WARNING "Sedlbauer: card not available!\n"); return; } - - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); + hscxisac_irq(intno, dev_id, regs); } static void -sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 ista, val, icnt = 5; - - if (!cs) { - printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n"); - return; - } - ista = readreg(cs, cs->hw.sedl.isac, IPAC_ISTA); -Start_IPAC: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = hscx_read(cs, 1, HSCX_ISTA); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) - hscx_int_main(cs, val); - } - if (ista & 0x20) { - val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe; - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = readreg(cs, cs->hw.sedl.isac, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPAC; - } - if (!icnt) - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "Sedlbauer IRQ LOOP"); - writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xFF); - writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xC0); -} - -static void -sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs) +sedlbauer_isar_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; u8 val; @@ -417,108 +337,121 @@ spin_unlock(&cs->lock); } -void -release_io_sedlbauer(struct IsdnCardState *cs) +static int +sedlbauer_ipac_reset(struct IsdnCardState *cs) { - int bytecnt = 8; + writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0); + writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff); + writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0); + writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0); + writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12); + return 0; +} - if (cs->subtyp == SEDL_SPEED_FAX) { - bytecnt = 16; - } else if (cs->hw.sedl.bus == SEDL_BUS_PCI) { - bytecnt = 256; - } - if (cs->hw.sedl.cfg_reg) - release_region(cs->hw.sedl.cfg_reg, bytecnt); +static int +sedlbauer_isar_pci_reset(struct IsdnCardState *cs) +{ + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout((20*HZ)/1000); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout((20*HZ)/1000); + return 0; } -static void -reset_sedlbauer(struct IsdnCardState *cs) +static int +sedlbauer_reset(struct IsdnCardState *cs) { printk(KERN_INFO "Sedlbauer: resetting card\n"); + if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA && + cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX) + return 0; - if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && - (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) { - if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { - writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0); - writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff); - writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0); - writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0); - writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12); - } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && - (cs->hw.sedl.bus == SEDL_BUS_PCI)) { - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); - } else { - byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - } + if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { + return sedlbauer_ipac_reset(cs); + } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && + (cs->hw.sedl.bus == SEDL_BUS_PCI)) { + return sedlbauer_isar_pci_reset(cs); + } else { + byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); + byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); } + return 0; } -static int -Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +sedlbauer_isar_release(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - reset_sedlbauer(cs); - return(0); - case CARD_RELEASE: - if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - reset_sedlbauer(cs); - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - } - release_io_sedlbauer(cs); - return(0); - case CARD_INIT: - if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { - isar_write(cs, 0, ISAR_IRQBIT, 0); - initisac(cs); - initisar(cs); - } else { - inithscxisac(cs); - } - return(0); - case CARD_TEST: - return(0); - case MDL_INFO_CONN: - if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) - return(0); - if ((long) arg) - cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; - else - cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - break; - case MDL_INFO_REL: - if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) - return(0); - if ((long) arg) - cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; - else - cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - break; - } - return(0); + isar_write(cs, 0, ISAR_IRQBIT, 0); + isac_write(cs, ISAC_MASK, 0xFF); + sedlbauer_reset(cs); + isar_write(cs, 0, ISAR_IRQBIT, 0); + isac_write(cs, ISAC_MASK, 0xFF); + hisax_release_resources(cs); +} + +static void +sedlbauer_led_handler(struct IsdnCardState *cs) +{ + if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) + return; + + if (cs->status & 0x2000) + cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; + else + cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; + + if (cs->status & 0x1000) + cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; + else + cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; + + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); +} + +static void +sedlbauer_isar_init(struct IsdnCardState *cs) +{ + isar_write(cs, 0, ISAR_IRQBIT, 0); + initisac(cs); + initisar(cs); } +static struct card_ops sedlbauer_ops = { + .init = inithscxisac, + .reset = sedlbauer_reset, + .release = hisax_release_resources, + .led_handler = sedlbauer_led_handler, + .irq_func = sedlbauer_interrupt, +}; + +static struct card_ops sedlbauer_ipac_ops = { + .init = ipac_init, + .reset = sedlbauer_reset, + .release = hisax_release_resources, + .led_handler = sedlbauer_led_handler, + .irq_func = ipac_irq, +}; + +static struct card_ops sedlbauer_isar_ops = { + .init = sedlbauer_isar_init, + .reset = sedlbauer_reset, + .release = sedlbauer_isar_release, + .led_handler = sedlbauer_led_handler, + .irq_func = sedlbauer_isar_interrupt, +}; + static struct pci_dev *dev_sedl __devinitdata = NULL; #ifdef __ISAPNP__ @@ -533,13 +466,13 @@ }; static struct isapnp_device_id *pdev = &sedl_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_sedlbauer(struct IsdnCard *card) { - int bytecnt, ver, val; + int bytecnt, val; struct IsdnCardState *cs = card->cs; char tmp[64]; u16 sub_vendor_id, sub_id; @@ -572,31 +505,38 @@ } else { #ifdef __ISAPNP__ if (isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pb; + struct pnp_dev *pd; while(pdev->card_vendor) { - if ((pb = isapnp_find_card(pdev->card_vendor, - pdev->card_device, pnp_c))) { + if ((pb = pnp_find_card(pdev->card_vendor, + pdev->card_device, + pnp_c))) { pnp_c = pb; pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - pdev->vendor, pdev->function, pd))) { + if ((pd = pnp_find_dev(pnp_c, + pdev->vendor, + pdev->function, + pd))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)pdev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[1] = - pd->resource[0].start; - card->para[0] = - pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1]) { + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd, NULL) < 0) { + printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", - card->para[0], card->para[1]); - pd->deactivate(pd); - return(0); + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); + goto err; } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); cs->hw.sedl.cfg_reg = card->para[1]; cs->irq = card->para[0]; if (pdev->function == ISAPNP_FUNCTION(0x2)) { @@ -610,7 +550,7 @@ goto ready; } else { printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); - return(0); + goto err; } } pdev++; @@ -623,23 +563,19 @@ #endif /* Probe for Sedlbauer speed pci */ #if CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "Sedlbauer: no PCI bus present\n"); - return(0); - } if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { if (pci_enable_device(dev_sedl)) - return(0); + goto err; cs->irq = dev_sedl->irq; if (!cs->irq) { printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); - return(0); + goto err; } cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); } else { printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); - return(0); + goto err; } cs->irq_flags |= SA_SHIRQ; cs->hw.sedl.bus = SEDL_BUS_PCI; @@ -651,7 +587,7 @@ cs->hw.sedl.cfg_reg); if (sub_id != PCI_SUB_ID_SEDLBAUER) { printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); - return(0); + goto err; } if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; @@ -665,7 +601,7 @@ } else { printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", sub_vendor_id); - return(0); + goto err; } bytecnt = 256; cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; @@ -678,9 +614,6 @@ current->state = TASK_UNINTERRUPTIBLE; schedule_timeout((10*HZ)/1000); byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); -#else - printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n"); - return (0); #endif /* CONFIG_PCI */ } ready: @@ -688,14 +621,9 @@ * reserved for us by the card manager. So we do not check it * here, it would fail. */ - if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA && - (!request_region((cs->hw.sedl.cfg_reg), bytecnt, "sedlbauer isdn"))) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.sedl.cfg_reg, - cs->hw.sedl.cfg_reg + bytecnt); - return (0); + if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) { + if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) + goto err; } printk(KERN_INFO @@ -704,9 +632,6 @@ cs->hw.sedl.cfg_reg + bytecnt, cs->irq); - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &Sedl_card_msg; - /* * testing ISA and PCMCIA Cards for IPAC, default is ISAC * do not test for PCI card, because ports are different @@ -749,16 +674,12 @@ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; } - test_and_set_bit(HW_IPAC, &cs->HW_Flags); - cs->dc_hw_ops = &ipac_dc_ops; - cs->irq_func = &sedlbauer_interrupt_ipac; - - val = readreg(cs, cs->hw.sedl.isac, IPAC_ID); - printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val); - reset_sedlbauer(cs); + cs->card_ops = &sedlbauer_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + sedlbauer_reset(cs); } else { /* ISAC_HSCX oder ISAC_ISAR */ - cs->dc_hw_ops = &isac_ops; if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { if (cs->hw.sedl.bus == SEDL_BUS_PCI) { cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + @@ -782,17 +703,11 @@ cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; test_and_set_bit(HW_ISAR, &cs->HW_Flags); - cs->irq_func = &sedlbauer_interrupt_isar; + cs->card_ops = &sedlbauer_isar_ops; cs->auxcmd = &isar_auxcmd; - ISACVersion(cs, "Sedlbauer:"); - cs->bc_hw_ops = &isar_ops; - ver = ISARVersion(cs, "Sedlbauer:"); - if (ver < 0) { - printk(KERN_WARNING - "Sedlbauer: wrong ISAR version (ret = %d)\n", ver); - release_io_sedlbauer(cs); - return (0); - } + isac_setup(cs, &isac_ops); + if (isar_setup(cs, &isar_ops)) + goto err; } else { if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; @@ -807,17 +722,15 @@ cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; } - cs->irq_func = &sedlbauer_interrupt; - ISACVersion(cs, "Sedlbauer:"); - - if (HscxVersion(cs, "Sedlbauer:")) { - printk(KERN_WARNING - "Sedlbauer: wrong HSCX versions check IO address\n"); - release_io_sedlbauer(cs); - return (0); - } - reset_sedlbauer(cs); + cs->card_ops = &sedlbauer_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + + sedlbauer_reset(cs); } } - return (1); + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c --- a/drivers/isdn/hisax/sportster.c Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/sportster.c Mon Jan 13 10:18:05 2003 @@ -115,36 +115,13 @@ sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - /* get a new irq impulse if there any pending */ + hscxisac_irq(intno, dev_id, regs); bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1); - spin_unlock(&cs->lock); } -void -release_io_sportster(struct IsdnCardState *cs) +static void +sportster_release(struct IsdnCardState *cs) { int i, adr; @@ -155,8 +132,8 @@ } } -void -reset_sportster(struct IsdnCardState *cs) +static int +sportster_reset(struct IsdnCardState *cs) { cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); @@ -166,33 +143,34 @@ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); + return 0; } static int Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - switch (mt) { - case CARD_RESET: - reset_sportster(cs); - return(0); - case CARD_RELEASE: - release_io_sportster(cs); - return(0); - case CARD_INIT: - inithscxisac(cs); - cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ - byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - return(0); - case CARD_TEST: - return(0); - } return(0); } +static void +sportster_init(struct IsdnCardState *cs) +{ + inithscxisac(cs); + cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ + byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); +} + +static struct card_ops sportster_ops = { + .init = sportster_init, + .reset = sportster_reset, + .release = sportster_release, + .irq_func = sportster_interrupt, +}; + static int __init get_io_range(struct IsdnCardState *cs) { - int i, j, adr; + int i, adr; for (i=0;i<64;i++) { adr = cs->hw.spt.cfg_reg + i *1024; @@ -200,20 +178,18 @@ printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", CardType[cs->typ], adr, adr + 8); - break; + goto err; } } - if (i==64) - return(1); - else { - for (j=0; jhw.spt.cfg_reg + j *1024; - release_region(adr, 8); - } - return(0); + return 1; + err: + for (i=i-1; i >= 0; i--) { + adr = cs->hw.spt.cfg_reg + i *1024; + release_region(adr, 8); } + return 0; } - + int __init setup_sportster(struct IsdnCard *card) { @@ -222,8 +198,6 @@ strcpy(tmp, sportster_revision); printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_SPORTSTER) - return (0); cs->hw.spt.cfg_reg = card->para[1]; cs->irq = card->para[0]; @@ -248,26 +222,20 @@ break; case 15:cs->hw.spt.res_irq = 7; break; - default:release_io_sportster(cs); + default:sportster_release(cs); printk(KERN_WARNING "Sportster: wrong IRQ\n"); return(0); } - reset_sportster(cs); - printk(KERN_INFO - "HiSax: %s config irq:%d cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.spt.cfg_reg); + sportster_reset(cs); + printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; cs->cardmsg = &Sportster_card_msg; - cs->irq_func = &sportster_interrupt; - ISACVersion(cs, "Sportster:"); - if (HscxVersion(cs, "Sportster:")) { - printk(KERN_WARNING - "Sportster: wrong HSCX versions check IO address\n"); - release_io_sportster(cs); - return (0); - } - return (1); + cs->card_ops = &sportster_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c --- a/drivers/isdn/hisax/tei.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/tei.c Mon Jan 13 10:18:07 2003 @@ -74,6 +74,22 @@ "EV_T202", }; +static inline void +mdl_assign(struct IsdnCardState *cs) +{ + cs->status |= 0x0001; + if (cs->card_ops->led_handler) + cs->card_ops->led_handler(cs); +} + +static inline void +mdl_remove(struct IsdnCardState *cs) +{ + cs->status = 0; + if (cs->card_ops->led_handler) + cs->card_ops->led_handler(cs); +} + unsigned int random_ri(void) { @@ -167,7 +183,7 @@ FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); + mdl_assign(cs); } } @@ -241,7 +257,7 @@ FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); L3L2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); + mdl_remove(cs); } } @@ -277,7 +293,7 @@ st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed"); L3L2(st, MDL_ERROR | RESPONSE, 0); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); + mdl_remove(cs); FsmChangeState(fi, ST_TEI_NOP); } } @@ -300,7 +316,7 @@ "verify req for tei %d failed", st->l2.tei); L3L2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); + mdl_remove(cs); FsmChangeState(fi, ST_TEI_NOP); } } @@ -373,7 +389,7 @@ "fixed assign tei %d", st->l2.tei); L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); + mdl_assign(cs); } return; } diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c --- a/drivers/isdn/hisax/teleint.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/teleint.c Mon Jan 13 10:18:07 2003 @@ -179,7 +179,7 @@ }; static void -TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs) +teleint_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; u8 val; @@ -217,17 +217,16 @@ add_timer(&cs->hw.hfc.timer); } -void -release_io_TeleInt(struct IsdnCardState *cs) +static void +teleint_release(struct IsdnCardState *cs) { del_timer(&cs->hw.hfc.timer); releasehfc(cs); - if (cs->hw.hfc.addr) - release_region(cs->hw.hfc.addr, 2); + hisax_release_resources(cs); } -static void -reset_TeleInt(struct IsdnCardState *cs) +static int +teleint_reset(struct IsdnCardState *cs) { printk(KERN_INFO "TeleInt: resetting card\n"); cs->hw.hfc.cirm |= HFC_RESET; @@ -238,30 +237,25 @@ byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); + return 0; } -static int -TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg) +static void +teleint_init(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - reset_TeleInt(cs); - return(0); - case CARD_RELEASE: - release_io_TeleInt(cs); - return(0); - case CARD_INIT: - inithfc(cs); - initisac(cs); - cs->hw.hfc.timer.expires = jiffies + 1; - add_timer(&cs->hw.hfc.timer); - return(0); - case CARD_TEST: - return(0); - } - return(0); + inithfc(cs); + initisac(cs); + cs->hw.hfc.timer.expires = jiffies + 1; + add_timer(&cs->hw.hfc.timer); } +static struct card_ops teleint_ops = { + .init = teleint_init, + .reset = teleint_reset, + .release = teleint_release, + .irq_func = teleint_interrupt, +}; + int __init setup_TeleInt(struct IsdnCard *card) { @@ -270,8 +264,6 @@ strcpy(tmp, TeleInt_revision); printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_TELEINT) - return (0); cs->hw.hfc.addr = card->para[1] & 0x3fe; cs->irq = card->para[0]; @@ -285,16 +277,9 @@ cs->hw.hfc.timer.function = (void *) TeleInt_Timer; cs->hw.hfc.timer.data = (long) cs; init_timer(&cs->hw.hfc.timer); - if (check_region((cs->hw.hfc.addr), 2)) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.hfc.addr, - cs->hw.hfc.addr + 2); - return (0); - } else { - request_region(cs->hw.hfc.addr, 2, "TeleInt isdn"); - } + if (!request_io(&cs->rs, cs->hw.hfc.addr, 2, "TeleInt isdn")) + goto err; + /* HW IO = IO */ byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff); byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54); @@ -319,8 +304,7 @@ break; default: printk(KERN_WARNING "TeleInt: wrong IRQ\n"); - release_io_TeleInt(cs); - return (0); + goto err; } byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt); @@ -330,11 +314,12 @@ cs->hw.hfc.addr, cs->irq); - reset_TeleInt(cs); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hfc_ops; - cs->cardmsg = &TeleInt_card_msg; - cs->irq_func = &TeleInt_interrupt; - ISACVersion(cs, "TeleInt:"); - return (1); + cs->card_ops = &teleint_ops; + teleint_reset(cs); + isac_setup(cs, &isac_ops); + hfc_setup(cs, &hfc_ops); + return 1; + err: + teleint_release(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c --- a/drivers/isdn/hisax/teles0.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/teles0.c Mon Jan 13 10:18:06 2003 @@ -48,7 +48,7 @@ isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) { int i; - unsigned long ad = cs->hw.teles0.membase + 0x100; + void *ad = cs->hw.teles0.membase + 0x100; for (i = 0; i < size; i++) data[i] = readb(ad); } @@ -57,7 +57,7 @@ isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) { int i; - unsigned long ad = cs->hw.teles0.membase + 0x100; + void *ad = cs->hw.teles0.membase + 0x100; for (i = 0; i < size; i++) { writeb(data[i], ad); mb(); } @@ -88,7 +88,7 @@ hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) { int i; - unsigned long ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); + void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); for (i = 0; i < size; i++) data[i] = readb(ad); } @@ -97,7 +97,7 @@ hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) { int i; - unsigned long ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); + void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); for (i = 0; i < size; i++) { writeb(data[i], ad); } @@ -110,55 +110,8 @@ .write_fifo = hscx_write_fifo, }; -static void -teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 val; - int count = 0; - - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - count++; - val = hscx_read(cs, 1, HSCX_ISTA); - if (val && count < 5) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val && count < 5) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); -} - -void -release_io_teles0(struct IsdnCardState *cs) -{ - if (cs->hw.teles0.cfg_reg) - release_region(cs->hw.teles0.cfg_reg, 8); - iounmap((unsigned char *)cs->hw.teles0.membase); - release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); -} - static int -reset_teles0(struct IsdnCardState *cs) +teles0_reset(struct IsdnCardState *cs) { u8 cfval; @@ -205,24 +158,12 @@ return(0); } -static int -Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - reset_teles0(cs); - return(0); - case CARD_RELEASE: - release_io_teles0(cs); - return(0); - case CARD_INIT: - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} +static struct card_ops teles0_ops = { + .init = inithscxisac, + .reset = teles0_reset, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; int __init setup_teles0(struct IsdnCard *card) @@ -233,9 +174,6 @@ strcpy(tmp, teles0_revision); printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp)); - if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0)) - return (0); - if (cs->typ == ISDN_CTYPE_16_0) cs->hw.teles0.cfg_reg = card->para[2]; else /* 8.0 */ @@ -249,76 +187,50 @@ } cs->irq = card->para[0]; if (cs->hw.teles0.cfg_reg) { - if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.teles0.cfg_reg, - cs->hw.teles0.cfg_reg + 8); - return (0); - } - } - if (cs->hw.teles0.cfg_reg) { + if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg")) + goto err; + if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", cs->hw.teles0.cfg_reg + 0, val); - release_region(cs->hw.teles0.cfg_reg, 8); - return (0); + goto err; } if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", cs->hw.teles0.cfg_reg + 1, val); - release_region(cs->hw.teles0.cfg_reg, 8); - return (0); + goto err; } - val = bytein(cs->hw.teles0.cfg_reg + 2); /* 0x1e=without AB - * 0x1f=with AB - * 0x1c 16.3 ??? - */ + val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB + * 0x1f=with AB + * 0x1c 16.3 ??? + */ if (val != 0x1e && val != 0x1f) { printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", cs->hw.teles0.cfg_reg + 2, val); - release_region(cs->hw.teles0.cfg_reg, 8); - return (0); + goto err; } } /* 16.0 and 8.0 designed for IOM1 */ test_and_set_bit(HW_IOM1, &cs->HW_Flags); cs->hw.teles0.phymem = card->para[1]; - if (check_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE)) { - printk(KERN_WARNING - "HiSax: %s memory region %lx-%lx already in use\n", - CardType[card->typ], - cs->hw.teles0.phymem, - cs->hw.teles0.phymem + TELES_IOMEM_SIZE); - if (cs->hw.teles0.cfg_reg) - release_region(cs->hw.teles0.cfg_reg, 8); - return (0); - } else { - request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE, - "teles iomem"); - } - cs->hw.teles0.membase = - (unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); + cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem"); + if (!cs->hw.teles0.membase) + goto err; + printk(KERN_INFO - "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n", + "HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n", CardType[cs->typ], cs->irq, cs->hw.teles0.membase, cs->hw.teles0.cfg_reg); - if (reset_teles0(cs)) { + if (teles0_reset(cs)) { printk(KERN_WARNING "Teles0: wrong IRQ\n"); - release_io_teles0(cs); - return (0); - } - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &Teles_card_msg; - cs->irq_func = &teles0_interrupt; - ISACVersion(cs, "Teles0:"); - if (HscxVersion(cs, "Teles0:")) { - printk(KERN_WARNING - "Teles0: wrong HSCX versions check IO/MEM addresses\n"); - release_io_teles0(cs); - return (0); + goto err; } - return (1); + cs->card_ops = &teles0_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c --- a/drivers/isdn/hisax/teles3.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/teles3.c Mon Jan 13 10:18:07 2003 @@ -113,77 +113,8 @@ .write_fifo = hscx_write_fifo, }; -static void -teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs) -{ -#define MAXCOUNT 5 - struct IsdnCardState *cs = dev_id; - u8 val; - int count = 0; - - spin_lock(&cs->lock); - val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = readreg(cs->hw.teles3.isac, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - count++; - val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); - if (val && count < MAXCOUNT) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = readreg(cs->hw.teles3.isac, ISAC_ISTA); - if (val && count < MAXCOUNT) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - if (count >= MAXCOUNT) - printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count); - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); -} - -inline static void -release_ioregs(struct IsdnCardState *cs, int mask) -{ - if (mask & 1) - release_region(cs->hw.teles3.isac + 32, 32); - if (mask & 2) - release_region(cs->hw.teles3.hscx[0] + 32, 32); - if (mask & 4) - release_region(cs->hw.teles3.hscx[1] + 32, 32); -} - -void -release_io_teles3(struct IsdnCardState *cs) -{ - if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - release_region(cs->hw.teles3.hscx[1], 96); - } else { - if (cs->hw.teles3.cfg_reg) { - if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - release_region(cs->hw.teles3.cfg_reg, 1); - } else { - release_region(cs->hw.teles3.cfg_reg, 8); - } - } - release_ioregs(cs, 0x7); - } -} - static int -reset_teles3(struct IsdnCardState *cs) +teles3_reset(struct IsdnCardState *cs) { u8 irqcfg; @@ -238,24 +169,12 @@ return(0); } -static int -Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - reset_teles3(cs); - return(0); - case CARD_RELEASE: - release_io_teles3(cs); - return(0); - case CARD_INIT: - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} +static struct card_ops teles3_ops = { + .init = inithscxisac, + .reset = teles3_reset, + .release = hisax_release_resources, + .irq_func = hscxisac_irq, +}; #ifdef __ISAPNP__ static struct isapnp_device_id teles_ids[] __initdata = { @@ -272,7 +191,7 @@ }; static struct isapnp_device_id *tdev = &teles_ids[0]; -static struct pci_bus *pnp_c __devinitdata = NULL; +static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit @@ -290,31 +209,41 @@ #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pci_bus *pb; - struct pci_dev *pd; + struct pnp_card *pnp_card; + struct pnp_dev *pnp_dev; while(tdev->card_vendor) { - if ((pb = isapnp_find_card(tdev->card_vendor, - tdev->card_device, pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = isapnp_find_dev(pnp_c, - tdev->vendor, tdev->function, pd))) { + if ((pnp_card = pnp_find_card(tdev->card_vendor, + tdev->card_device, pnp_c))) { + pnp_c = pnp_card; + pnp_dev = NULL; + if ((pnp_dev = pnp_find_dev(pnp_card, + tdev->vendor, + tdev->function, + pnp_dev))) { printk(KERN_INFO "HiSax: %s detected\n", (char *)tdev->driver_data); - pd->prepare(pd); - pd->deactivate(pd); - pd->activate(pd); - card->para[3] = pd->resource[2].start; - card->para[2] = pd->resource[1].start; - card->para[1] = pd->resource[0].start; - card->para[0] = pd->irq_resource[0].start; - if (!card->para[0] || !card->para[1] || !card->para[2]) { - printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n", - card->para[0], card->para[1], card->para[2]); - pd->deactivate(pd); - return(0); + if (pnp_device_attach(pnp_dev) < 0) { + printk(KERN_ERR "Teles PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pnp_dev, NULL) < 0) { + printk(KERN_ERR "Teles PnP: activate failed\n"); + pnp_device_detach(pnp_dev); + return 0; + } + if (!pnp_irq_valid(pnp_dev, 0) || + !pnp_port_valid(pnp_dev, 0) || + !pnp_port_valid(pnp_dev, 1)) { + printk(KERN_ERR "Teles PnP: some resources are missing %ld/%lx/%lx\n", + pnp_irq(pnp_dev, 0), pnp_port_start(pnp_dev, 0), pnp_port_start(pnp_dev, 1)); + pnp_device_detach(pnp_dev); + return 0; } + card->para[3] = pnp_port_start(pnp_dev, 2); + card->para[2] = pnp_port_start(pnp_dev, 1); + card->para[1] = pnp_port_start(pnp_dev, 0); + card->para[0] = pnp_irq(pnp_dev, 0); break; } else { printk(KERN_ERR "Teles PnP: PnP error card found, no device\n"); @@ -362,95 +291,35 @@ cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - if (!request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) { - printk(KERN_WARNING - "HiSax: %s ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.teles3.hscx[1], - cs->hw.teles3.hscx[1] + 96); - return (0); - } + if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) + goto err; } else { if (cs->hw.teles3.cfg_reg) { if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - if (!request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) { - printk(KERN_WARNING - "HiSax: %s config port %x already in use\n", - CardType[card->typ], - cs->hw.teles3.cfg_reg); - return (0); - } + if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) + goto err; } else { - if (!request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.teles3.cfg_reg, - cs->hw.teles3.cfg_reg + 8); - return (0); - } - } - } - if (!request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac")) { - printk(KERN_WARNING - "HiSax: %s isac ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.teles3.isac + 32, - cs->hw.teles3.isac + 64); - if (cs->hw.teles3.cfg_reg) { - if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - release_region(cs->hw.teles3.cfg_reg, 1); - } else { - release_region(cs->hw.teles3.cfg_reg, 8); - } + if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) + goto err; } - return (0); - } - if (!request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) { - printk(KERN_WARNING - "HiSax: %s hscx A ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.teles3.hscx[0] + 32, - cs->hw.teles3.hscx[0] + 64); - if (cs->hw.teles3.cfg_reg) { - if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - release_region(cs->hw.teles3.cfg_reg, 1); - } else { - release_region(cs->hw.teles3.cfg_reg, 8); - } - } - release_ioregs(cs, 1); - return (0); - } - if (!request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) { - printk(KERN_WARNING - "HiSax: %s hscx B ports %x-%x already in use\n", - CardType[cs->typ], - cs->hw.teles3.hscx[1] + 32, - cs->hw.teles3.hscx[1] + 64); - if (cs->hw.teles3.cfg_reg) { - if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - release_region(cs->hw.teles3.cfg_reg, 1); - } else { - release_region(cs->hw.teles3.cfg_reg, 8); - } - } - release_ioregs(cs, 3); - return (0); } + if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac")) + goto err; + if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) + goto err; + if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) + goto err; } if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", cs->hw.teles3.cfg_reg + 0, val); - release_io_teles3(cs); - return (0); + goto err; } if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", cs->hw.teles3.cfg_reg + 1, val); - release_io_teles3(cs); - return (0); + goto err; } val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB * 0x1f=with AB @@ -462,8 +331,7 @@ if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) { printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", cs->hw.teles3.cfg_reg + 2, val); - release_io_teles3(cs); - return (0); + goto err; } } printk(KERN_INFO @@ -474,21 +342,16 @@ "HiSax: hscx A:0x%X hscx B:0x%X\n", cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); - if (reset_teles3(cs)) { + if (teles3_reset(cs)) { printk(KERN_WARNING "Teles3: wrong IRQ\n"); - release_io_teles3(cs); - return (0); + goto err; } - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &Teles_card_msg; - cs->irq_func = &teles3_interrupt; - ISACVersion(cs, "Teles3:"); - if (HscxVersion(cs, "Teles3:")) { - printk(KERN_WARNING - "Teles3: wrong HSCX versions check IO address\n"); - release_io_teles3(cs); - return (0); - } - return (1); + cs->card_ops = &teles3_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; + } diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c --- a/drivers/isdn/hisax/telespci.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/hisax/telespci.c Mon Jan 13 10:18:06 2003 @@ -45,7 +45,7 @@ static u8 isac_read(struct IsdnCardState *cs, u8 off) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; ZORAN_WAIT_NOBUSY; @@ -63,7 +63,7 @@ static void isac_write(struct IsdnCardState *cs, u8 off, u8 data) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; ZORAN_WAIT_NOBUSY; @@ -80,7 +80,7 @@ static void isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; int i; @@ -99,7 +99,7 @@ static void isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; int i; @@ -124,7 +124,7 @@ static u8 hscx_read(struct IsdnCardState *cs, int hscx, u8 off) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; ZORAN_WAIT_NOBUSY; @@ -141,7 +141,7 @@ static void hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; ZORAN_WAIT_NOBUSY; @@ -157,7 +157,7 @@ static void hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; int i; @@ -176,7 +176,7 @@ static void hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) { - unsigned long adr = cs->hw.teles0.membase + 0x200; + void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; int i; @@ -225,29 +225,11 @@ spin_unlock(&cs->lock); } -void -release_io_telespci(struct IsdnCardState *cs) -{ - iounmap((void *)cs->hw.teles0.membase); -} - -static int -TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - return(0); - case CARD_RELEASE: - release_io_telespci(cs); - return(0); - case CARD_INIT: - inithscxisac(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} +static struct card_ops telespci_ops = { + .init = inithscxisac, + .release = hisax_release_resources, + .irq_func = telespci_interrupt, +}; static struct pci_dev *dev_tel __initdata = NULL; @@ -262,13 +244,6 @@ #endif strcpy(tmp, telespci_revision); printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_TELESPCI) - return (0); -#if CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "TelesPCI: no PCI bus present\n"); - return(0); - } if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { if (pci_enable_device(dev_tel)) return(0); @@ -277,19 +252,15 @@ printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); return(0); } - cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0), - PAGE_SIZE); + cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci"); + if (!cs->hw.teles0.membase) + goto err; printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", pci_resource_start(dev_tel, 0), dev_tel->irq); } else { printk(KERN_WARNING "TelesPCI: No PCI card found\n"); return(0); } -#else - printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); - printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); - return (0); -#endif /* CONFIG_PCI */ /* Initialize Zoran PCI controller */ writel(0x00000000, cs->hw.teles0.membase + 0x28); @@ -299,23 +270,17 @@ writel(0x70000000, cs->hw.teles0.membase + 0x3C); writel(0x61000000, cs->hw.teles0.membase + 0x40); /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ - printk(KERN_INFO - "HiSax: %s config irq:%d mem:%lx\n", + "HiSax: %s config irq:%d mem:%p\n", CardType[cs->typ], cs->irq, cs->hw.teles0.membase); - cs->dc_hw_ops = &isac_ops; - cs->bc_hw_ops = &hscx_ops; - cs->cardmsg = &TelesPCI_card_msg; - cs->irq_func = &telespci_interrupt; cs->irq_flags |= SA_SHIRQ; - ISACVersion(cs, "TelesPCI:"); - if (HscxVersion(cs, "TelesPCI:")) { - printk(KERN_WARNING - "TelesPCI: wrong HSCX versions check IO/MEM addresses\n"); - release_io_telespci(cs); - return (0); - } - return (1); + cs->card_ops = &telespci_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 1; + err: + hisax_release_resources(cs); + return 0; } diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c --- a/drivers/isdn/hisax/w6692.c Mon Jan 13 10:18:07 2003 +++ b/drivers/isdn/hisax/w6692.c Mon Jan 13 10:18:07 2003 @@ -57,7 +57,7 @@ outb(value, cs->hw.w6692.iobase + offset); } -static inline void +static void w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size) { insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); @@ -69,6 +69,10 @@ outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); } +static struct dc_hw_ops w6692_dc_hw_ops = { + .read_fifo = w6692_read_fifo, +}; + static inline u8 w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset) { @@ -81,6 +85,16 @@ outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); } +static void +w6692_bc_read_fifo(struct IsdnCardState *cs, int bchan, u8 *data, int len) +{ + insb(cs->hw.w6692.iobase + W_B_RFIFO + (bchan ? 0x40:0), data, len); +} + +static struct bc_hw_ops w6692_bc_hw_ops = { + .read_fifo = w6692_bc_read_fifo, +}; + static char *W6692Ver[] __initdata = {"W6692 V00", "W6692 V01", "W6692 V10", "W6692 V11"}; @@ -171,30 +185,8 @@ static void W6692_empty_fifo(struct IsdnCardState *cs, int count) { - u8 *ptr; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, "W6692_empty_fifo"); - - if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "W6692_empty_fifo overrun %d", - cs->rcvidx + count); - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK); - cs->rcvidx = 0; - return; - } - ptr = cs->rcvbuf + cs->rcvidx; - cs->rcvidx += count; - w6692_read_fifo(cs, ptr, count); + recv_empty_fifo_d(cs, count); w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK); - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "W6692_empty_fifo cnt %d", count); - QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); - } } static void @@ -221,31 +213,8 @@ static void W6692B_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr; - struct IsdnCardState *cs = bcs->cs; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, "W6692B_empty_fifo"); - - if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "W6692B_empty_fifo: incoming packet too large"); - w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); - bcs->hw.w6692.rcvidx = 0; - return; - } - ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; - bcs->hw.w6692.rcvidx += count; - READW6692BFIFO(cs, bcs->channel, ptr, count); - w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "W6692B_empty_fifo %c cnt %d", - bcs->channel + '1', count); - QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); - } + recv_empty_fifo_b(bcs, count); + w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); } static void @@ -276,7 +245,6 @@ u8 val; u8 r; struct BCState *bcs; - struct sk_buff *skb; int count; bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1); @@ -298,38 +266,18 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 B CRC error"); w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); + bcs->rcvidx = 0; } else { count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); if (count == 0) count = W_B_FIFO_THRESH; W6692B_empty_fifo(bcs, count); - if ((count = bcs->hw.w6692.rcvidx) > 0) { - if (cs->debug & L1_DEB_HSCX_FIFO) - debugl1(cs, "W6692 Bchan Frame %d", count); - if (!(skb = dev_alloc_skb(count))) - printk(KERN_WARNING "W6692: Bchan receive out of memory\n"); - else { - memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count); - skb_queue_tail(&bcs->rqueue, skb); - } - } + recv_rme_b(bcs); } - bcs->hw.w6692.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); } if (val & W_B_EXI_RMR) { /* RMR */ W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); - if (bcs->mode == L1_MODE_TRANS) { - /* receive audio data */ - if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH))) - printk(KERN_WARNING "HiSax: receive out of memory\n"); - else { - memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH); - skb_queue_tail(&bcs->rqueue, skb); - } - bcs->hw.w6692.rcvidx = 0; - sched_b_event(bcs, B_RCVBUFREADY); - } + recv_rpf_b(bcs); } if (val & W_B_EXI_XFR) { /* XFR */ xmit_xpr_b(bcs); @@ -340,11 +288,10 @@ } static void -W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) +w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; u8 val, exval, v1; - struct sk_buff *skb; unsigned int count; int icnt = 5; @@ -369,23 +316,14 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 D-channel ABORT"); w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); + cs->rcvidx = 0; } else { count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); if (count == 0) count = W_D_FIFO_THRESH; W6692_empty_fifo(cs, count); - if ((count = cs->rcvidx) > 0) { - cs->rcvidx = 0; - if (!(skb = alloc_skb(count, GFP_ATOMIC))) - printk(KERN_WARNING "HiSax: D receive out of memory\n"); - else { - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - } - } + recv_rme_d(cs); } - cs->rcvidx = 0; - sched_d_event(cs, D_RCVBUFREADY); } if (val & W_INT_D_RMR) { /* RMR */ W6692_empty_fifo(cs, W_D_FIFO_THRESH); @@ -518,15 +456,11 @@ } } -static void +static int setstack_W6692(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = W6692_l1hw; -} - -static void -DC_Close_W6692(struct IsdnCardState *cs) -{ + return 0; } static void @@ -560,7 +494,7 @@ debugl1(cs, "D-Channel Busy no skb"); } w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ - cs->irq_func(cs->irq, cs, NULL); + cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ } } } @@ -632,52 +566,13 @@ close_w6692state(struct BCState *bcs) { W6692Bmode(bcs, 0, bcs->channel); - if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.w6692.rcvbuf) { - kfree(bcs->hw.w6692.rcvbuf); - bcs->hw.w6692.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - if (bcs->tx_skb) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - } - } + bc_close(bcs); } static int open_w6692state(struct IsdnCardState *cs, struct BCState *bcs) { - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for w6692.rcvbuf\n"); - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); - return (1); - } - if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for bcs->blog\n"); - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); - kfree(bcs->hw.w6692.rcvbuf); - bcs->hw.w6692.rcvbuf = NULL; - return (2); - } - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - } - bcs->tx_skb = NULL; - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->event = 0; - bcs->hw.w6692.rcvidx = 0; - bcs->tx_cnt = 0; - return (0); + return bc_open(bcs); } static int @@ -694,7 +589,8 @@ return (0); } -void resetW6692(struct IsdnCardState *cs) +static int +w6692_reset(struct IsdnCardState *cs) { w6692_write_reg(cs, W_D_CTL, W_D_CTL_SRST); schedule_timeout((10*HZ)/1000); @@ -714,72 +610,81 @@ w6692_write_reg(cs, W_PCTL, 0x80); w6692_write_reg(cs, W_XDATA, 0x00); } + return 0; } -void __init initW6692(struct IsdnCardState *cs, int part) +static void +w6692_init(struct IsdnCardState *cs) { - if (part & 1) { - INIT_WORK(&cs->work, W6692_bh, cs); - cs->setstack_d = setstack_W6692; - cs->DC_Close = DC_Close_W6692; - cs->dbusytimer.function = (void *) dbusy_timer_handler; - cs->dbusytimer.data = (long) cs; - init_timer(&cs->dbusytimer); - resetW6692(cs); - ph_command(cs, W_L1CMD_RST); - cs->dc.w6692.ph_state = W_L1CMD_RST; - W6692_new_ph(cs); - ph_command(cs, W_L1CMD_ECK); + w6692_reset(cs); + ph_command(cs, W_L1CMD_RST); + cs->dc.w6692.ph_state = W_L1CMD_RST; + W6692_new_ph(cs); + ph_command(cs, W_L1CMD_ECK); + + W6692Bmode(cs->bcs, 0, 0); + W6692Bmode(cs->bcs + 1, 0, 0); - cs->bcs[0].BC_SetStack = setstack_w6692; - cs->bcs[1].BC_SetStack = setstack_w6692; - cs->bcs[0].BC_Close = close_w6692state; - cs->bcs[1].BC_Close = close_w6692state; - W6692Bmode(cs->bcs, 0, 0); - W6692Bmode(cs->bcs + 1, 0, 0); - } - if (part & 2) { - /* Reenable all IRQ */ - w6692_write_reg(cs, W_IMASK, 0x18); - w6692_write_reg(cs, W_D_EXIM, 0x00); - w6692_bc_write_reg(cs, 0, W_B_EXIM, 0x00); - w6692_bc_write_reg(cs, 1, W_B_EXIM, 0x00); - /* Reset D-chan receiver and transmitter */ - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); - } + /* Reenable all IRQ */ + w6692_write_reg(cs, W_IMASK, 0x18); + w6692_write_reg(cs, W_D_EXIM, 0x00); + w6692_bc_write_reg(cs, 0, W_B_EXIM, 0x00); + w6692_bc_write_reg(cs, 1, W_B_EXIM, 0x00); + /* Reset D-chan receiver and transmitter */ + w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); } -static int -w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg) + +static void +w6692_release(struct IsdnCardState *cs) { - switch (mt) { - case CARD_RESET: - resetW6692(cs); - return (0); - case CARD_RELEASE: - w6692_write_reg(cs, W_IMASK, 0xff); - release_region(cs->hw.w6692.iobase, 256); - if (cs->subtyp == W6692_USR) { - w6692_write_reg(cs, W_XDATA, 0x04); - } - return (0); - case CARD_INIT: - initW6692(cs, 3); - return (0); - case CARD_TEST: - return (0); - } - return (0); + w6692_write_reg(cs, W_IMASK, 0xff); + if (cs->subtyp == W6692_USR) + w6692_write_reg(cs, W_XDATA, 0x04); + hisax_release_resources(cs); } +static struct card_ops w6692_ops = { + .init = w6692_init, + .reset = w6692_reset, + .release = w6692_release, + .irq_func = w6692_interrupt, +}; + +static struct dc_l1_ops w6692_dc_l1_ops = { + .fill_fifo = W6692_fill_fifo, + .open = setstack_W6692, + .bh_func = W6692_bh, + .dbusy_func = dbusy_timer_handler, +}; + static struct bc_l1_ops w6692_bc_l1_ops = { .fill_fifo = W6692B_fill_fifo, + .open = setstack_w6692, + .close = close_w6692state, }; static int id_idx ; static struct pci_dev *dev_w6692 __initdata = NULL; +static int +w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops, + struct bc_hw_ops *bc_ops) +{ + cs->dc_hw_ops = dc_ops; + cs->bc_hw_ops = bc_ops; + dc_l1_init(cs, &w6692_dc_l1_ops); + cs->bc_l1_ops = &w6692_bc_l1_ops; + W6692Version(cs, "W6692:"); + printk(KERN_INFO "W6692 ISTA=0x%X\n", w6692_read_reg(cs, W_ISTA)); + printk(KERN_INFO "W6692 IMASK=0x%X\n", w6692_read_reg(cs, W_IMASK)); + printk(KERN_INFO "W6692 D_EXIR=0x%X\n", w6692_read_reg(cs, W_D_EXIR)); + printk(KERN_INFO "W6692 D_EXIM=0x%X\n", w6692_read_reg(cs, W_D_EXIM)); + printk(KERN_INFO "W6692 D_RSTA=0x%X\n", w6692_read_reg(cs, W_D_RSTA)); + return 0; +} + int __init setup_w6692(struct IsdnCard *card) { @@ -794,13 +699,6 @@ #endif strcpy(tmp, w6692_revision); printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_W6692) - return (0); -#if CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "W6692: no PCI bus present\n"); - return (0); - } while (id_list[id_idx].vendor_id) { dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, @@ -844,36 +742,16 @@ printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, pci_ioaddr, pci_irq); - if (!request_region((cs->hw.w6692.iobase), 256, - id_list[cs->subtyp].card_name)) { - printk(KERN_WARNING - "HiSax: %s I/O ports %x-%x already in use\n", - id_list[cs->subtyp].card_name, - cs->hw.w6692.iobase, - cs->hw.w6692.iobase + 255); - return (0); - } -#else - printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); - printk(KERN_WARNING "HiSax: W6692 unable to config\n"); - return (0); -#endif /* CONFIG_PCI */ - + if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name)) + return 0; + printk(KERN_INFO "HiSax: %s config irq:%d I/O:%x\n", id_list[cs->subtyp].card_name, cs->irq, cs->hw.w6692.iobase); - cs->bc_l1_ops = &w6692_bc_l1_ops; - cs->DC_Send_Data = &W6692_fill_fifo; - cs->cardmsg = &w6692_card_msg; - cs->irq_func = &W6692_interrupt; + cs->card_ops = &w6692_ops; + w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops); cs->irq_flags |= SA_SHIRQ; - W6692Version(cs, "W6692:"); - printk(KERN_INFO "W6692 ISTA=0x%X\n", w6692_read_reg(cs, W_ISTA)); - printk(KERN_INFO "W6692 IMASK=0x%X\n", w6692_read_reg(cs, W_IMASK)); - printk(KERN_INFO "W6692 D_EXIR=0x%X\n", w6692_read_reg(cs, W_D_EXIR)); - printk(KERN_INFO "W6692 D_EXIM=0x%X\n", w6692_read_reg(cs, W_D_EXIM)); - printk(KERN_INFO "W6692 D_RSTA=0x%X\n", w6692_read_reg(cs, W_D_RSTA)); return (1); } diff -Nru a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h --- a/drivers/isdn/hisax/w6692.h Mon Jan 13 10:18:05 2003 +++ b/drivers/isdn/hisax/w6692.h Mon Jan 13 10:18:05 2003 @@ -18,9 +18,6 @@ /* B-channel FIFO read/write routines */ -#define READW6692BFIFO(cs,bchan,ptr,count) \ - insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count) - #define WRITEW6692BFIFO(cs,bchan,ptr,count) \ outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count) diff -Nru a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c --- a/drivers/isdn/i4l/isdn_tty.c Mon Jan 13 10:18:06 2003 +++ b/drivers/isdn/i4l/isdn_tty.c Mon Jan 13 10:18:06 2003 @@ -1876,7 +1876,7 @@ * line status register. */ if (info->flags & ISDN_ASYNC_INITIALIZED) { - tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ + tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -1901,7 +1901,7 @@ tty->closing = 0; if (info->blocked_open) { set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(50); + schedule_timeout(HZ/2); wake_up_interruptible(&info->open_wait); } info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE | diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Mon Jan 13 10:18:05 2003 +++ b/drivers/md/md.c Mon Jan 13 10:18:05 2003 @@ -2838,16 +2838,18 @@ mdidx(mddev), mdidx(mddev2)); if (mddev < mddev2) {/* arbitrarily yield */ mddev->curr_resync = 1; - yield(); + wake_up(&resync_wait); } if (wait_event_interruptible(resync_wait, - mddev2->curr_resync < 2)) { + mddev2->curr_resync < mddev->curr_resync)) { flush_curr_signals(); err = -EINTR; mddev_put(mddev2); goto skip; } } + if (mddev->curr_resync == 1) + break; } } while (mddev->curr_resync < 2); diff -Nru a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c --- a/drivers/media/radio/radio-cadet.c Mon Jan 13 10:18:06 2003 +++ b/drivers/media/radio/radio-cadet.c Mon Jan 13 10:18:06 2003 @@ -47,7 +47,7 @@ static int cadet_lock=0; static int cadet_probe(void); -static struct pci_dev *dev; +static struct pnp_dev *dev = NULL; static int isapnp_cadet_probe(void); /* @@ -543,23 +543,26 @@ static int isapnp_cadet_probe(void) { - dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'), - ISAPNP_FUNCTION(0x0c24), NULL); + dev = pnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'), + ISAPNP_FUNCTION(0x0c24), NULL); if (!dev) return -ENODEV; - if (dev->prepare(dev)<0) + if (pnp_device_attach(dev) < 0) return -EAGAIN; - if (!(dev->resource[0].flags & IORESOURCE_IO)) + if (pnp_activate_dev(dev, NULL) < 0) { + printk ("radio-cadet: pnp configure failed (out of resources?)\n"); + pnp_device_detach(dev); + return -EIO; + } + if (!pnp_port_valid(dev, 0)) { + pnp_device_detach(dev); return -ENODEV; - if (dev->activate(dev)<0) { - printk ("radio-cadet: isapnp configure failed (out of resources?)\n"); - return -ENOMEM; } - io = dev->resource[0].start; + io = pnp_port_start(dev, 0); - printk ("radio-cadet: ISAPnP reports card at %#x\n", io); + printk ("radio-cadet: PnP reports device at %#x\n", io); return io; } @@ -645,7 +648,7 @@ release_region(io,2); if (dev) - dev->deactivate(dev); + pnp_device_detach(dev); } module_init(cadet_init); diff -Nru a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c --- a/drivers/media/radio/radio-sf16fmi.c Mon Jan 13 10:18:07 2003 +++ b/drivers/media/radio/radio-sf16fmi.c Mon Jan 13 10:18:07 2003 @@ -36,7 +36,7 @@ static int io = -1; static int radio_nr = -1; -static struct pci_dev *dev = NULL; +static struct pnp_dev *dev = NULL; static struct semaphore lock; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ @@ -253,24 +253,27 @@ int i = 0; while (id_table[i].card_vendor != 0 && dev == NULL) { - dev = isapnp_find_dev(NULL, id_table[i].vendor, - id_table[i].function, NULL); + dev = pnp_find_dev(NULL, id_table[i].vendor, + id_table[i].function, NULL); i++; } if (!dev) return -ENODEV; - if (dev->prepare(dev) < 0) + if (pnp_device_attach(dev) < 0) return -EAGAIN; - if (!(dev->resource[0].flags & IORESOURCE_IO)) - return -ENODEV; - if (dev->activate(dev) < 0) { - printk ("radio-sf16fmi: ISAPnP configure failed (out of resources?)\n"); + if (pnp_activate_dev(dev, NULL) < 0) { + printk ("radio-sf16fmi: PnP configure failed (out of resources?)\n"); + pnp_device_detach(dev); return -ENOMEM; } + if (!pnp_port_valid(dev, 0)) { + pnp_device_detach(dev); + return -ENODEV; + } - i = dev->resource[0].start; - printk ("radio-sf16fmi: ISAPnP reports card at %#x\n", i); + i = pnp_port_start(dev, 0); + printk ("radio-sf16fmi: PnP reports card at %#x\n", i); return i; } @@ -320,7 +323,7 @@ video_unregister_device(&fmi_radio); release_region(io, 2); if (dev) - dev->deactivate(dev); + pnp_device_detach(dev); } module_init(fmi_init); diff -Nru a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c --- a/drivers/mtd/devices/blkmtd.c Mon Jan 13 10:18:05 2003 +++ b/drivers/mtd/devices/blkmtd.c Mon Jan 13 10:18:05 2003 @@ -1219,7 +1219,7 @@ INIT_LIST_HEAD(&mtd_rawdevice->as.dirty_pages); INIT_LIST_HEAD(&mtd_rawdevice->as.locked_pages); mtd_rawdevice->as.host = NULL; - spin_lock_init(&(mtd_rawdevice->as.i_shared_lock)); + init_MUTEX(&(mtd_rawdevice->as.i_shared_sem)); mtd_rawdevice->as.a_ops = &blkmtd_aops; INIT_LIST_HEAD(&mtd_rawdevice->as.i_mmap); diff -Nru a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c --- a/drivers/mtd/maps/sa1100-flash.c Mon Jan 13 10:18:05 2003 +++ b/drivers/mtd/maps/sa1100-flash.c Mon Jan 13 10:18:05 2003 @@ -74,15 +74,15 @@ } static struct map_info sa1100_map __initdata = { - name: "SA1100 flash", - read8: sa1100_read8, - read16: sa1100_read16, - read32: sa1100_read32, - copy_from: sa1100_copy_from, - write8: sa1100_write8, - write16: sa1100_write16, - write32: sa1100_write32, - copy_to: sa1100_copy_to, + .name = "SA1100 flash", + .read8 = sa1100_read8, + .read16 = sa1100_read16, + .read32 = sa1100_read32, + .copy_from = sa1100_copy_from, + .write8 = sa1100_write8, + .write16 = sa1100_write16, + .write32 = sa1100_write32, + .copy_to = sa1100_copy_to, }; @@ -108,24 +108,24 @@ #ifdef CONFIG_SA1100_ADSBITSY static struct mtd_partition adsbitsy_partitions[] = { { - name: "bootROM", - size: 0x80000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "zImage", - size: 0x100000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "ramdisk.gz", - size: 0x300000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "User FS", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .name = "bootROM", + .size = 0x80000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "zImage", + .size = 0x100000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "ramdisk.gz", + .size = 0x300000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "User FS", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; #endif @@ -134,38 +134,38 @@ /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */ static struct mtd_partition assabet4_partitions[] = { { - name: "bootloader", - size: 0x00020000, - offset: 0, - mask_flags: MTD_WRITEABLE, - }, { - name: "bootloader params", - size: 0x00020000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "jffs", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .name = "bootloader", + .size = 0x00020000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "bootloader params", + .size = 0x00020000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "jffs", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; /* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */ static struct mtd_partition assabet5_partitions[] = { { - name: "bootloader", - size: 0x00040000, - offset: 0, - mask_flags: MTD_WRITEABLE, - }, { - name: "bootloader params", - size: 0x00040000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "jffs", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .name = "bootloader", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "bootloader params", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "jffs", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; @@ -180,21 +180,21 @@ */ static struct mtd_partition badge4_partitions[] = { { - name: "BLOB boot loader", - offset: 0, - size: 0x0000A000 - }, { - name: "params", - offset: MTDPART_OFS_APPEND, - size: 0x00006000 - }, { - name: "kernel", - offset: MTDPART_OFS_APPEND, - size: 0x00100000 - }, { - name: "root", - offset: MTDPART_OFS_APPEND, - size: MTDPART_SIZ_FULL + .name = "BLOB boot loader", + .offset = 0, + .size = 0x0000A000 + }, { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = 0x00006000 + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 0x00100000 + }, { + .name = "root", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL } }; #endif @@ -204,41 +204,41 @@ #ifdef CONFIG_SA1100_CERF_FLASH_32MB static struct mtd_partition cerf_partitions[] = { { - name: "firmware", - size: 0x00040000, - offset: 0, - }, { - name: "params", - size: 0x00040000, - offset: 0x00040000, - }, { - name: "kernel", - size: 0x00100000, - offset: 0x00080000, - }, { - name: "rootdisk", - size: 0x01E80000, - offset: 0x00180000, + .name = "firmware", + .size = 0x00040000, + .offset = 0, + }, { + .name = "params", + .size = 0x00040000, + .offset = 0x00040000, + }, { + .name = "kernel", + .size = 0x00100000, + .offset = 0x00080000, + }, { + .name = "rootdisk", + .size = 0x01E80000, + .offset = 0x00180000, } }; #elif defined CONFIG_SA1100_CERF_FLASH_16MB static struct mtd_partition cerf_partitions[] = { { - name: "firmware", - size: 0x00020000, - offset: 0, - }, { - name: "params", - size: 0x00020000, - offset: 0x00020000, - }, { - name: "kernel", - size: 0x00100000, - offset: 0x00040000, - }, { - name: "rootdisk", - size: 0x00EC0000, - offset: 0x00140000, + .name = "firmware", + .size = 0x00020000, + .offset = 0, + }, { + .name = "params", + .size = 0x00020000, + .offset = 0x00020000, + }, { + .name = "kernel", + .size = 0x00100000, + .offset = 0x00040000, + }, { + .name = "rootdisk", + .size = 0x00EC0000, + .offset = 0x00140000, } }; #elif defined CONFIG_SA1100_CERF_FLASH_8MB @@ -251,36 +251,36 @@ #ifdef CONFIG_SA1100_CONSUS static struct mtd_partition consus_partitions[] = { { - name: "Consus boot firmware", - offset: 0, - size: 0x00040000, - mask_flags: MTD_WRITABLE, /* force read-only */ - }, { - name: "Consus kernel", - offset: 0x00040000, - size: 0x00100000, - mask_flags: 0, + .name = "Consus boot firmware", + .offset = 0, + .size = 0x00040000, + .mask_flags = MTD_WRITABLE, /* force read-only */ + }, { + .name = "Consus kernel", + .offset = 0x00040000, + .size = 0x00100000, + .mask_flags = 0, }, { - name: "Consus disk", - offset: 0x00140000, + .name = "Consus disk", + .offset = 0x00140000, /* The rest (up to 16M) for jffs. We could put 0 and make it find the size automatically, but right now i have 32 megs. jffs will use all 32 megs if given the chance, and this leads to horrible problems when you try to re-flash the image because blob won't erase the whole partition. */ - size: 0x01000000 - 0x00140000, - mask_flags: 0, + .size = 0x01000000 - 0x00140000, + .mask_flags = 0, }, { /* this disk is a secondary disk, which can be used as needed, for simplicity, make it the size of the other consus partition, although realistically it could be the remainder of the disk (depending on the file system used) */ - name: "Consus disk2", - offset: 0x01000000, - size: 0x01000000 - 0x00140000, - mask_flags: 0, + .name = "Consus disk2", + .offset = 0x01000000, + .size = 0x01000000 - 0x00140000, + .mask_flags = 0, } }; #endif @@ -290,45 +290,45 @@ #define FLEXANET_FLASH_SIZE 0x02000000 static struct mtd_partition flexanet_partitions[] = { { - name: "bootloader", - size: 0x00040000, - offset: 0, - mask_flags: MTD_WRITEABLE, - }, { - name: "bootloader params", - size: 0x00040000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "kernel", - size: 0x000C0000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "altkernel", - size: 0x000C0000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "root", - size: 0x00400000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "free1", - size: 0x00300000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "free2", - size: 0x00300000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, - }, { - name: "free3", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, + .name = "bootloader", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "bootloader params", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "kernel", + .size = 0x000C0000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "altkernel", + .size = 0x000C0000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "root", + .size = 0x00400000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "free1", + .size = 0x00300000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "free2", + .size = 0x00300000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "free3", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, } }; #endif @@ -337,48 +337,48 @@ static struct mtd_partition freebird_partitions[] = { #if CONFIG_SA1100_FREEBIRD_NEW { - name: "firmware", - size: 0x00040000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "kernel", - size: 0x00080000, - offset: 0x00040000, - }, { - name: "params", - size: 0x00040000, - offset: 0x000C0000, - }, { - name: "initrd", - size: 0x00100000, - offset: 0x00100000, - }, { - name: "root cramfs", - size: 0x00300000, - offset: 0x00200000, - }, { - name: "usr cramfs", - size: 0x00C00000, - offset: 0x00500000, - }, { - name: "local", - size: MTDPART_SIZ_FULL, - offset: 0x01100000, + .name = "firmware", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "kernel", + .size = 0x00080000, + .offset = 0x00040000, + }, { + .name = "params", + .size = 0x00040000, + .offset = 0x000C0000, + }, { + .name = "initrd", + .size = 0x00100000, + .offset = 0x00100000, + }, { + .name = "root cramfs", + .size = 0x00300000, + .offset = 0x00200000, + }, { + .name = "usr cramfs", + .size = 0x00C00000, + .offset = 0x00500000, + }, { + .name = "local", + .size = MTDPART_SIZ_FULL, + .offset = 0x01100000, } #else { - size: 0x00040000, - offset: 0, + .size = 0x00040000, + .offset = 0, }, { - size: 0x000c0000, - offset: MTDPART_OFS_APPEND, + .size = 0x000c0000, + .offset = MTDPART_OFS_APPEND, }, { - size: 0x00400000, - offset: MTDPART_OFS_APPEND, + .size = 0x00400000, + .offset = MTDPART_OFS_APPEND, }, { - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } #endif }; @@ -389,29 +389,29 @@ static struct mtd_partition frodo_partitions[] = { { - name: "bootloader", - size: 0x00040000, - offset: 0x00000000, - mask_flags: MTD_WRITEABLE - }, { - name: "bootloader params", - size: 0x00040000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE - }, { - name: "kernel", - size: 0x00100000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE - }, { - name: "ramdisk", - size: 0x00400000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE - }, { - name: "file system", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND + .name = "bootloader", + .size = 0x00040000, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE + }, { + .name = "bootloader params", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE + }, { + .name = "kernel", + .size = 0x00100000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE + }, { + .name = "ramdisk", + .size = 0x00400000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE + }, { + .name = "file system", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND } }; #endif @@ -419,19 +419,19 @@ #ifdef CONFIG_SA1100_GRAPHICSCLIENT static struct mtd_partition graphicsclient_partitions[] = { { - name: "zImage", - size: 0x100000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "ramdisk.gz", - size: 0x300000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "User FS", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .name = "zImage", + .size = 0x100000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "ramdisk.gz", + .size = 0x300000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "User FS", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; #endif @@ -439,21 +439,21 @@ #ifdef CONFIG_SA1100_GRAPHICSMASTER static struct mtd_partition graphicsmaster_partitions[] = { { - name: "zImage", - size: 0x100000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ + .name = "zImage", + .size = 0x100000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ }, { - name: "ramdisk.gz", - size: 0x300000, - offset: MTDPART_OFS_APPEND, - mask_flags: MTD_WRITEABLE, /* force read-only */ + .name = "ramdisk.gz", + .size = 0x300000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, /* force read-only */ }, { - name: "User FS", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .name = "User FS", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; #endif @@ -461,44 +461,44 @@ #ifdef CONFIG_SA1100_H3XXX static struct mtd_partition h3xxx_partitions[] = { { - name: "H3XXX boot firmware", - size: 0x00040000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ + .name = "H3XXX boot firmware", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ }, { #ifdef CONFIG_MTD_2PARTS_IPAQ - name: "H3XXX root jffs2", - size: MTDPART_SIZ_FULL, - offset: 0x00040000, + .name = "H3XXX root jffs2", + .size = MTDPART_SIZ_FULL, + .offset = 0x00040000, #else - name: "H3XXX kernel", - size: 0x00080000, - offset: 0x00040000, - }, { - name: "H3XXX params", - size: 0x00040000, - offset: 0x000C0000, + .name = "H3XXX kernel", + .size = 0x00080000, + .offset = 0x00040000, + }, { + .name = "H3XXX params", + .size = 0x00040000, + .offset = 0x000C0000, }, { #ifdef CONFIG_JFFS2_FS - name: "H3XXX root jffs2", - size: MTDPART_SIZ_FULL, - offset: 0x00100000, + .name = "H3XXX root jffs2", + .size = MTDPART_SIZ_FULL, + .offset = 0x00100000, #else - name: "H3XXX initrd", - size: 0x00100000, - offset: 0x00100000, - }, { - name: "H3XXX root cramfs", - size: 0x00300000, - offset: 0x00200000, - }, { - name: "H3XXX usr cramfs", - size: 0x00800000, - offset: 0x00500000, - }, { - name: "H3XXX usr local", - size: MTDPART_SIZ_FULL, - offset: 0x00d00000, + .name = "H3XXX initrd", + .size = 0x00100000, + .offset = 0x00100000, + }, { + .name = "H3XXX root cramfs", + .size = 0x00300000, + .offset = 0x00200000, + }, { + .name = "H3XXX usr cramfs", + .size = 0x00800000, + .offset = 0x00500000, + }, { + .name = "H3XXX usr local", + .size = MTDPART_SIZ_FULL, + .offset = 0x00d00000, #endif #endif } @@ -515,16 +515,16 @@ #ifdef CONFIG_SA1100_HUW_WEBPANEL static struct mtd_partition huw_webpanel_partitions[] = { { - name: "Loader", - size: 0x00040000, - offset: 0, - }, { - name: "Sector 1", - size: 0x00040000, - offset: MTDPART_OFS_APPEND, + .name = "Loader", + .size = 0x00040000, + .offset = 0, + }, { + .name = "Sector 1", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, }, { - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; #endif @@ -532,38 +532,38 @@ #ifdef CONFIG_SA1100_JORNADA720 static struct mtd_partition jornada720_partitions[] = { { - name: "JORNADA720 boot firmware", - size: 0x00040000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ + .name = "JORNADA720 boot firmware", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ }, { - name: "JORNADA720 kernel", - size: 0x000c0000, - offset: 0x00040000, + .name = "JORNADA720 kernel", + .size = 0x000c0000, + .offset = 0x00040000, }, { - name: "JORNADA720 params", - size: 0x00040000, - offset: 0x00100000, + .name = "JORNADA720 params", + .size = 0x00040000, + .offset = 0x00100000, }, { - name: "JORNADA720 initrd", - size: 0x00100000, - offset: 0x00140000, + .name = "JORNADA720 initrd", + .size = 0x00100000, + .offset = 0x00140000, }, { - name: "JORNADA720 root cramfs", - size: 0x00300000, - offset: 0x00240000, + .name = "JORNADA720 root cramfs", + .size = 0x00300000, + .offset = 0x00240000, }, { - name: "JORNADA720 usr cramfs", - size: 0x00800000, - offset: 0x00540000, + .name = "JORNADA720 usr cramfs", + .size = 0x00800000, + .offset = 0x00540000, }, { - name: "JORNADA720 usr local", - size: 0 /* will expand to the end of the flash */ - offset: 0x00d00000, + .name = "JORNADA720 usr local", + .size = 0, /* will expand to the end of the flash */ + .offset = 0x00d00000, } }; -static void jornada720_set_vpp(int vpp) +static void jornada720_set_vpp(struct map_info *map, int vpp) { if (vpp) PPSR |= 0x80; @@ -578,22 +578,22 @@ #ifdef CONFIG_SA1100_PANGOLIN static struct mtd_partition pangolin_partitions[] = { { - name: "boot firmware", - size: 0x00080000, - offset: 0x00000000, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "kernel", - size: 0x00100000, - offset: 0x00080000, - }, { - name: "initrd", - size: 0x00280000, - offset: 0x00180000, - }, { - name: "initrd-test", - size: 0x03C00000, - offset: 0x00400000, + .name = "boot firmware", + .size = 0x00080000, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "kernel", + .size = 0x00100000, + .offset = 0x00080000, + }, { + .name = "initrd", + .size = 0x00280000, + .offset = 0x00180000, + }, { + .name = "initrd-test", + .size = 0x03C00000, + .offset = 0x00400000, } }; #endif @@ -602,22 +602,22 @@ /* erase size is 0x40000 == 256k partitions have to have this boundary */ static struct mtd_partition system3_partitions[] = { { - name: "BLOB", - size: 0x00040000, - offset: 0x00000000, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "config", - size: 0x00040000, - offset: MTDPART_OFS_APPEND, - }, { - name: "kernel", - size: 0x00100000, - offset: MTDPART_OFS_APPEND, - }, { - name: "root", - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .name = "BLOB", + .size = 0x00040000, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "config", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "kernel", + .size = 0x00100000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "root", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; #endif @@ -625,19 +625,19 @@ #ifdef CONFIG_SA1100_SHANNON static struct mtd_partition shannon_partitions[] = { { - name: "BLOB boot loader", - offset: 0, - size: 0x20000 + .name = "BLOB boot loader", + .offset = 0, + .size = 0x20000 }, { - name: "kernel", - offset: MTDPART_OFS_APPEND, - size: 0xe0000 + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 0xe0000 }, { - name: "initrd", - offset: MTDPART_OFS_APPEND, - size: MTDPART_SIZ_FULL + .name = "initrd", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL } }; @@ -646,17 +646,17 @@ #ifdef CONFIG_SA1100_SHERMAN static struct mtd_partition sherman_partitions[] = { { - size: 0x50000, - offset: 0, + .size = 0x50000, + .offset = 0, }, { - size: 0x70000, - offset: MTDPART_OFS_APPEND, + .size = 0x70000, + .offset = MTDPART_OFS_APPEND, }, { - size: 0x600000, - offset: MTDPART_OFS_APPEND, + .size = 0x600000, + .offset = MTDPART_OFS_APPEND, }, { - size: 0xA0000, - offset: MTDPART_OFS_APPEND, + .size = 0xA0000, + .offset = MTDPART_OFS_APPEND, } }; #endif @@ -664,35 +664,35 @@ #ifdef CONFIG_SA1100_SIMPAD static struct mtd_partition simpad_partitions[] = { { - name: "SIMpad boot firmware", - size: 0x00080000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "SIMpad kernel", - size: 0x00100000, - offset: 0x00080000, + .name = "SIMpad boot firmware", + .size = 0x00080000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "SIMpad kernel", + .size = 0x00100000, + .offset = 0x00080000, }, { #ifdef CONFIG_JFFS2_FS - name: "SIMpad root jffs2", - size: MTDPART_SIZ_FULL, - offset: 0x00180000, + .name = "SIMpad root jffs2", + .size = MTDPART_SIZ_FULL, + .offset = 0x00180000, #else - name: "SIMpad initrd", - size: 0x00300000, - offset: 0x00180000, - }, { - name: "SIMpad root cramfs", - size: 0x00300000, - offset: 0x00480000, - }, { - name: "SIMpad usr cramfs", - size: 0x005c0000, - offset: 0x00780000, - }, { - name: "SIMpad usr local", - size: MTDPART_SIZ_FULL, - offset: 0x00d40000, + .name = "SIMpad initrd", + .size = 0x00300000, + .offset = 0x00180000, + }, { + .name = "SIMpad root cramfs", + .size = 0x00300000, + .offset = 0x00480000, + }, { + .name = "SIMpad usr cramfs", + .size = 0x005c0000, + .offset = 0x00780000, + }, { + .name = "SIMpad usr local", + .size = MTDPART_SIZ_FULL, + .offset = 0x00d40000, #endif } }; @@ -701,39 +701,39 @@ #ifdef CONFIG_SA1100_STORK static struct mtd_partition stork_partitions[] = { { - name: "STORK boot firmware", - size: 0x00040000, - offset: 0, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "STORK params", - size: 0x00040000, - offset: 0x00040000, - }, { - name: "STORK kernel", - size: 0x00100000, - offset: 0x00080000, + .name = "STORK boot firmware", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "STORK params", + .size = 0x00040000, + .offset = 0x00040000, + }, { + .name = "STORK kernel", + .size = 0x00100000, + .offset = 0x00080000, }, { #ifdef CONFIG_JFFS2_FS - name: "STORK root jffs2", - offset: 0x00180000, - size: MTDPART_SIZ_FULL, + .name = "STORK root jffs2", + .offset = 0x00180000, + .size = MTDPART_SIZ_FULL, #else - name: "STORK initrd", - size: 0x00100000, - offset: 0x00180000, - }, { - name: "STORK root cramfs", - size: 0x00300000, - offset: 0x00280000, - }, { - name: "STORK usr cramfs", - size: 0x00800000, - offset: 0x00580000, - }, { - name: "STORK usr local", - offset: 0x00d80000, - size: MTDPART_SIZ_FULL, + .name = "STORK initrd", + .size = 0x00100000, + .offset = 0x00180000, + }, { + .name = "STORK root cramfs", + .size = 0x00300000, + .offset = 0x00280000, + }, { + .name = "STORK usr cramfs", + .size = 0x00800000, + .offset = 0x00580000, + }, { + .name = "STORK usr local", + .offset = 0x00d80000, + .size = MTDPART_SIZ_FULL, #endif } }; @@ -742,16 +742,16 @@ #ifdef CONFIG_SA1100_TRIZEPS static struct mtd_partition trizeps_partitions[] = { { - name: "Bootloader & the kernel", - size: 0x00200000, - offset: 0, - }, { - name: "Data", - size: 0x00400000, - offset: MTDPART_OFS_APPEND, + .name = "Bootloader & the kernel", + .size = 0x00200000, + .offset = 0, + }, { + .name = "Data", + .size = 0x00400000, + .offset = MTDPART_OFS_APPEND, }, { - size: MTDPART_SIZ_FULL, - offset: MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; #endif @@ -759,22 +759,22 @@ #ifdef CONFIG_SA1100_YOPY static struct mtd_partition yopy_partitions[] = { { - name: "boot firmware", - size: 0x00040000, - offset: 0x00000000, - mask_flags: MTD_WRITEABLE, /* force read-only */ - }, { - name: "kernel", - size: 0x00080000, - offset: 0x00080000, - }, { - name: "initrd", - size: 0x00300000, - offset: 0x00100000, - }, { - name: "root", - size: 0x01000000, - offset: 0x00400000, + .name = "boot firmware", + .size = 0x00040000, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "kernel", + .size = 0x00080000, + .offset = 0x00080000, + }, { + .name = "initrd", + .size = 0x00300000, + .offset = 0x00100000, + }, { + .name = "root", + .size = 0x01000000, + .offset = 0x00400000, } }; #endif diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c --- a/drivers/net/3c501.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/3c501.c Mon Jan 13 10:18:05 2003 @@ -36,6 +36,10 @@ Check up pass for 2.5. Nothing significant changed 20021009 Alan Cox + + Fixed zero fill corner case + 20030104 Alan Cox + For the avoidance of doubt the "preferred form" of this code is one which is in an open non patent encumbered format. Where cryptographic key signing @@ -421,8 +425,15 @@ do { - int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); + int len = skb->len; + int pad = 0; + int gp_start; unsigned char *buf = skb->data; + + if (len < ETH_ZLEN) + pad = ETH_ZLEN - len; + + gp_start = 0x800 - ( len + pad ); lp->tx_pkt_start = gp_start; lp->collisions = 0; @@ -450,7 +461,11 @@ outw(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */ outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */ - outsb(DATAPORT,buf,skb->len); /* load buffer (usual thing each byte increments the pointer) */ + outsb(DATAPORT,buf,len); /* load buffer (usual thing each byte increments the pointer) */ + if (pad) { + while(pad--) /* Zero fill buffer tail */ + outb(0, DATAPORT); + } outw(gp_start, GP_LOW); /* the board reuses the same register */ if(lp->loading != 2) diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c --- a/drivers/net/3c505.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/3c505.c Mon Jan 13 10:18:07 2003 @@ -1037,8 +1037,9 @@ adapter->current_dma.direction = 1; adapter->current_dma.start_time = jiffies; - if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS) { + if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) { memcpy(adapter->dma_buffer, skb->data, nlen); + memset(adapter->dma_buffer+skb->len, 0, nlen-skb->len); target = isa_virt_to_bus(adapter->dma_buffer); } else { diff -Nru a/drivers/net/3c507.c b/drivers/net/3c507.c --- a/drivers/net/3c507.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/3c507.c Mon Jan 13 10:18:07 2003 @@ -297,7 +297,7 @@ static struct net_device_stats *el16_get_stats(struct net_device *dev); static void el16_tx_timeout (struct net_device *dev); -static void hardware_send_packet(struct net_device *dev, void *buf, short length); +static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad); static void init_82586_mem(struct net_device *dev); static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); @@ -499,7 +499,7 @@ /* Disable the 82586's input to the interrupt line. */ outb (0x80, ioaddr + MISC_CTRL); - hardware_send_packet (dev, buf, length); + hardware_send_packet (dev, buf, skb->len, length - skb->len); dev->trans_start = jiffies; /* Enable the 82586 interrupt input. */ @@ -752,12 +752,13 @@ return; } -static void hardware_send_packet(struct net_device *dev, void *buf, short length) +static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad) { struct net_local *lp = (struct net_local *)dev->priv; short ioaddr = dev->base_addr; ushort tx_block = lp->tx_head; unsigned long write_ptr = dev->mem_start + tx_block; + static char padding[ETH_ZLEN]; /* Set the write pointer to the Tx block, and put out the header. */ isa_writew(0x0000,write_ptr); /* Tx status */ @@ -766,7 +767,7 @@ isa_writew(tx_block+8,write_ptr+=2); /* Data Buffer offset. */ /* Output the data buffer descriptor. */ - isa_writew(length | 0x8000,write_ptr+=2); /* Byte count parameter. */ + isa_writew((pad + length) | 0x8000,write_ptr+=2); /* Byte count parameter. */ isa_writew(-1,write_ptr+=2); /* No next data buffer. */ isa_writew(tx_block+22+SCB_BASE,write_ptr+=2); /* Buffer follows the NoOp command. */ isa_writew(0x0000,write_ptr+=2); /* Buffer address high bits (always zero). */ @@ -778,6 +779,8 @@ /* Output the packet at the write pointer. */ isa_memcpy_toio(write_ptr+2, buf, length); + if (pad) + isa_memcpy_toio(write_ptr+length+2, padding, pad); /* Set the old command link pointing to this send packet. */ isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link); diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c --- a/drivers/net/3c509.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/3c509.c Mon Jan 13 10:18:05 2003 @@ -167,6 +167,9 @@ #ifdef CONFIG_PM struct pm_dev *pmdev; #endif +#ifdef __ISAPNP__ + struct pnp_dev *pnpdev; +#endif }; static int id_port __initdata = 0x110; /* Start with 0x110 to avoid new sound cards.*/ static struct net_device *el3_root_dev; @@ -247,6 +250,7 @@ int mca_slot = -1; #ifdef __ISAPNP__ static int pnp_cards; + struct pnp_dev *idev = NULL; #endif /* __ISAPNP__ */ if (dev) SET_MODULE_OWNER(dev); @@ -356,23 +360,26 @@ goto no_pnp; for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) { - struct pci_dev *idev = NULL; int j; - while ((idev = isapnp_find_dev(NULL, - el3_isapnp_adapters[i].vendor, - el3_isapnp_adapters[i].function, - idev))) { - idev->prepare(idev); - /* Deactivation is needed if the driver was called - with "nopnp=1" before, does not harm if not. */ - idev->deactivate(idev); - idev->activate(idev); - if (!idev->resource[0].start || check_region(idev->resource[0].start, EL3_IO_EXTENT)) + while ((idev = pnp_find_dev(NULL, + el3_isapnp_adapters[i].vendor, + el3_isapnp_adapters[i].function, + idev))) { + if (pnp_device_attach(idev) < 0) continue; - ioaddr = idev->resource[0].start; - if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP")) + if (pnp_activate_dev(idev, NULL) < 0) { + __again: + pnp_device_detach(idev); + continue; + } + if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) + goto __again; + ioaddr = pnp_port_start(idev, 0); + if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP")) { + pnp_device_detach(idev); return -EBUSY; - irq = idev->irq_resource[0].start; + } + irq = pnp_irq(idev, 0); if (el3_debug > 3) printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n", (char*) el3_isapnp_adapters[i].driver_data, ioaddr, irq); @@ -531,6 +538,9 @@ memset(dev->priv, 0, sizeof(struct el3_private)); lp = dev->priv; +#ifdef __ISAPNP__ + lp->pnpdev = idev; +#endif lp->mca_slot = mca_slot; lp->next_dev = el3_root_dev; spin_lock_init(&lp->lock); @@ -1466,6 +1476,10 @@ next_dev = lp->next_dev; unregister_netdev(el3_root_dev); release_region(el3_root_dev->base_addr, EL3_IO_EXTENT); +#ifdef __ISAPNP__ + if (lp->pnpdev) + pnp_device_detach(lp->pnpdev); +#endif kfree(el3_root_dev); el3_root_dev = next_dev; } diff -Nru a/drivers/net/3c515.c b/drivers/net/3c515.c --- a/drivers/net/3c515.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/3c515.c Mon Jan 13 10:18:05 2003 @@ -460,33 +460,34 @@ if(nopnp == 1) goto no_pnp; for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) { - struct pci_dev *idev = NULL; + struct pnp_dev *idev = NULL; int irq; - while((idev = isapnp_find_dev(NULL, - corkscrew_isapnp_adapters[i].vendor, - corkscrew_isapnp_adapters[i].function, - idev))) { + while((idev = pnp_find_dev(NULL, + corkscrew_isapnp_adapters[i].vendor, + corkscrew_isapnp_adapters[i].function, + idev))) { - if(idev->active) idev->deactivate(idev); - - if(idev->prepare(idev)<0) - continue; - if (!(idev->resource[0].flags & IORESOURCE_IO)) + if (pnp_device_attach(idev) < 0) continue; - if(idev->activate(idev)<0) { - printk("isapnp configure failed (out of resources?)\n"); + if (pnp_activate_dev(idev, NULL) < 0) { + printk("pnp activate failed (out of resources?)\n"); + pnp_device_detach(idev); return -ENOMEM; } - if (!idev->resource[0].start || check_region(idev->resource[0].start,16)) + if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) { + pnp_device_detach(idev); continue; - ioaddr = idev->resource[0].start; - irq = idev->irq_resource[0].start; + } + ioaddr = pnp_port_start(idev, 0); + irq = pnp_irq(idev, 0); if(corkscrew_debug) printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n", (char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq); - if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) + if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) { + pnp_device_detach(idev); continue; + } /* Verify by reading the device ID from the EEPROM. */ { int timer; @@ -498,8 +499,10 @@ == 0) break; } - if (inw(ioaddr + Wn0EepromData) != 0x6d50) + if (inw(ioaddr + Wn0EepromData) != 0x6d50) { + pnp_device_detach(idev); continue; + } } printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c --- a/drivers/net/3c523.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/3c523.c Mon Jan 13 10:18:06 2003 @@ -1120,8 +1120,11 @@ netif_stop_queue(dev); - memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len); len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + + if (len != skb->len) + memset((char *) p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN); + memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len); #if (NUM_XMIT_BUFFS == 1) #ifdef NO_NOPCOMMANDS diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c --- a/drivers/net/3c527.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/3c527.c Mon Jan 13 10:18:06 2003 @@ -1084,6 +1084,11 @@ /* We will need this to flush the buffer out */ lp->tx_ring[lp->tx_ring_head].skb=skb; + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + goto out; + } np->length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; np->data = isa_virt_to_bus(skb->data); @@ -1092,7 +1097,7 @@ wmb(); p->control &= ~CONTROL_EOL; /* Clear EOL on p */ - +out: restore_flags(flags); netif_wake_queue(dev); diff -Nru a/drivers/net/7990.c b/drivers/net/7990.c --- a/drivers/net/7990.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/7990.c Mon Jan 13 10:18:06 2003 @@ -528,6 +528,8 @@ ib->btx_ring [entry].length = (-len) | 0xf000; ib->btx_ring [entry].misc = 0; + if (skb->len < ETH_ZLEN) + memset((char *)&ib->tx_buf[entry][0], 0, ETH_ZLEN); memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen); /* Now, give the packet to the lance */ diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c --- a/drivers/net/8139too.c Mon Jan 13 10:18:04 2003 +++ b/drivers/net/8139too.c Mon Jan 13 10:18:04 2003 @@ -1686,6 +1686,8 @@ entry = tp->cur_tx % NUM_TX_DESC; if (likely(len < TX_BUF_SIZE)) { + if (len < ETH_ZLEN) + memset(tp->tx_buf[entry], 0, ETH_ZLEN); skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); dev_kfree_skb(skb); } else { diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c --- a/drivers/net/82596.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/82596.c Mon Jan 13 10:18:06 2003 @@ -1063,12 +1063,18 @@ struct i596_private *lp = (struct i596_private *) dev->priv; struct tx_cmd *tx_cmd; struct i596_tbd *tbd; - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + short length = skb->len; dev->trans_start = jiffies; DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%x) called\n", dev->name, skb->len, (unsigned int)skb->data)); + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } netif_stop_queue(dev); tx_cmd = lp->tx_cmds + lp->next_tx_cmd; diff -Nru a/drivers/net/8390.c b/drivers/net/8390.c --- a/drivers/net/8390.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/8390.c Mon Jan 13 10:18:05 2003 @@ -270,6 +270,7 @@ struct ei_device *ei_local = (struct ei_device *) dev->priv; int length, send_length, output_page; unsigned long flags; + char scratch[ETH_ZLEN]; length = skb->len; @@ -340,8 +341,15 @@ * isn't already sending. If it is busy, the interrupt handler will * trigger the send later, upon receiving a Tx done interrupt. */ - - ei_block_output(dev, length, skb->data, output_page); + + if (length == send_length) + ei_block_output(dev, length, skb->data, output_page); + else { + memset(scratch, 0, ETH_ZLEN); + memcpy(scratch, skb->data, skb->len); + ei_block_output(dev, ETH_ZLEN, scratch, output_page); + } + if (! ei_local->txing) { ei_local->txing = 1; @@ -373,7 +381,13 @@ * reasonable hardware if you only use one Tx buffer. */ - ei_block_output(dev, length, skb->data, ei_local->tx_start_page); + if (length == send_length) + ei_block_output(dev, length, skb->data, ei_local->tx_start_page); + else { + memset(scratch, 0, ETH_ZLEN); + memcpy(scratch, skb->data, skb->len); + ei_block_output(dev, ETH_ZLEN, scratch, ei_local->tx_start_page); + } ei_local->txing = 1; NS8390_trigger_send(dev, send_length, ei_local->tx_start_page); dev->trans_start = jiffies; diff -Nru a/drivers/net/a2065.c b/drivers/net/a2065.c --- a/drivers/net/a2065.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/a2065.c Mon Jan 13 10:18:06 2003 @@ -570,6 +570,14 @@ unsigned long flags; skblen = skb->len; + len = skblen; + + if (len < ETH_ZLEN) { + len = ETH_ZLEN; + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } local_irq_save(flags); @@ -590,7 +598,6 @@ } } #endif - len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; entry = lp->tx_new & lp->tx_ring_mod_mask; ib->btx_ring [entry].length = (-len) | 0xf000; ib->btx_ring [entry].misc = 0; diff -Nru a/drivers/net/aironet4500_card.c b/drivers/net/aironet4500_card.c --- a/drivers/net/aironet4500_card.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/aironet4500_card.c Mon Jan 13 10:18:06 2003 @@ -273,16 +273,17 @@ #include #define AIRONET4X00_IO_SIZE 0x40 -#define isapnp_logdev pci_dev -#define isapnp_dev pci_bus -#define isapnp_find_device isapnp_find_card -#define isapnp_find_logdev isapnp_find_dev -#define PNP_BUS bus +#define isapnp_logdev pnp_dev +#define isapnp_dev pnp_card +#define isapnp_find_device pnp_find_card +#define isapnp_find_logdev pnp_find_dev +#define PNP_BUS card #define PNP_BUS_NUMBER number -#define PNP_DEV_NUMBER devfn +#define PNP_DEV_NUMBER number int awc4500_pnp_hw_reset(struct net_device *dev){ + struct isapnp_logdev *logdev; DEBUG(0, "awc_pnp_reset \n"); @@ -299,23 +300,16 @@ return -1; }; - if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER)<0) - printk("isapnp cfg failed at release \n"); - isapnp_deactivate(logdev->PNP_DEV_NUMBER); - isapnp_cfg_end(); + pnp_disable_dev(logdev); udelay(100); - - if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) { + if (pnp_activate_dev(logdev, NULL) < 0) { printk("%s cfg begin failed in hw_reset for csn %x devnum %x \n", dev->name, logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER); return -EAGAIN; } - isapnp_activate(logdev->PNP_DEV_NUMBER); /* activate device */ - isapnp_cfg_end(); - return 0; } @@ -341,32 +335,33 @@ isa_index++; logdev = isapnp_find_logdev(pnp_dev, ISAPNP_VENDOR('A','W','L'), - ISAPNP_FUNCTION(1), - 0); + ISAPNP_FUNCTION(1), + 0); if (!logdev){ printk("No logical device found on Aironet board \n"); return -ENODEV; } - if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) { - printk("cfg begin failed for csn %x devnum %x \n", + if (pnp_device_attach(logdev) < 0) { + printk("pnp_device_attach failed for csn %x devnum %x \n", logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER); return -EAGAIN; } - isapnp_activate(logdev->PNP_DEV_NUMBER); /* activate device */ - isapnp_cfg_end(); + if (pnp_activate_dev(logdev, NULL) < 0) { + printk("pnp_activate_dev failed for csn %x devnum %x \n", + logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER); + pnp_device_detach(logdev); + return -EIO; + } - isa_irq_line = logdev->irq; - isa_ioaddr = logdev->resource[0].start; + isa_irq_line = pnp_irq(logdev, 0); + isa_ioaddr = pnp_port_start(logdev, 0); request_region(isa_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr"); if (!dev) { dev = init_etherdev(NULL, 0); if (!dev) { release_region(isa_ioaddr, AIRONET4X00_IO_SIZE); - isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, - logdev->PNP_DEV_NUMBER); - isapnp_deactivate(logdev->PNP_DEV_NUMBER); - isapnp_cfg_end(); + pnp_device_detach(logdev); return -ENOMEM; } } diff -Nru a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c --- a/drivers/net/aironet4500_proc.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/aironet4500_proc.c Mon Jan 13 10:18:05 2003 @@ -42,7 +42,7 @@ #define DEV_AWC_INFO 1 #define DEV_AWC 1 -spinlock_t driver_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED; struct awc_proc_private{ struct ctl_table_header * sysctl_header; diff -Nru a/drivers/net/am79c961a.c b/drivers/net/am79c961a.c --- a/drivers/net/am79c961a.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/am79c961a.c Mon Jan 13 10:18:07 2003 @@ -407,10 +407,18 @@ am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev) { struct dev_priv *priv = (struct dev_priv *)dev->priv; - unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + unsigned int length = skb->len; unsigned int hdraddr, bufaddr; unsigned int head; unsigned long flags; + + /* FIXME: I thought the 79c961 could do padding - RMK ??? */ + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } head = priv->txhead; hdraddr = priv->txhdr + (head << 3); diff -Nru a/drivers/net/ariadne.c b/drivers/net/ariadne.c --- a/drivers/net/ariadne.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/ariadne.c Mon Jan 13 10:18:06 2003 @@ -574,6 +574,7 @@ volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr; int entry; unsigned long flags; + int len = skb->len; #if 0 if (ariadne_debug > 3) { @@ -584,6 +585,15 @@ } #endif + /* FIXME: is the 79C960 new enough to do its own padding right ? */ + if (skb->len < ETH_ZLEN) + { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + len = ETH_ZLEN; + } + /* Fill in a Tx ring entry */ #if 0 @@ -613,8 +623,7 @@ priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len); priv->tx_ring[entry]->TMD3 = 0x0000; - memcpyw(priv->tx_buff[entry], (u_short *)skb->data, - skb->len <= ETH_ZLEN ? ETH_ZLEN : skb->len); + memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len); #if 0 { diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c --- a/drivers/net/at1700.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/at1700.c Mon Jan 13 10:18:05 2003 @@ -572,7 +572,9 @@ struct net_local *lp = (struct net_local *) dev->priv; int ioaddr = dev->base_addr; short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + short len = skb->len; unsigned char *buf = skb->data; + static u8 pad[ETH_ZLEN]; netif_stop_queue (dev); @@ -584,7 +586,16 @@ lp->tx_queue_ready = 0; { outw (length, ioaddr + DATAPORT); - outsw (ioaddr + DATAPORT, buf, (length + 1) >> 1); + /* Packet data */ + outsw (ioaddr + DATAPORT, buf, len >> 1); + /* Check for dribble byte */ + if (len & 1) { + outw(skb->data[skb->len-1], ioaddr + DATAPORT); + len++; + } + /* Check for packet padding */ + if (length != skb->len) + outsw(ioaddr + DATAPORT, pad, (length - len + 1) >> 1); lp->tx_queue++; lp->tx_queue_len += length + 2; diff -Nru a/drivers/net/atarilance.c b/drivers/net/atarilance.c --- a/drivers/net/atarilance.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/atarilance.c Mon Jan 13 10:18:05 2003 @@ -787,6 +787,21 @@ DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name, DREG )); + + /* The old LANCE chips doesn't automatically pad buffers to min. size. */ + len = skb->len; + if (len < ETH_ZLEN) + len = ETH_ZLEN; + /* PAM-Card has a bug: Can only send packets with even number of bytes! */ + else if (lp->cardtype == PAM_CARD && (len & 1)) + ++len; + + if (len > skb->len) { + skb = skb_padto(skb, len); + if (skb == NULL) + return 0; + } + netif_stop_queue (dev); /* Fill in a Tx ring entry */ @@ -816,11 +831,6 @@ * last. */ - /* The old LANCE chips doesn't automatically pad buffers to min. size. */ - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - /* PAM-Card has a bug: Can only send packets with even number of bytes! */ - if (lp->cardtype == PAM_CARD && (len & 1)) - ++len; head->length = -len; head->misc = 0; diff -Nru a/drivers/net/atp.c b/drivers/net/atp.c --- a/drivers/net/atp.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/atp.c Mon Jan 13 10:18:07 2003 @@ -200,7 +200,7 @@ static unsigned short eeprom_op(long ioaddr, unsigned int cmd); static int net_open(struct net_device *dev); static void hardware_init(struct net_device *dev); -static void write_packet(long ioaddr, int length, unsigned char *packet, int mode); +static void write_packet(long ioaddr, int length, unsigned char *packet, int pad, int mode); static void trigger_send(long ioaddr, int length); static int atp_send_packet(struct sk_buff *skb, struct net_device *dev); static void atp_interrupt(int irq, void *dev_id, struct pt_regs *regs); @@ -499,15 +499,23 @@ write_reg(ioaddr, CMR1, CMR1_Xmit); } -static void write_packet(long ioaddr, int length, unsigned char *packet, int data_mode) +static void write_packet(long ioaddr, int length, unsigned char *packet, int pad_len, int data_mode) { - length = (length + 1) & ~1; /* Round up to word length. */ + if (length & 1) + { + length++; + pad_len++; + } + outb(EOC+MAR, ioaddr + PAR_DATA); if ((data_mode & 1) == 0) { /* Write the packet out, starting with the write addr. */ outb(WrAddr+MAR, ioaddr + PAR_DATA); do { write_byte_mode0(ioaddr, *packet++); + } while (--length > pad_len) ; + do { + write_byte_mode0(ioaddr, 0); } while (--length > 0) ; } else { /* Write the packet out in slow mode. */ @@ -521,8 +529,10 @@ outbyte >>= 4; outb(outbyte & 0x0f, ioaddr + PAR_DATA); outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL); - while (--length > 0) + while (--length > pad_len) write_byte_mode1(ioaddr, *packet++); + while (--length > 0) + write_byte_mode1(ioaddr, 0); } /* Terminate the Tx frame. End of write: ECB. */ outb(0xff, ioaddr + PAR_DATA); @@ -564,7 +574,7 @@ write_reg_high(ioaddr, IMR, 0); spin_unlock_irqrestore(&lp->lock, flags); - write_packet(ioaddr, length, skb->data, dev->if_port); + write_packet(ioaddr, length, skb->data, length-skb->len, dev->if_port); lp->pac_cnt_in_tx_buf++; if (lp->tx_unit_busy == 0) { diff -Nru a/drivers/net/bagetlance.c b/drivers/net/bagetlance.c --- a/drivers/net/bagetlance.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/bagetlance.c Mon Jan 13 10:18:05 2003 @@ -830,6 +830,18 @@ struct lance_tx_head *head; unsigned long flags; + /* The old LANCE chips doesn't automatically pad buffers to min. size. */ + len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + /* PAM-Card has a bug: Can only send packets with even number of bytes! */ + if (lp->cardtype == PAM_CARD && (len & 1)) + ++len; + + if (len > skb->len) { + skb = skb_padto(skb, len); + if (skb == NULL) + return 0; + } + /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; @@ -915,12 +927,6 @@ /* Caution: the write order is important here, set the "ownership" bits * last. */ - - /* The old LANCE chips doesn't automatically pad buffers to min. size. */ - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - /* PAM-Card has a bug: Can only send packets with even number of bytes! */ - if (lp->cardtype == PAM_CARD && (len & 1)) - ++len; head->length = -len; head->misc = 0; diff -Nru a/drivers/net/de600.c b/drivers/net/de600.c --- a/drivers/net/de600.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/de600.c Mon Jan 13 10:18:07 2003 @@ -187,6 +187,7 @@ int len; int tickssofar; u8 *buffer = skb->data; + int i; if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ tickssofar = jiffies - dev->trans_start; @@ -228,8 +229,10 @@ } de600_setup_address(transmit_from, RW_ADDR); - for ( ; len > 0; --len, ++buffer) + for (i = 0; i < skb->len ; ++i, ++buffer) de600_put_byte(*buffer); + for (; i < len; ++i) + de600_put_byte(0); if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ dev->trans_start = jiffies; diff -Nru a/drivers/net/de620.c b/drivers/net/de620.c --- a/drivers/net/de620.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/de620.c Mon Jan 13 10:18:06 2003 @@ -315,7 +315,7 @@ } static inline void -de620_write_block(struct net_device *dev, byte *buffer, int count) +de620_write_block(struct net_device *dev, byte *buffer, int count, int pad) { #ifndef LOWSPEED byte uflip = NIC_Cmd ^ (DS0 | DS1); @@ -334,6 +334,9 @@ for ( ; count > 0; --count, ++buffer) { de620_put_byte(dev,*buffer); } + for ( count = pad ; count > 0; --count, ++buffer) { + de620_put_byte(dev, 0); + } de620_send_command(dev,W_DUMMY); #ifdef COUNT_LOOPS /* trial debug output: loops per byte in de620_ready() */ @@ -571,7 +574,7 @@ spin_unlock_irqrestore(&de620_lock, flags); return 1; } - de620_write_block(dev, buffer, len); + de620_write_block(dev, buffer, skb->len, len-skb->len); dev->trans_start = jiffies; if(!(using_txbuf == (TXBF0 | TXBF1))) diff -Nru a/drivers/net/declance.c b/drivers/net/declance.c --- a/drivers/net/declance.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/declance.c Mon Jan 13 10:18:06 2003 @@ -869,7 +869,14 @@ skblen = skb->len; - len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; + len = skblen; + + if (len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + len = ETH_ZLEN; + } lp->stats.tx_bytes += len; diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c --- a/drivers/net/depca.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/depca.c Mon Jan 13 10:18:06 2003 @@ -862,6 +862,12 @@ if (skb->len < 1) goto out; + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + goto out; + } + netif_stop_queue(dev); if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ diff -Nru a/drivers/net/eepro.c b/drivers/net/eepro.c --- a/drivers/net/eepro.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/eepro.c Mon Jan 13 10:18:07 2003 @@ -1130,17 +1130,23 @@ struct eepro_local *lp = (struct eepro_local *)dev->priv; unsigned long flags; int ioaddr = dev->base_addr; + short length = skb->len; if (net_debug > 5) printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name); + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } netif_stop_queue (dev); eepro_dis_int(ioaddr); spin_lock_irqsave(&lp->lock, flags); { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; if (hardware_send_packet(dev, buf, length)) diff -Nru a/drivers/net/eexpress.c b/drivers/net/eexpress.c --- a/drivers/net/eexpress.c Mon Jan 13 10:18:04 2003 +++ b/drivers/net/eexpress.c Mon Jan 13 10:18:04 2003 @@ -636,6 +636,7 @@ static int eexp_xmit(struct sk_buff *buf, struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; + short length = buf->len; #ifdef CONFIG_SMP unsigned long flags; #endif @@ -644,6 +645,13 @@ printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name); #endif + if (buf->len < ETH_ZLEN) { + buf = skb_padto(buf, ETH_ZLEN); + if (buf == NULL) + return 0; + length = buf->len; + } + disable_irq(dev->irq); /* @@ -656,8 +664,6 @@ #endif { - unsigned short length = (ETH_ZLEN < buf->len) ? buf->len : - ETH_ZLEN; unsigned short *data = (unsigned short *)buf->data; lp->stats.tx_bytes += length; diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c --- a/drivers/net/epic100.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/epic100.c Mon Jan 13 10:18:06 2003 @@ -974,6 +974,12 @@ int entry, free_count; u32 ctrl_word; long flags; + + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } /* Caution: the write order is important here, set the field with the "ownership" bit last. */ diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c --- a/drivers/net/eth16i.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/eth16i.c Mon Jan 13 10:18:05 2003 @@ -1052,10 +1052,16 @@ struct eth16i_local *lp = (struct eth16i_local *)dev->priv; int ioaddr = dev->base_addr; int status = 0; - ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + ushort length = skb->len; unsigned char *buf = skb->data; unsigned long flags; + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } netif_stop_queue(dev); diff -Nru a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c --- a/drivers/net/fmv18x.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/fmv18x.c Mon Jan 13 10:18:05 2003 @@ -366,7 +366,7 @@ { struct net_local *lp = dev->priv; int ioaddr = dev->base_addr; - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + short length = skb->len; unsigned char *buf = skb->data; unsigned long flags; @@ -378,6 +378,14 @@ dev->name, length); return 1; } + + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } + if (net_debug > 4) printk("%s: Transmitting a packet of length %lu.\n", dev->name, (unsigned long)skb->len); diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/hp100.c Mon Jan 13 10:18:05 2003 @@ -1555,6 +1555,12 @@ if (skb->len <= 0) return 0; + + if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } /* Get Tx ring tail pointer */ if (lp->txrtail->next == lp->txrhead) { @@ -2097,6 +2103,7 @@ struct hp100_private *lp = (struct hp100_private *) dev->priv; #ifdef HP100_DEBUG_B + int ioaddr = dev->base_addr; hp100_outw(0x4216, TRACE); printk("hp100: %s: misc_interrupt\n", dev->name); #endif @@ -2536,6 +2543,11 @@ return HP100_LAN_10; if (val_10 & HP100_AUI_ST) { /* have we BNC or AUI onboard? */ + /* + * This can be overriden by dos utility, so if this has no effect, + * perhaps you need to download that utility from HP and set card + * back to "auto detect". + */ val_10 |= HP100_AUI_SEL | HP100_LOW_TH; hp100_page(MAC_CTRL); hp100_outb(val_10, 10_LAN_CFG_1); diff -Nru a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c --- a/drivers/net/irda/sa1100_ir.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/irda/sa1100_ir.c Mon Jan 13 10:18:05 2003 @@ -10,8 +10,7 @@ * Infra-red driver for the StrongARM SA1100 embedded microprocessor * * Note that we don't have to worry about the SA1111's DMA bugs in here, - * so we use the straight forward pci_map_* functions with a null pointer. - * IMHO we should really be using our own machine specific set. + * so we use the straight forward dma_map_* functions with a null pointer. * * This driver takes one kernel command line parameter, sa1100ir=, with * the following options: @@ -29,8 +28,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -57,11 +56,6 @@ static int tx_lpm; static int max_rate = 4000000; -/* - * Our netdevice. There is only ever one of these. - */ -static struct net_device *netdev; - struct sa1100_irda { unsigned char hscr0; unsigned char utcr4; @@ -79,8 +73,8 @@ dma_regs_t *rxdma; struct net_device_stats stats; + struct device *dev; struct irlap_cb *irlap; - struct pm_dev *pmdev; struct qos_info qos; iobuff_t tx_buff; @@ -112,9 +106,9 @@ */ skb_reserve(si->rxskb, 1); - si->rxbuf_dma = pci_map_single(NULL, si->rxskb->data, + si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data, HPSIR_MAX_RXLEN, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); return 0; } @@ -361,11 +355,12 @@ /* * Suspend the IrDA interface. */ -static int sa1100_irda_suspend(struct net_device *dev, int state) +static int sa1100_irda_suspend(struct device *_dev, u32 state, u32 level) { + struct net_device *dev = dev_get_drvdata(_dev); struct sa1100_irda *si = dev->priv; - if (si && si->open) { + if (si && si->open && level == SUSPEND_DISABLE) { /* * Stop the transmit queue */ @@ -381,11 +376,12 @@ /* * Resume the IrDA interface. */ -static int sa1100_irda_resume(struct net_device *dev) +static int sa1100_irda_resume(struct device *_dev, u32 level) { + struct net_device *dev = dev_get_drvdata(_dev); struct sa1100_irda *si = dev->priv; - if (si && si->open) { + if (si && si->open && level == RESUME_ENABLE) { /* * If we missed a speed change, initialise at the new speed * directly. It is debatable whether this is actually @@ -410,31 +406,9 @@ return 0; } - -static int sa1100_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - int ret; - - if (!dev->data) - return -EINVAL; - - switch (rqst) { - case PM_SUSPEND: - ret = sa1100_irda_suspend((struct net_device *)dev->data, - (int)data); - break; - - case PM_RESUME: - ret = sa1100_irda_resume((struct net_device *)dev->data); - break; - - default: - ret = -EINVAL; - break; - } - - return ret; -} +#else +#define sa1100_irda_suspend NULL +#define sa1100_irda_resume NULL #endif /* @@ -555,7 +529,7 @@ len = dma_addr - si->rxbuf_dma; if (len > HPSIR_MAX_RXLEN) len = HPSIR_MAX_RXLEN; - pci_unmap_single(NULL, si->rxbuf_dma, len, PCI_DMA_FROMDEVICE); + dma_unmap_single(si->dev, si->rxbuf_dma, len, DMA_FROM_DEVICE); do { /* @@ -603,9 +577,9 @@ /* * Remap the buffer. */ - si->rxbuf_dma = pci_map_single(NULL, si->rxskb->data, + si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data, HPSIR_MAX_RXLEN, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); } } @@ -716,7 +690,7 @@ * Account and free the packet. */ if (skb) { - pci_unmap_single(NULL, si->txbuf_dma, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(si->dev, si->txbuf_dma, skb->len, DMA_TO_DEVICE); si->stats.tx_packets ++; si->stats.tx_bytes += skb->len; dev_kfree_skb_irq(skb); @@ -782,8 +756,8 @@ netif_stop_queue(dev); si->txskb = skb; - si->txbuf_dma = pci_map_single(NULL, skb->data, - skb->len, PCI_DMA_TODEVICE); + si->txbuf_dma = dma_map_single(si->dev, skb->data, + skb->len, DMA_TO_DEVICE); sa1100_start_dma(si->txdma, si->txbuf_dma, skb->len); @@ -931,8 +905,8 @@ * tidy that up cleanly. */ if (si->rxskb) { - pci_unmap_single(NULL, si->rxbuf_dma, HPSIR_MAX_RXLEN, - PCI_DMA_FROMDEVICE); + dma_unmap_single(si->dev, si->rxbuf_dma, HPSIR_MAX_RXLEN, + DMA_FROM_DEVICE); dev_kfree_skb(si->rxskb); si->rxskb = NULL; } @@ -972,6 +946,24 @@ return io->head ? 0 : -ENOMEM; } +static struct device_driver sa1100ir_driver = { + .name = "sa1100ir", + .bus = &system_bus_type, + .suspend = sa1100_irda_suspend, + .resume = sa1100_irda_resume, +}; + +static struct sys_device sa1100ir_device = { + .name = "sa1100ir", + .id = 0, + .root = NULL, + .dev = { + .name = "Intel Corporation SA11x0 [IrDA]", + .bus_id = "0", + .driver = &sa1100ir_driver, + }, +}; + static int sa1100_irda_net_init(struct net_device *dev) { struct sa1100_irda *si = dev->priv; @@ -984,6 +976,8 @@ memset(si, 0, sizeof(*si)); + si->dev = &sa1100ir_device.dev; + /* * Initialise the HP-SIR buffers */ @@ -1035,15 +1029,6 @@ Ser2UTCR4 = si->utcr4; Ser2HSCR0 = HSCR0_UART; -#ifdef CONFIG_PM - /* - * Power-Management is optional. - */ - si->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, sa1100_irda_pmproc); - if (si->pmdev) - si->pmdev->data = dev; -#endif - return 0; kfree(si->tx_buff.head); @@ -1071,15 +1056,12 @@ dev->get_stats = NULL; dev->priv = NULL; - pm_unregister(si->pmdev); - kfree(si->tx_buff.head); kfree(si->rx_buff.head); kfree(si); } -static -int __init sa1100_irda_init(void) +static int __init sa1100_irda_init(void) { struct net_device *dev; int err; @@ -1102,6 +1084,9 @@ if (err) goto err_mem_3; + driver_register(&sa1100ir_driver); + sys_device_register(&sa1100ir_device); + rtnl_lock(); dev = dev_alloc("irda%d", &err); if (dev) { @@ -1114,11 +1099,14 @@ if (err) kfree(dev); else - netdev = dev; + dev_set_drvdata(&sa1100ir_device.dev, dev); } rtnl_unlock(); if (err) { + sys_device_unregister(&sa1100ir_device); + driver_unregister(&sa1100ir_driver); + release_mem_region(__PREG(Ser2HSCR2), 0x04); err_mem_3: release_mem_region(__PREG(Ser2HSCR0), 0x1c); @@ -1131,14 +1119,16 @@ static void __exit sa1100_irda_exit(void) { - struct net_device *dev = netdev; + struct net_device *dev = dev_get_drvdata(&sa1100ir_device.dev); - netdev = NULL; if (dev) { rtnl_lock(); unregister_netdevice(dev); rtnl_unlock(); } + + sys_device_unregister(&sa1100ir_device); + driver_unregister(&sa1100ir_driver); release_mem_region(__PREG(Ser2HSCR2), 0x04); release_mem_region(__PREG(Ser2HSCR0), 0x1c); diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c --- a/drivers/net/lance.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/lance.c Mon Jan 13 10:18:05 2003 @@ -899,8 +899,14 @@ /* The old LANCE chips doesn't automatically pad buffers to min. size. */ if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) { - lp->tx_ring[entry].length = - -(ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + goto out; + lp->tx_ring[entry].length = -ETH_ZLEN; + } + else + lp->tx_ring[entry].length = -skb->len; } else lp->tx_ring[entry].length = -skb->len; @@ -933,6 +939,7 @@ if ((lp->cur_tx - lp->dirty_tx) >= TX_RING_SIZE) netif_stop_queue(dev); +out: spin_unlock_irqrestore(&lp->devlock, flags); return 0; } diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c --- a/drivers/net/lasi_82596.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/lasi_82596.c Mon Jan 13 10:18:05 2003 @@ -1080,12 +1080,19 @@ struct i596_private *lp = (struct i596_private *) dev->priv; struct tx_cmd *tx_cmd; struct i596_tbd *tbd; - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + short length = skb->len; dev->trans_start = jiffies; DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%p) called\n", dev->name, skb->len, skb->data)); + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } + netif_stop_queue(dev); tx_cmd = lp->tx_cmds + lp->next_tx_cmd; diff -Nru a/drivers/net/lp486e.c b/drivers/net/lp486e.c --- a/drivers/net/lp486e.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/lp486e.c Mon Jan 13 10:18:05 2003 @@ -885,7 +885,15 @@ if (skb->len <= 0) return 0; - length = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + length = skb->len; + + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } + dev->trans_start = jiffies; tx_cmd = (struct tx_cmd *) diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c --- a/drivers/net/ne.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/ne.c Mon Jan 13 10:18:06 2003 @@ -196,29 +196,32 @@ int i; for (i = 0; isapnp_clone_list[i].vendor != 0; i++) { - struct pci_dev *idev = NULL; + struct pnp_dev *idev = NULL; - while ((idev = isapnp_find_dev(NULL, - isapnp_clone_list[i].vendor, - isapnp_clone_list[i].function, - idev))) { + while ((idev = pnp_find_dev(NULL, + isapnp_clone_list[i].vendor, + isapnp_clone_list[i].function, + idev))) { /* Avoid already found cards from previous calls */ - if (idev->prepare(idev)) - continue; - if (idev->activate(idev)) - continue; - /* if no irq, search for next */ - if (idev->irq_resource[0].start == 0) + if (pnp_device_attach(idev) < 0) continue; + if (pnp_activate_dev(idev, NULL) < 0) { + __again: + pnp_device_detach(idev); + continue; + } + /* if no io and irq, search for next */ + if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) + goto __again; /* found it */ - dev->base_addr = idev->resource[0].start; - dev->irq = idev->irq_resource[0].start; + dev->base_addr = pnp_port_start(idev, 0); + dev->irq = pnp_irq(idev, 0); printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", (char *) isapnp_clone_list[i].driver_data, - dev->base_addr, dev->irq); if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */ printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); + pnp_device_detach(idev); return -ENXIO; } ei_status.priv = (unsigned long)idev; diff -Nru a/drivers/net/ni5010.c b/drivers/net/ni5010.c --- a/drivers/net/ni5010.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/ni5010.c Mon Jan 13 10:18:06 2003 @@ -114,7 +114,7 @@ static int process_xmt_interrupt(struct net_device *dev); #define tx_done(dev) 1 -static void hardware_send_packet(struct net_device *dev, char *buf, int length); +static void hardware_send_packet(struct net_device *dev, char *buf, int length, int pad); static void chipset_init(struct net_device *dev, int startp); static void dump_packet(void *buf, int len); static void ni5010_show_registers(struct net_device *dev); @@ -441,7 +441,7 @@ */ netif_stop_queue(dev); - hardware_send_packet(dev, (unsigned char *)skb->data, length); + hardware_send_packet(dev, (unsigned char *)skb->data, skb->len, length-skb->len); dev->trans_start = jiffies; dev_kfree_skb (skb); return 0; @@ -665,7 +665,7 @@ } } -static void hardware_send_packet(struct net_device *dev, char *buf, int length) +static void hardware_send_packet(struct net_device *dev, char *buf, int length, int pad) { struct ni5010_local *lp = (struct ni5010_local *)dev->priv; int ioaddr = dev->base_addr; @@ -690,8 +690,8 @@ if (NI5010_DEBUG > 3) dump_packet(buf, length); - buf_offs = NI5010_BUFSIZE - length; - lp->o_pkt_size = length; + buf_offs = NI5010_BUFSIZE - length - pad; + lp->o_pkt_size = length + pad; save_flags(flags); cli(); @@ -702,6 +702,9 @@ outw(buf_offs, IE_GP); /* Point GP at start of packet */ outsb(IE_XBUF, buf, length); /* Put data in buffer */ + while(pad--) + outb(0, IE_XBUF); + outw(buf_offs, IE_GP); /* Rewrite where packet starts */ /* should work without that outb() (Crynwr used it) */ diff -Nru a/drivers/net/ni52.c b/drivers/net/ni52.c --- a/drivers/net/ni52.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/ni52.c Mon Jan 13 10:18:06 2003 @@ -1169,7 +1169,11 @@ #endif { memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + len = skb->len; + if (len < ETH_ZLEN) { + len = ETH_ZLEN; + memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0, len - skb->len); + } #if (NUM_XMIT_BUFFS == 1) # ifdef NO_NOPCOMMANDS diff -Nru a/drivers/net/ni65.c b/drivers/net/ni65.c --- a/drivers/net/ni65.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/ni65.c Mon Jan 13 10:18:05 2003 @@ -1145,6 +1145,8 @@ memcpy((char *) p->tmdbounce[p->tmdbouncenum] ,(char *)skb->data, (skb->len > T_BUF_SIZE) ? T_BUF_SIZE : skb->len); + if (len > skb->len) + memset((char *)p->tmdbounce[p->tmdbouncenum]+skb->len, 0, len-skb->len); dev_kfree_skb (skb); save_flags(flags); diff -Nru a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c --- a/drivers/net/pcmcia/axnet_cs.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/pcmcia/axnet_cs.c Mon Jan 13 10:18:06 2003 @@ -1216,7 +1216,8 @@ struct ei_device *ei_local = (struct ei_device *) dev->priv; int length, send_length, output_page; unsigned long flags; - + u8 packet[ETH_ZLEN]; + netif_stop_queue(dev); length = skb->len; @@ -1241,7 +1242,7 @@ ei_local->irqlock = 1; send_length = ETH_ZLEN < length ? length : ETH_ZLEN; - + /* * We have two Tx slots available for use. Find the first free * slot, and then perform some sanity checks. With two Tx bufs, @@ -1286,7 +1287,14 @@ * trigger the send later, upon receiving a Tx done interrupt. */ - ei_block_output(dev, length, skb->data, output_page); + if (length == skb->len) + ei_block_output(dev, length, skb->data, output_page); + else { + memset(packet, 0, ETH_ZLEN); + memcpy(packet, skb->data, skb->len); + ei_block_output(dev, length, packet, output_page); + } + if (! ei_local->txing) { ei_local->txing = 1; diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c --- a/drivers/net/pcmcia/fmvj18x_cs.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/pcmcia/fmvj18x_cs.c Mon Jan 13 10:18:06 2003 @@ -951,11 +951,19 @@ { struct local_info_t *lp = (struct local_info_t *)dev->priv; ioaddr_t ioaddr = dev->base_addr; + short length = skb->len; + + if (length < ETH_ZLEN) + { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } netif_stop_queue(dev); { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; if (length > ETH_FRAME_LEN) { diff -Nru a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c --- a/drivers/net/pcmcia/ray_cs.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/pcmcia/ray_cs.c Mon Jan 13 10:18:05 2003 @@ -1052,7 +1052,7 @@ { ray_dev_t *local = dev->priv; dev_link_t *link = local->finder; - short length; + short length = skb->len; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_dev_start_xmit - device not present\n"); @@ -1068,7 +1068,13 @@ } } - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + if (length < ETH_ZLEN) + { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } switch (ray_hw_xmit( skb->data, length, dev, DATA_TYPE)) { case XMIT_NO_CCS: case XMIT_NEED_AUTH: diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c --- a/drivers/net/pcmcia/xirc2ps_cs.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/pcmcia/xirc2ps_cs.c Mon Jan 13 10:18:05 2003 @@ -1547,7 +1547,6 @@ DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", skb, dev, pktlen); - netif_stop_queue(dev); /* adjust the packet length to min. required * and hope that the buffer is large enough @@ -1557,8 +1556,14 @@ * pad this in his buffer with random bytes */ if (pktlen < ETH_ZLEN) + { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; pktlen = ETH_ZLEN; + } + netif_stop_queue(dev); SelectPage(0); PutWord(XIRCREG0_TRS, (u_short)pktlen+2); freespace = GetWord(XIRCREG0_TSO); diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/r8169.c Mon Jan 13 10:18:06 2003 @@ -822,6 +822,12 @@ void *ioaddr = tp->mmio_addr; int entry = tp->cur_tx % NUM_TX_DESC; + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } + spin_lock_irq(&tp->lock); if ((tp->TxDescArray[entry].status & OWNbit) == 0) { diff -Nru a/drivers/net/sb1000.c b/drivers/net/sb1000.c --- a/drivers/net/sb1000.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/sb1000.c Mon Jan 13 10:18:05 2003 @@ -145,7 +145,7 @@ { unsigned short ioaddr[2], irq; - struct pci_dev *idev=NULL; + struct pnp_dev *idev=NULL; unsigned int serial_number; while(1) @@ -154,55 +154,58 @@ * Find the card */ - idev=isapnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'), + idev=pnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'), ISAPNP_FUNCTION(0x1000), idev); /* * No card */ - if(idev==NULL) + if(idev==NULL || idev->card == NULL) return -ENODEV; /* * Bring it online */ - idev->prepare(idev); - idev->activate(idev); + if (pnp_device_attach(idev) < 0) + continue; + if (pnp_activate_dev(idev, NULL) < 0) { + __again: + pnp_device_detach(idev); + continue; + } /* * Ports free ? */ - if(!idev->resource[0].start || check_region(idev->resource[0].start, 16)) - continue; - if(!idev->resource[1].start || check_region(idev->resource[1].start, 16)) - continue; + if(!pnp_port_valid(idev, 0) || !pnp_port_valid(idev, 1) || !pnp_irq_valid(idev, 0)) + goto __again; - serial_number = idev->bus->serial; + serial_number = idev->card->serial; - ioaddr[0]=idev->resource[0].start; - ioaddr[1]=idev->resource[1].start; + ioaddr[0]=pnp_port_start(idev, 0); + ioaddr[1]=pnp_port_start(idev, 0); - irq = idev->irq_resource[0].start; + irq = pnp_irq(idev, 0); /* check I/O base and IRQ */ if (dev->base_addr != 0 && dev->base_addr != ioaddr[0]) - continue; + goto __again; if (dev->mem_start != 0 && dev->mem_start != ioaddr[1]) - continue; + goto __again; if (dev->irq != 0 && dev->irq != irq) - continue; + goto __again; /* * Ok set it up. */ if (!request_region(ioaddr[0], 16, dev->name)) - continue; + goto __again; if (!request_region(ioaddr[1], 16, dev->name)) { release_region(ioaddr[0], 16); - continue; + goto __again; } dev->base_addr = ioaddr[0]; @@ -216,8 +219,12 @@ dev->mem_start, serial_number, dev->irq); dev = init_etherdev(dev, 0); - if (!dev) + if (!dev) { + pnp_device_detach(idev); + release_region(ioaddr[1], 16); + release_region(ioaddr[0], 16); return -ENOMEM; + } SET_MODULE_OWNER(dev); /* Make up a SB1000-specific-data structure. */ diff -Nru a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c --- a/drivers/net/seeq8005.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/seeq8005.c Mon Jan 13 10:18:07 2003 @@ -377,9 +377,15 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + short length = skb->len; unsigned char *buf = skb->data; + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } /* Block a timer-based transmit from overlapping */ netif_stop_queue(dev); diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c --- a/drivers/net/sgiseeq.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/sgiseeq.c Mon Jan 13 10:18:07 2003 @@ -531,6 +531,8 @@ * added this new entry and restarted it. */ memcpy((char *)(long)td->buf_vaddr, skb->data, skblen); + if (len != skblen) + memset((char *)(long)td->buf_vaddr + skb->len, 0, len-skblen); td->tdma.cntinfo = (len & HPCDMA_BCNT) | (HPCDMA_XIU | HPCDMA_EOXP | HPCDMA_XIE | HPCDMA_EOX); if (sp->tx_old != sp->tx_new) { diff -Nru a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c --- a/drivers/net/sk_g16.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/sk_g16.c Mon Jan 13 10:18:07 2003 @@ -1254,6 +1254,7 @@ { struct priv *p = (struct priv *) dev->priv; struct tmd *tmdp; + static char pad[64]; PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", SK_NAME, SK_read_reg(CSR0))); @@ -1278,6 +1279,8 @@ /* Copy data into dual ported ram */ memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len); + if (len != skb->len) + memcpy_toio((tmdp->u.buffer & 0x00ffffff) + sb->len, pad, len-skb->len); writew(-len, &tmdp->blen); /* set length to transmit */ diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c --- a/drivers/net/smc-ultra.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/smc-ultra.c Mon Jan 13 10:18:05 2003 @@ -284,29 +284,33 @@ int i; for (i = 0; ultra_device_ids[i].vendor != 0; i++) { - struct pci_dev *idev = NULL; + struct pnp_dev *idev = NULL; - while ((idev = isapnp_find_dev(NULL, - ultra_device_ids[i].vendor, - ultra_device_ids[i].function, - idev))) { + while ((idev = pnp_find_dev(NULL, + ultra_device_ids[i].vendor, + ultra_device_ids[i].function, + idev))) { /* Avoid already found cards from previous calls */ - if (idev->prepare(idev)) - continue; - if (idev->activate(idev)) - continue; - /* if no irq, search for next */ - if (idev->irq_resource[0].start == 0) - continue; + if (pnp_device_attach(idev) < 0) + continue; + if (pnp_activate_dev(idev, NULL) < 0) { + __again: + pnp_device_detach(idev); + continue; + } + /* if no io and irq, search for next */ + if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) + goto __again; /* found it */ - dev->base_addr = idev->resource[0].start; - dev->irq = idev->irq_resource[0].start; + dev->base_addr = pnp_port_start(idev, 0); + dev->irq = pnp_irq(idev, 0); printk(KERN_INFO "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", (char *) ultra_device_ids[i].driver_data, - dev->base_addr, dev->irq); if (ultra_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); return -ENXIO; + printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); + pnp_device_detach(idev); + return -ENXIO; } ei_status.priv = (unsigned long)idev; break; diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c --- a/drivers/net/smc9194.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/smc9194.c Mon Jan 13 10:18:07 2003 @@ -484,8 +484,16 @@ } lp->saved_skb = skb; - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + length = skb->len; + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) { + netif_wake_queue(dev); + return 0; + } + length = ETH_ZLEN; + } /* ** The MMU wants the number of pages to be the number of 256 bytes diff -Nru a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c --- a/drivers/net/sun3_82586.c Mon Jan 13 10:18:06 2003 +++ b/drivers/net/sun3_82586.c Mon Jan 13 10:18:06 2003 @@ -1010,8 +1010,12 @@ else #endif { + len = skb->len; + if (len < ETH_ZLEN) { + memset((char *)p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN); + len = ETH_ZLEN; + } memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; #if (NUM_XMIT_BUFFS == 1) # ifdef NO_NOPCOMMANDS diff -Nru a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c --- a/drivers/net/sun3lance.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/sun3lance.c Mon Jan 13 10:18:07 2003 @@ -593,6 +593,9 @@ head->misc = 0; memcpy( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); + if (len != skb->len) + memset(PKTBUF_ADDR(head) + skb->len, 0, len-skb->len); + head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; lp->new_tx = (lp->new_tx + 1) & TX_RING_MOD_MASK; lp->stats.tx_bytes += skb->len; diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c --- a/drivers/net/wireless/wavelan.c Mon Jan 13 10:18:07 2003 +++ b/drivers/net/wireless/wavelan.c Mon Jan 13 10:18:07 2003 @@ -3008,6 +3008,12 @@ (unsigned) skb); #endif + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } + /* * Block a timer-based transmit from overlapping. * In other words, prevent reentering this routine. diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c --- a/drivers/net/yellowfin.c Mon Jan 13 10:18:05 2003 +++ b/drivers/net/yellowfin.c Mon Jan 13 10:18:05 2003 @@ -862,6 +862,7 @@ { struct yellowfin_private *yp = dev->priv; unsigned entry; + int len = skb->len; netif_stop_queue (dev); @@ -876,28 +877,36 @@ if (gx_fix) { /* Note: only works for paddable protocols e.g. IP. */ int cacheline_end = ((unsigned long)skb->data + skb->len) % 32; /* Fix GX chipset errata. */ - if (cacheline_end > 24 || cacheline_end == 0) - skb->len += 32 - cacheline_end + 1; + if (cacheline_end > 24 || cacheline_end == 0) { + len = skb->len + 32 - cacheline_end + 1; + if (len != skb->len) + skb = skb_padto(skb, len); + } + if (skb == NULL) { + yp->tx_skbuff[entry] = NULL; + netif_wake_queue(dev); + return 0; + } } #ifdef NO_TXSTATS yp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(yp->pci_dev, - skb->data, skb->len, PCI_DMA_TODEVICE)); + skb->data, len, PCI_DMA_TODEVICE)); yp->tx_ring[entry].result_status = 0; if (entry >= TX_RING_SIZE-1) { /* New stop command. */ yp->tx_ring[0].dbdma_cmd = cpu_to_le32(CMD_STOP); yp->tx_ring[TX_RING_SIZE-1].dbdma_cmd = - cpu_to_le32(CMD_TX_PKT|BRANCH_ALWAYS | skb->len); + cpu_to_le32(CMD_TX_PKT|BRANCH_ALWAYS | len); } else { yp->tx_ring[entry+1].dbdma_cmd = cpu_to_le32(CMD_STOP); yp->tx_ring[entry].dbdma_cmd = - cpu_to_le32(CMD_TX_PKT | BRANCH_IFTRUE | skb->len); + cpu_to_le32(CMD_TX_PKT | BRANCH_IFTRUE | len); } yp->cur_tx++; #else - yp->tx_ring[entry<<1].request_cnt = skb->len; + yp->tx_ring[entry<<1].request_cnt = len; yp->tx_ring[entry<<1].addr = cpu_to_le32(pci_map_single(yp->pci_dev, - skb->data, skb->len, PCI_DMA_TODEVICE)); + skb->data, len, PCI_DMA_TODEVICE)); /* The input_last (status-write) command is constant, but we must rewrite the subsequent 'stop' command. */ @@ -910,7 +919,7 @@ yp->tx_ring[entry<<1].dbdma_cmd = cpu_to_le32( ((entry % 6) == 0 ? CMD_TX_PKT|INTR_ALWAYS|BRANCH_IFTRUE : - CMD_TX_PKT | BRANCH_IFTRUE) | skb->len); + CMD_TX_PKT | BRANCH_IFTRUE) | len); #endif /* Non-x86 Todo: explicitly flush cache lines here. */ diff -Nru a/drivers/net/znet.c b/drivers/net/znet.c --- a/drivers/net/znet.c Mon Jan 13 10:18:04 2003 +++ b/drivers/net/znet.c Mon Jan 13 10:18:04 2003 @@ -538,10 +538,18 @@ int ioaddr = dev->base_addr; struct znet_private *znet = dev->priv; unsigned long flags; + short length = skb->len; if (znet_debug > 4) printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name); + if (length < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + length = ETH_ZLEN; + } + netif_stop_queue (dev); /* Check that the part hasn't reset itself, probably from suspend. */ @@ -556,7 +564,6 @@ } if (1) { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = (void *)skb->data; ushort *tx_link = znet->tx_cur - 1; ushort rnd_len = (length + 1)>>1; diff -Nru a/drivers/pci/Kconfig b/drivers/pci/Kconfig --- a/drivers/pci/Kconfig Mon Jan 13 10:18:05 2003 +++ b/drivers/pci/Kconfig Mon Jan 13 10:18:05 2003 @@ -3,6 +3,7 @@ # config PCI_LEGACY_PROC bool "Legacy /proc/pci interface" + depends on PCI ---help--- This feature enables a procfs file -- /proc/pci -- that provides a summary of PCI devices in the system. diff -Nru a/drivers/pci/pool.c b/drivers/pci/pool.c --- a/drivers/pci/pool.c Mon Jan 13 10:18:07 2003 +++ b/drivers/pci/pool.c Mon Jan 13 10:18:07 2003 @@ -34,19 +34,16 @@ DECLARE_MUTEX (pools_lock); static ssize_t -show_pools (struct device *dev, char *buf, size_t count, loff_t off) +show_pools (struct device *dev, char *buf) { struct pci_dev *pdev; unsigned temp, size; char *next; struct list_head *i, *j; - if (off != 0) - return 0; - pdev = container_of (dev, struct pci_dev, dev); next = buf; - size = count; + size = PAGE_SIZE; temp = snprintf (next, size, "poolinfo - 0.1\n"); size -= temp; @@ -77,7 +74,7 @@ } up (&pools_lock); - return count - size; + return PAGE_SIZE - size; } static DEVICE_ATTR (pools, S_IRUGO, show_pools, NULL); diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c Mon Jan 13 10:18:06 2003 +++ b/drivers/pci/probe.c Mon Jan 13 10:18:06 2003 @@ -262,7 +262,8 @@ pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass); - if ((buses & 0xffff00) && !pcibios_assign_all_busses()) { + if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { + unsigned int cmax; /* * Bus already configured by firmware, process it in the first * pass and just note the configuration. @@ -274,13 +275,8 @@ child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->number = child->secondary; - if (!is_cardbus) { - unsigned int cmax = pci_do_scan_bus(child); - if (cmax > max) max = cmax; - } else { - unsigned int cmax = child->subordinate; - if (cmax > max) max = cmax; - } + cmax = pci_do_scan_bus(child); + if (cmax > max) max = cmax; } else { /* * We need to assign a number to this bus which we always diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c --- a/drivers/pci/proc.c Mon Jan 13 10:18:06 2003 +++ b/drivers/pci/proc.c Mon Jan 13 10:18:06 2003 @@ -374,32 +374,25 @@ struct proc_dir_entry *proc_bus_pci_dir; /* driverfs files */ -static ssize_t pci_show_irq(struct device * dev, char * buf, size_t count, loff_t off) +static ssize_t pci_show_irq(struct device * dev, char * buf) { struct pci_dev * pci_dev = to_pci_dev(dev); - return off ? 0 : sprintf(buf,"%u\n",pci_dev->irq); + return sprintf(buf,"%u\n",pci_dev->irq); } static DEVICE_ATTR(irq,S_IRUGO,pci_show_irq,NULL); -static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off) +static ssize_t pci_show_resources(struct device * dev, char * buf) { struct pci_dev * pci_dev = to_pci_dev(dev); char * str = buf; int i; - if (off && off < DEVICE_COUNT_RESOURCE) { + for (i = 0; i < DEVICE_COUNT_RESOURCE && pci_resource_start(pci_dev,i); i++) { str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n", - pci_resource_start(pci_dev,off), - pci_resource_end(pci_dev,off), - pci_resource_flags(pci_dev,off)); - } else if (!off) { - for (i = 0; i < DEVICE_COUNT_RESOURCE && pci_resource_start(pci_dev,i); i++) { - str += sprintf(str,LONG_FORMAT LONG_FORMAT LONG_FORMAT "\n", - pci_resource_start(pci_dev,i), - pci_resource_end(pci_dev,i), - pci_resource_flags(pci_dev,i)); - } + pci_resource_start(pci_dev,i), + pci_resource_end(pci_dev,i), + pci_resource_flags(pci_dev,i)); } return (str - buf); } diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c --- a/drivers/pcmcia/cardbus.c Mon Jan 13 10:18:05 2003 +++ b/drivers/pcmcia/cardbus.c Mon Jan 13 10:18:05 2003 @@ -281,6 +281,8 @@ dev->vendor = vend; pci_readw(dev, PCI_DEVICE_ID, &dev->device); dev->hdr_type = hdr & 0x7f; + dev->dma_mask = 0xffffffff; + dev->dev.dma_mask = &dev->dma_mask; pci_setup_device(dev); if (pci_enable_device(dev)) diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c Mon Jan 13 10:18:07 2003 +++ b/drivers/pcmcia/i82365.c Mon Jan 13 10:18:07 2003 @@ -839,18 +839,24 @@ for (devid = id_table; devid->vendor; devid++) { if ((dev = pnp_find_dev(NULL, devid->vendor, devid->function, NULL))) { + + if (pnp_device_attach(dev) < 0) + continue; + printk("PNP "); - + if (pnp_activate_dev(dev, NULL) < 0) { printk("activate failed\n"); + pnp_device_detach(dev); break; } - i365_base = pnp_port_start(dev, 0); - if (i365_base) { - printk("no resources ?\n"); + if (pnp_port_valid(dev, 0)) { + printk("invalid resources ?\n"); + pnp_device_detach(dev); break; } + i365_base = pnp_port_start(dev, 0); i82365_pnpdev = dev; break; } diff -Nru a/drivers/pnp/card.c b/drivers/pnp/card.c --- a/drivers/pnp/card.c Mon Jan 13 10:18:07 2003 +++ b/drivers/pnp/card.c Mon Jan 13 10:18:07 2003 @@ -62,6 +62,7 @@ return -EINVAL; if (!card) return -EINVAL; + id->next = NULL; ptr = card->id; while (ptr && ptr->next) ptr = ptr->next; @@ -109,6 +110,7 @@ card->dev.parent = &card->protocol->dev; card->dev.bus = &pnpc_bus_type; card->dev.release = &pnp_release_card; + card->status = PNP_READY; error = device_register(&card->dev); if (error == 0){ struct list_head *pos; @@ -131,16 +133,17 @@ void pnpc_remove_card(struct pnp_card *card) { - struct list_head *pos; + struct list_head *pos, *temp; if (!card) return; device_unregister(&card->dev); spin_lock(&pnp_lock); - list_del_init(&card->global_list); - list_del_init(&card->protocol_list); + list_del(&card->global_list); + list_del(&card->protocol_list); spin_unlock(&pnp_lock); - list_for_each(pos,&card->devices){ + list_for_each_safe(pos,temp,&card->devices){ struct pnp_dev *dev = card_to_pnp_dev(pos); + pnpc_remove_device(dev); __pnp_remove_device(dev); } } @@ -174,7 +177,7 @@ { spin_lock(&pnp_lock); dev->card = NULL; - list_del_init(&dev->card_list); + list_del(&dev->card_list); spin_unlock(&pnp_lock); __pnp_remove_device(dev); } @@ -213,6 +216,13 @@ return NULL; found: + spin_lock(&pnp_lock); + if(dev->status != PNP_READY){ + spin_unlock(&pnp_lock); + return NULL; + } + dev->status = PNP_ATTACHED; + spin_unlock(&pnp_lock); cdrv = to_pnpc_driver(card->dev.driver); if (dev->active == 0) { if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) { @@ -239,20 +249,43 @@ void pnp_release_card_device(struct pnp_dev *dev) { spin_lock(&pnp_lock); - list_del_init(&dev->rdev_list); + list_del(&dev->rdev_list); + if (dev->status == PNP_ATTACHED) + dev->status = PNP_READY; spin_unlock(&pnp_lock); pnp_disable_dev(dev); } static void pnpc_recover_devices(struct pnp_card *card) { - struct list_head *pos; - list_for_each(pos,&card->rdevs){ + struct list_head *pos, *temp; + list_for_each_safe(pos,temp,&card->rdevs){ struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list); pnp_release_card_device(dev); } } +int pnpc_attach(struct pnp_card *pnp_card) +{ + spin_lock(&pnp_lock); + if(pnp_card->status != PNP_READY){ + spin_unlock(&pnp_lock); + return -EBUSY; + } + pnp_card->status = PNP_ATTACHED; + spin_unlock(&pnp_lock); + return 0; +} + +void pnpc_detach(struct pnp_card *pnp_card) +{ + spin_lock(&pnp_lock); + if (pnp_card->status == PNP_ATTACHED) + pnp_card->status = PNP_READY; + spin_unlock(&pnp_lock); + pnpc_recover_devices(pnp_card); +} + static int pnpc_card_probe(struct device *dev) { int error = 0; @@ -262,6 +295,9 @@ pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name); + error = pnpc_attach(card); + if (error < 0) + return error; if (drv->probe) { card_id = match_card(drv, card); if (card_id != NULL) @@ -270,7 +306,7 @@ card->driver = drv; error = 0; } else - pnpc_recover_devices(card); + pnpc_detach(card); } return error; } @@ -285,7 +321,7 @@ drv->remove(card); card->driver = NULL; } - pnpc_recover_devices(card); + pnpc_detach(card); return 0; } @@ -348,3 +384,5 @@ EXPORT_SYMBOL(pnpc_register_driver); EXPORT_SYMBOL(pnpc_unregister_driver); EXPORT_SYMBOL(pnpc_add_id); +EXPORT_SYMBOL(pnpc_attach); +EXPORT_SYMBOL(pnpc_detach); diff -Nru a/drivers/pnp/core.c b/drivers/pnp/core.c --- a/drivers/pnp/core.c Mon Jan 13 10:18:05 2003 +++ b/drivers/pnp/core.c Mon Jan 13 10:18:05 2003 @@ -81,7 +81,7 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol) { spin_lock(&pnp_lock); - list_del_init(&protocol->protocol_list); + list_del(&protocol->protocol_list); spin_unlock(&pnp_lock); device_unregister(&protocol->dev); } @@ -119,6 +119,7 @@ dev->dev.name[DEVICE_NAME_SIZE-1] = '\0'; dev->dev.bus = &pnp_bus_type; dev->dev.release = &pnp_release_device; + dev->status = PNP_READY; error = device_register(&dev->dev); if (error == 0){ spin_lock(&pnp_lock); @@ -149,8 +150,8 @@ void __pnp_remove_device(struct pnp_dev *dev) { spin_lock(&pnp_lock); - list_del_init(&dev->global_list); - list_del_init(&dev->protocol_list); + list_del(&dev->global_list); + list_del(&dev->protocol_list); spin_unlock(&pnp_lock); device_unregister(&dev->dev); } @@ -171,7 +172,7 @@ static int __init pnp_init(void) { - printk(KERN_INFO "Linux Plug and Play Support v0.93 (c) Adam Belay\n"); + printk(KERN_INFO "Linux Plug and Play Support v0.94 (c) Adam Belay\n"); return bus_register(&pnp_bus_type); } diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c --- a/drivers/pnp/driver.c Mon Jan 13 10:18:07 2003 +++ b/drivers/pnp/driver.c Mon Jan 13 10:18:07 2003 @@ -19,6 +19,7 @@ #endif #include +#include "base.h" static int compare_func(const char *ida, const char *idb) { @@ -64,6 +65,27 @@ return NULL; } +int pnp_device_attach(struct pnp_dev *pnp_dev) +{ + spin_lock(&pnp_lock); + if(pnp_dev->status != PNP_READY){ + spin_unlock(&pnp_lock); + return -EBUSY; + } + pnp_dev->status = PNP_ATTACHED; + spin_unlock(&pnp_lock); + return 0; +} + +void pnp_device_detach(struct pnp_dev *pnp_dev) +{ + spin_lock(&pnp_lock); + if (pnp_dev->status == PNP_ATTACHED) + pnp_dev->status = PNP_READY; + spin_unlock(&pnp_lock); + pnp_disable_dev(pnp_dev); +} + static int pnp_device_probe(struct device *dev) { int error; @@ -75,6 +97,10 @@ pnp_dbg("pnp: match found with the PnP device '%s' and the driver '%s'", dev->bus_id,pnp_drv->name); + error = pnp_device_attach(pnp_dev); + if (error < 0) + return error; + if (pnp_dev->active == 0) { if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) { error = pnp_activate_dev(pnp_dev, NULL); @@ -95,6 +121,12 @@ pnp_dev->driver = pnp_drv; error = 0; } + else + goto fail; + return error; + +fail: + pnp_device_detach(pnp_dev); return error; } @@ -108,7 +140,7 @@ drv->remove(pnp_dev); pnp_dev->driver = NULL; } - pnp_disable_dev(pnp_dev); + pnp_device_detach(pnp_dev); return 0; } @@ -172,6 +204,7 @@ return -EINVAL; if (!dev) return -EINVAL; + id->next = NULL; ptr = dev->id; while (ptr && ptr->next) ptr = ptr->next; @@ -185,3 +218,5 @@ EXPORT_SYMBOL(pnp_register_driver); EXPORT_SYMBOL(pnp_unregister_driver); EXPORT_SYMBOL(pnp_add_id); +EXPORT_SYMBOL(pnp_device_attach); +EXPORT_SYMBOL(pnp_device_detach); diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c --- a/drivers/pnp/interface.c Mon Jan 13 10:18:05 2003 +++ b/drivers/pnp/interface.c Mon Jan 13 10:18:05 2003 @@ -215,14 +215,13 @@ pnp_print_mem32(buffer, space, mem32); } -static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf, size_t count, loff_t off) +static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_resources * res = dev->res; int dep = 0; pnp_info_buffer_t *buffer; - if (off) - return 0; + buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t)); if (!buffer) return -ENOMEM; @@ -242,57 +241,58 @@ static DEVICE_ATTR(possible,S_IRUGO,pnp_show_possible_resources,NULL); -static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf, size_t count, loff_t off) +static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); char *str = buf; int i; - if (off) - return 0; + if (!dev->active){ str += sprintf(str,"DISABLED\n"); goto done; } - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - if (dev->resource[i].flags & IORESOURCE_IO){ - str += sprintf(str,"io"); - str += sprintf(str," 0x%lx-0x%lx \n", - dev->resource[i].start, - dev->resource[i].end); - } - if (dev->resource[i].flags & IORESOURCE_MEM){ - str += sprintf(str,"mem"); - str += sprintf(str," 0x%lx-0x%lx \n", - dev->resource[i].start, - dev->resource[i].end); - } + for (i = 0; i < DEVICE_COUNT_IO; i++) { + if (pnp_port_valid(dev, i)) { + str += sprintf(str,"io"); + str += sprintf(str," 0x%lx-0x%lx \n", + pnp_port_start(dev, i), + pnp_port_end(dev, i)); + } + } + for (i = 0; i < DEVICE_COUNT_MEM; i++) { + if (pnp_mem_valid(dev, i)) { + str += sprintf(str,"mem"); + str += sprintf(str," 0x%lx-0x%lx \n", + pnp_mem_start(dev, i), + pnp_mem_end(dev, i)); + } } - for (i = 0; i < DEVICE_COUNT_IRQ && dev->irq_resource[i].flags - & IORESOURCE_IRQ; i++) { + for (i = 0; i < DEVICE_COUNT_IRQ; i++) { + if (pnp_irq_valid(dev, i)) { str += sprintf(str,"irq"); - str += sprintf(str," %ld \n", dev->irq_resource[i].start); + str += sprintf(str," %ld \n", pnp_irq(dev, i)); + } } - for (i = 0; i < DEVICE_COUNT_DMA && dev->dma_resource[i].flags - & IORESOURCE_DMA; i++) { + for (i = 0; i < DEVICE_COUNT_DMA; i++) { + if (pnp_dma_valid(dev, i)) { str += sprintf(str,"dma"); - str += sprintf(str," %ld \n", dev->dma_resource[i].start); + str += sprintf(str," %ld \n", pnp_dma(dev, i)); + } } done: return (str - buf); } static ssize_t -pnp_set_current_resources(struct device * dmdev, const char * buf, size_t count, loff_t off) +pnp_set_current_resources(struct device * dmdev, const char * buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); char command[20]; - char type[20]; int num_args; int error = 0; - int depnum, mode = 0; - if (off) - return 0; - num_args = sscanf(buf,"%10s %i %10s",command,&depnum,type); + int depnum; + + num_args = sscanf(buf,"%10s %i",command,&depnum); if (!num_args) goto done; if (!strnicmp(command,"lock",4)) { @@ -320,27 +320,24 @@ goto done; } if (!strnicmp(command,"manual",6)) { - if (num_args != 3) + if (num_args != 2) goto done; - if (!strnicmp(type,"static",6)) - mode = PNP_STATIC; - error = pnp_raw_set_dev(dev,depnum,NULL,mode); + error = pnp_raw_set_dev(dev,depnum,NULL); goto done; } done: - return error < 0 ? error : count; + return error < 0 ? error : strlen(buf); } static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR, pnp_show_current_resources,pnp_set_current_resources); -static ssize_t pnp_show_current_ids(struct device *dmdev, char *buf, size_t count, loff_t off) +static ssize_t pnp_show_current_ids(struct device *dmdev, char *buf) { char *str = buf; struct pnp_dev *dev = to_pnp_dev(dmdev); struct pnp_id * pos = dev->id; - if (off) - return 0; + while (pos) { str += sprintf(str,"%s\n", pos->id); pos = pos->next; diff -Nru a/drivers/pnp/isapnp/compat.c b/drivers/pnp/isapnp/compat.c --- a/drivers/pnp/isapnp/compat.c Mon Jan 13 10:18:07 2003 +++ b/drivers/pnp/isapnp/compat.c Mon Jan 13 10:18:07 2003 @@ -8,10 +8,11 @@ /* TODO: see if more isapnp functions are needed here */ -#include +#include +#include +#include #include #include -#include static void pnp_convert_id(char *buf, unsigned short vendor, unsigned short device) { @@ -29,8 +30,8 @@ unsigned short device, struct pnp_card *from) { - char id[7]; - char any[7]; + char id[8]; + char any[8]; struct list_head *list; pnp_convert_id(id, vendor, device); pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID); @@ -51,8 +52,8 @@ unsigned short function, struct pnp_dev *from) { - char id[7]; - char any[7]; + char id[8]; + char any[8]; pnp_convert_id(id, vendor, function); pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID); if (card == NULL) { /* look for a logical device from all cards */ diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c Mon Jan 13 10:18:06 2003 +++ b/drivers/pnp/isapnp/core.c Mon Jan 13 10:18:06 2003 @@ -454,6 +454,10 @@ if (size > 5) dev->regs |= tmp[5] << 8; dev->protocol = &isapnp_protocol; + dev->capabilities |= PNP_CONFIGURABLE; + dev->capabilities |= PNP_READ; + dev->capabilities |= PNP_WRITE; + dev->capabilities |= PNP_DISABLE; return dev; } @@ -889,7 +893,7 @@ if (isapnp_checksum_value != 0x00) printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value); card->checksum = isapnp_checksum_value; - card->protocol = &isapnp_card_protocol; + card->protocol = &isapnp_protocol; pnpc_add_card(card); } return 0; @@ -903,7 +907,7 @@ { struct pnp_card *card; pnp_for_each_card(card) { - if (card->protocol == &isapnp_card_protocol) + if (card->protocol == &isapnp_protocol) return 1; } return 0; @@ -956,19 +960,25 @@ dev->irq_resource[idx].name = NULL; dev->irq_resource[idx].start = -1; dev->irq_resource[idx].end = -1; - dev->irq_resource[idx].flags = 0; + dev->irq_resource[idx].flags = IORESOURCE_IRQ|IORESOURCE_UNSET; } for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) { dev->dma_resource[idx].name = NULL; dev->dma_resource[idx].start = -1; dev->dma_resource[idx].end = -1; - dev->dma_resource[idx].flags = 0; + dev->dma_resource[idx].flags = IORESOURCE_DMA|IORESOURCE_UNSET; } - for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) { - dev->resource[idx].name = NULL; - dev->resource[idx].start = 0; - dev->resource[idx].end = 0; - dev->resource[idx].flags = 0; + for (idx = 0; idx < DEVICE_COUNT_IO; idx++) { + dev->io_resource[idx].name = NULL; + dev->io_resource[idx].start = 0; + dev->io_resource[idx].end = 0; + dev->io_resource[idx].flags = IORESOURCE_IO|IORESOURCE_UNSET; + } + for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) { + dev->mem_resource[idx].name = NULL; + dev->mem_resource[idx].start = 0; + dev->mem_resource[idx].end = 0; + dev->mem_resource[idx].flags = IORESOURCE_MEM|IORESOURCE_UNSET; } return 0; } @@ -993,16 +1003,17 @@ static int isapnp_get_resources(struct pnp_dev *dev) { /* We don't need to do anything but this, the rest is taken care of */ - if ((dev->resource[0].start == 0) && - (dev->irq_resource[0].start == -1) && - (dev->dma_resource[0].start == -1)) + if (pnp_port_valid(dev, 0) == 0 && + pnp_mem_valid(dev, 0) == 0 && + pnp_irq_valid(dev, 0) == 0 && + pnp_dma_valid(dev, 0) == 0) dev->active = 0; else dev->active = 1; return 0; } -static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_cfg *cfg, char flags) +static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_cfg *cfg) { int tmp; isapnp_cfg_begin(dev->card->number, dev->number); @@ -1011,21 +1022,22 @@ dev->irq_resource[1] = cfg->request.irq_resource[1]; dev->dma_resource[0] = cfg->request.dma_resource[0]; dev->dma_resource[1] = cfg->request.dma_resource[1]; - for (tmp = 0; tmp < 12; tmp++) { - dev->resource[tmp] = cfg->request.resource[tmp]; - } - for (tmp = 0; tmp < 8 && dev->resource[tmp].flags; tmp++) - isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start); - for (tmp = 0; tmp < 2 && dev->irq_resource[tmp].flags; tmp++) { - int irq = dev->irq_resource[tmp].start; + for (tmp = 0; tmp < DEVICE_COUNT_IO; tmp++) + dev->io_resource[tmp] = cfg->request.io_resource[tmp]; + for (tmp = 0; tmp < DEVICE_COUNT_MEM; tmp++) + dev->mem_resource[tmp] = cfg->request.mem_resource[tmp]; + for (tmp = 0; tmp < 8 && pnp_port_valid(dev, tmp); tmp++) + isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), pnp_port_start(dev, tmp)); + for (tmp = 0; tmp < 2 && pnp_irq_valid(dev, tmp); tmp++) { + int irq = pnp_irq(dev, tmp); if (irq == 2) irq = 9; isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq); } - for (tmp = 0; tmp < 2 && dev->dma_resource[tmp].flags; tmp++) - isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma_resource[tmp].start); - for (tmp = 0; tmp < 4 && dev->resource[tmp+8].flags; tmp++) - isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff); + for (tmp = 0; tmp < 2 && pnp_dma_valid(dev, tmp); tmp++) + isapnp_write_byte(ISAPNP_CFG_DMA+tmp, pnp_dma(dev, tmp)); + for (tmp = 0; tmp < 4 && pnp_mem_valid(dev, tmp); tmp++) + isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (pnp_mem_start(dev, tmp) >> 8) & 0xffff); isapnp_activate(dev->number); isapnp_cfg_end(); return 0; @@ -1042,15 +1054,8 @@ return 0; } -struct pnp_protocol isapnp_card_protocol = { - .name = "ISA Plug and Play - card", - .get = NULL, - .set = NULL, - .disable = NULL, -}; - struct pnp_protocol isapnp_protocol = { - .name = "ISA Plug and Play - device", + .name = "ISA Plug and Play", .get = isapnp_get_resources, .set = isapnp_set_resources, .disable = isapnp_disable_resources, @@ -1081,9 +1086,6 @@ return -EBUSY; } - if(pnp_register_protocol(&isapnp_card_protocol)<0) - return -EBUSY; - if(pnp_register_protocol(&isapnp_protocol)<0) return -EBUSY; @@ -1123,7 +1125,7 @@ isapnp_build_device_list(); cards = 0; - protocol_for_each_card(&isapnp_protocol,card) { + protocol_for_each_card(&isapnp_card_protocol,card) { cards++; if (isapnp_verbose) { printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown"); @@ -1144,7 +1146,7 @@ return 0; } -device_initcall(isapnp_init); +subsys_initcall(isapnp_init); /* format is: noisapnp */ diff -Nru a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c --- a/drivers/pnp/isapnp/proc.c Mon Jan 13 10:18:05 2003 +++ b/drivers/pnp/isapnp/proc.c Mon Jan 13 10:18:05 2003 @@ -19,12 +19,12 @@ * */ - +#include +#include +#include #include -#include #include #include -#include #include #include diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c --- a/drivers/pnp/pnpbios/core.c Mon Jan 13 10:18:05 2003 +++ b/drivers/pnp/pnpbios/core.c Mon Jan 13 10:18:05 2003 @@ -671,9 +671,10 @@ static void add_irqresource(struct pnp_dev *dev, int irq) { int i = 0; - while (!(dev->irq_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_IRQ) i++; + while (pnp_irq_valid(dev, i) && i < DEVICE_COUNT_IRQ) i++; if (i < DEVICE_COUNT_IRQ) { - dev->irq_resource[i].start = (unsigned long) irq; + dev->irq_resource[i].start = + dev->irq_resource[i].end = (unsigned long) irq; dev->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag } } @@ -681,9 +682,10 @@ static void add_dmaresource(struct pnp_dev *dev, int dma) { int i = 0; - while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++; + while (pnp_dma_valid(dev, i) && i < DEVICE_COUNT_DMA) i++; if (i < DEVICE_COUNT_DMA) { - dev->dma_resource[i].start = (unsigned long) dma; + dev->dma_resource[i].start = + dev->dma_resource[i].end = (unsigned long) dma; dev->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag } } @@ -691,22 +693,22 @@ static void add_ioresource(struct pnp_dev *dev, int io, int len) { int i = 0; - while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++; + while (pnp_port_valid(dev, i) && i < DEVICE_COUNT_IO) i++; if (i < DEVICE_COUNT_RESOURCE) { - dev->resource[i].start = (unsigned long) io; - dev->resource[i].end = (unsigned long)(io + len - 1); - dev->resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag + dev->io_resource[i].start = (unsigned long) io; + dev->io_resource[i].end = (unsigned long)(io + len - 1); + dev->io_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag } } static void add_memresource(struct pnp_dev *dev, int mem, int len) { - int i = 8; - while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++; + int i = 0; + while (pnp_mem_valid(dev, i) && i < DEVICE_COUNT_MEM) i++; if (i < DEVICE_COUNT_RESOURCE) { - dev->resource[i].start = (unsigned long) mem; - dev->resource[i].end = (unsigned long)(mem + len - 1); - dev->resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag + dev->mem_resource[i].start = (unsigned long) mem; + dev->mem_resource[i].end = (unsigned long)(mem + len - 1); + dev->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag } } @@ -718,17 +720,25 @@ /* * First, set resource info to default values */ - for (i=0;iresource[i].start = 0; // "disabled" - dev->resource[i].flags = IORESOURCE_UNSET; + for (i=0;iio_resource[i].start = 0; + dev->io_resource[i].end = 0; + dev->io_resource[i].flags = IORESOURCE_IO|IORESOURCE_UNSET; + } + for (i=0;imem_resource[i].start = 0; + dev->mem_resource[i].end = 0; + dev->mem_resource[i].flags = IORESOURCE_MEM|IORESOURCE_UNSET; } for (i=0;iirq_resource[i].start = (unsigned long)-1; // "disabled" - dev->irq_resource[i].flags = IORESOURCE_UNSET; + dev->irq_resource[i].start = (unsigned long)-1; + dev->irq_resource[i].end = (unsigned long)-1; + dev->irq_resource[i].flags = IORESOURCE_IRQ|IORESOURCE_UNSET; } for (i=0;idma_resource[i].start = (unsigned long)-1; // "disabled" - dev->dma_resource[i].flags = IORESOURCE_UNSET; + dev->dma_resource[i].start = (unsigned long)-1; + dev->dma_resource[i].end = (unsigned long)-1; + dev->dma_resource[i].flags = IORESOURCE_DMA|IORESOURCE_UNSET; } /* @@ -815,10 +825,10 @@ } /* while */ end: - if ((dev->resource[0].start == 0) && - (dev->resource[8].start == 0) && - (dev->irq_resource[0].start == -1) && - (dev->dma_resource[0].start == -1)) + if (pnp_port_valid(dev, 0) == 0 && + pnp_mem_valid(dev, 0) == 0 && + pnp_irq_valid(dev, 0) == 0 && + pnp_dma_valid(dev, 0) == 0) dev->active = 0; else dev->active = 1; @@ -1261,9 +1271,7 @@ struct pnp_bios_node * node; /* just in case */ - if(pnp_dev_has_driver(dev)) - return -EBUSY; - if(!pnp_is_dynamic(dev)) + if(!pnpbios_is_dynamic(dev)) return -EPERM; if (pnp_bios_dev_node_info(&node_info) != 0) return -ENODEV; @@ -1277,16 +1285,14 @@ return 0; } -static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config, char flags) +static int pnpbios_set_resources(struct pnp_dev *dev, struct pnp_cfg *config) { struct pnp_dev_node_info node_info; u8 nodenum = dev->number; struct pnp_bios_node * node; /* just in case */ - if(pnp_dev_has_driver(dev)) - return -EBUSY; - if (flags == PNP_DYNAMIC && !pnp_is_dynamic(dev)) + if (!pnpbios_is_dynamic(dev)) return -EPERM; if (pnp_bios_dev_node_info(&node_info) != 0) return -ENODEV; @@ -1338,9 +1344,7 @@ if (!config) return -1; /* just in case */ - if(pnp_dev_has_driver(dev)) - return -EBUSY; - if(dev->flags & PNP_NO_DISABLE || !pnp_is_dynamic(dev)) + if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev)) return -EPERM; memset(config, 0, sizeof(struct pnp_cfg)); if (!dev || !dev->active) @@ -1449,6 +1453,15 @@ pos = node_possible_resource_data_to_dev(pos,node,dev); node_id_data_to_dev(pos,node,dev); dev->flags = node->flags; + if (!(dev->flags & PNPBIOS_NO_CONFIG)) + dev->capabilities |= PNP_CONFIGURABLE; + if (!(dev->flags & PNPBIOS_NO_DISABLE)) + dev->capabilities |= PNP_DISABLE; + dev->capabilities |= PNP_READ; + if (pnpbios_is_dynamic(dev)) + dev->capabilities |= PNP_WRITE; + if (dev->flags & PNPBIOS_REMOVABLE) + dev->capabilities |= PNP_REMOVABLE; dev->protocol = &pnpbios_protocol; diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c --- a/drivers/pnp/resource.c Mon Jan 13 10:18:06 2003 +++ b/drivers/pnp/resource.c Mon Jan 13 10:18:06 2003 @@ -328,9 +328,9 @@ pnp_for_each_dev(dev) { if (dev->active) { for (tmp = 0; tmp < 8; tmp++) { - if (dev->resource[tmp].flags) { - rport = dev->resource[tmp].start; - rsize = (dev->resource[tmp].end - rport) + 1; + if (pnp_port_valid(dev, tmp)) { + rport = pnp_port_start(dev, tmp); + rsize = pnp_port_len(dev, tmp); if (port >= rport && port < rport + rsize) return 1; if (port + size > rport && port + size < (rport + rsize) - 1) @@ -340,9 +340,10 @@ } } for (tmp = 0; tmp < 8 && tmp != idx; tmp++) { - if (dev->resource[tmp].flags) { - rport = config->request.resource[tmp].start; - rsize = (config->request.resource[tmp].end - rport) + 1; + if (pnp_port_valid(dev, tmp) && + pnp_flags_valid(&config->request.io_resource[tmp])) { + rport = config->request.io_resource[tmp].start; + rsize = (config->request.io_resource[tmp].end - rport) + 1; if (port >= rport && port < rport + rsize) return 1; if (port + size > rport && port + size < (rport + rsize) - 1) @@ -371,9 +372,9 @@ pnp_for_each_dev(dev) { if (dev->active) { for (tmp = 0; tmp < 4; tmp++) { - if (dev->resource[tmp + 8].flags) { - raddr = dev->resource[tmp + 8].start; - rsize = (dev->resource[tmp + 8].end - raddr) + 1; + if (pnp_mem_valid(dev, tmp)) { + raddr = pnp_mem_start(dev, tmp); + rsize = pnp_mem_len(dev, tmp); if (addr >= raddr && addr < raddr + rsize) return 1; if (addr + size > raddr && addr + size < (raddr + rsize) - 1) @@ -383,9 +384,10 @@ } } for (tmp = 0; tmp < 4 && tmp != idx; tmp++) { - if (dev->resource[tmp + 8].flags) { - raddr = config->request.resource[tmp + 8].start; - rsize = (config->request.resource[tmp + 8].end - raddr) + 1; + if (pnp_mem_valid(dev, tmp) && + pnp_flags_valid(&config->request.mem_resource[tmp])) { + raddr = config->request.mem_resource[tmp].start; + rsize = (config->request.mem_resource[tmp].end - raddr) + 1; if (addr >= raddr && addr < raddr + rsize) return 1; if (addr + size > raddr && addr + size < (raddr + rsize) - 1) @@ -417,13 +419,14 @@ } pnp_for_each_dev(dev) { if (dev->active) { - if ((dev->irq_resource[0].flags && dev->irq_resource[0].start == irq) || - (dev->irq_resource[1].flags && dev->irq_resource[1].start == irq)) + if ((pnp_irq_valid(dev, 0) && dev->irq_resource[0].start == irq) || + (pnp_irq_valid(dev, 1) && dev->irq_resource[1].start == irq)) return 1; } } - if (config->request.irq_resource[0].flags && config->request.irq_resource[1].flags && - (config->request.irq_resource[0].start == irq)) + if (pnp_flags_valid(&config->request.irq_resource[0]) && + pnp_flags_valid(&config->request.irq_resource[1]) && + (config->request.irq_resource[0].start == irq)) return 1; #ifdef CONFIG_PCI if (!pnp_skip_pci_scan) { @@ -456,13 +459,14 @@ } pnp_for_each_dev(dev) { if (dev->active) { - if ((dev->dma_resource[0].flags && dev->dma_resource[0].start == dma) || - (dev->dma_resource[1].flags && dev->dma_resource[1].start == dma)) + if ((pnp_dma_valid(dev, 0) && pnp_dma(dev, 0) == dma) || + (pnp_dma_valid(dev, 1) && pnp_dma(dev, 1) == dma)) return 1; } } - if (config->request.dma_resource[0].flags && config->request.dma_resource[1].flags && - (config->request.dma_resource[0].start == dma)) + if (pnp_flags_valid(&config->request.dma_resource[0]) && + pnp_flags_valid(&config->request.dma_resource[1]) && + (config->request.dma_resource[0].start == dma)) return 1; if (request_dma(dma, "pnp")) return 1; @@ -481,11 +485,11 @@ port = config->port[num]; if (!port) return 0; - value1 = &config->request.resource[num].start; - value2 = &config->request.resource[num].end; - value3 = &config->request.resource[num].flags; + value1 = &config->request.io_resource[num].start; + value2 = &config->request.io_resource[num].end; + value3 = &config->request.io_resource[num].flags; *value1 = port->min; - *value2 = *value1 + port->size -1; + *value2 = *value1 + port->size - 1; *value3 = port->flags | IORESOURCE_IO; while (pnp_check_port(*value1, port->size, num, config)) { *value1 += port->align; @@ -505,11 +509,11 @@ mem = config->mem[num]; if (!mem) return 0; - value1 = &config->request.resource[num + 8].start; - value2 = &config->request.resource[num + 8].end; - value3 = &config->request.resource[num].flags; + value1 = &config->request.mem_resource[num].start; + value2 = &config->request.mem_resource[num].end; + value3 = &config->request.mem_resource[num].flags; *value1 = mem->min; - *value2 = *value1 + mem->size -1; + *value2 = *value1 + mem->size - 1; *value3 = mem->flags | IORESOURCE_MEM; if (!(mem->flags & IORESOURCE_MEM_WRITEABLE)) *value3 |= IORESOURCE_READONLY; @@ -597,19 +601,25 @@ for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) { res_config->irq_resource[idx].start = -1; res_config->irq_resource[idx].end = -1; - res_config->irq_resource[idx].flags = 0; + res_config->irq_resource[idx].flags = IORESOURCE_IRQ|IORESOURCE_UNSET; } for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) { res_config->dma_resource[idx].name = NULL; res_config->dma_resource[idx].start = -1; res_config->dma_resource[idx].end = -1; - res_config->dma_resource[idx].flags = 0; + res_config->dma_resource[idx].flags = IORESOURCE_DMA|IORESOURCE_UNSET; } - for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) { - res_config->resource[idx].name = NULL; - res_config->resource[idx].start = 0; - res_config->resource[idx].end = 0; - res_config->resource[idx].flags = 0; + for (idx = 0; idx < DEVICE_COUNT_IO; idx++) { + res_config->io_resource[idx].name = NULL; + res_config->io_resource[idx].start = 0; + res_config->io_resource[idx].end = 0; + res_config->io_resource[idx].flags = IORESOURCE_IO|IORESOURCE_UNSET; + } + for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) { + res_config->mem_resource[idx].name = NULL; + res_config->mem_resource[idx].start = 0; + res_config->mem_resource[idx].end = 0; + res_config->mem_resource[idx].flags = IORESOURCE_MEM|IORESOURCE_UNSET; } return 0; } @@ -629,14 +639,17 @@ if (!template) return 0; for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) - if (template->irq_resource[idx].start >= 0) + if (pnp_flags_valid(&template->irq_resource[idx])) config->request.irq_resource[idx] = template->irq_resource[idx]; for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) - if (template->dma_resource[idx].start >= 0) + if (pnp_flags_valid(&template->dma_resource[idx])) config->request.dma_resource[idx] = template->dma_resource[idx]; - for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) - if (template->resource[idx].start > 0) - config->request.resource[idx] = template->resource[idx]; + for (idx = 0; idx < DEVICE_COUNT_IO; idx++) + if (pnp_flags_valid(&template->io_resource[idx])) + config->request.io_resource[idx] = template->io_resource[idx]; + for (idx = 0; idx < DEVICE_COUNT_MEM; idx++) + if (pnp_flags_valid(&template->io_resource[idx])) + config->request.mem_resource[idx] = template->mem_resource[idx]; return 0; } @@ -750,7 +763,7 @@ dma = dma->next; } return config; - + fail: kfree(config); return NULL; @@ -772,13 +785,13 @@ if (!dev) return -EINVAL; max = pnp_get_max_depnum(dev); - if (dev->active) + if (!pnp_can_configure(dev)) return -EBUSY; - if (pnp_dev_has_driver(dev)){ + if (dev->status != PNP_READY && dev->status != PNP_ATTACHED){ printk(KERN_INFO "pnp: Automatic configuration failed because the PnP device '%s' is busy\n", dev->dev.bus_id); return -EINVAL; } - if (!dev->protocol->get || !dev->protocol->set) + if (!pnp_can_write(dev)) return -EINVAL; if (max == 0) return 0; @@ -796,8 +809,8 @@ done: pnp_dbg("the device '%s' has been activated", dev->dev.bus_id); - dev->protocol->set(dev,config,0); - if (dev->protocol->get) + dev->protocol->set(dev,config); + if (pnp_can_read(dev)) dev->protocol->get(dev); kfree(config); return 0; @@ -814,13 +827,13 @@ { if (!dev) return -EINVAL; - if (pnp_dev_has_driver(dev)){ + if (dev->status != PNP_READY){ printk(KERN_INFO "pnp: Disable failed becuase the PnP device '%s' is busy\n", dev->dev.bus_id); return -EINVAL; } if (dev->lock_resources) return -EPERM; - if (!dev->protocol->disable || !dev->active) + if (!pnp_can_disable(dev) || !dev->active) return -EINVAL; pnp_dbg("the device '%s' has been disabled", dev->dev.bus_id); return dev->protocol->disable(dev); @@ -834,16 +847,16 @@ * */ -int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template, int mode) +int pnp_raw_set_dev(struct pnp_dev *dev, int depnum, struct pnp_res_cfg *template) { struct pnp_cfg *config; if (!dev) return -EINVAL; - if (pnp_dev_has_driver(dev)){ + if (dev->status != PNP_READY){ printk(KERN_INFO "pnp: Unable to set resources because the PnP device '%s' is busy\n", dev->dev.bus_id); return -EINVAL; } - if (!dev->protocol->get || !dev->protocol->set) + if (!pnp_can_write(dev) || !pnp_can_configure(dev)) return -EINVAL; config = pnp_generate_config(dev,depnum); if (!config) @@ -855,8 +868,8 @@ return -ENOENT; done: - dev->protocol->set(dev,config,mode); - if (dev->protocol->get) + dev->protocol->set(dev,config); + if (pnp_can_read(dev)) dev->protocol->get(dev); kfree(config); return 0; @@ -874,7 +887,7 @@ { if (resource == NULL) return; - resource->flags &= ~IORESOURCE_AUTO; + resource->flags &= ~(IORESOURCE_AUTO|IORESOURCE_UNSET); resource->start = start; resource->end = start + size - 1; } diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c --- a/drivers/pnp/system.c Mon Jan 13 10:18:07 2003 +++ b/drivers/pnp/system.c Mon Jan 13 10:18:07 2003 @@ -53,44 +53,33 @@ { int i; - for (i=0;iresource[i].flags & IORESOURCE_UNSET ) + for (i=0;iresource[i].flags & IORESOURCE_IO) { - /* ioport */ - if ( dev->resource[i].start == 0 ) - /* disabled */ - /* Do nothing */ - continue; - if ( dev->resource[i].start < 0x100 ) - /* - * Below 0x100 is only standard PC hardware - * (pics, kbd, timer, dma, ...) - * We should not get resource conflicts there, - * and the kernel reserves these anyway - * (see arch/i386/kernel/setup.c). - * So, do nothing - */ - continue; - if ( dev->resource[i].end < dev->resource[i].start ) - /* invalid endpoint */ - /* Do nothing */ - continue; - reserve_ioport_range( - dev->dev.bus_id, - dev->resource[i].start, - dev->resource[i].end - ); - } else if (dev->resource[i].flags & IORESOURCE_MEM) { - /* iomem */ - /* For now do nothing */ continue; - } else { - /* Neither ioport nor iomem */ + if (pnp_port_start(dev, i) == 0) + /* disabled */ /* Do nothing */ continue; - } + if (pnp_port_start(dev, i) < 0x100) + /* + * Below 0x100 is only standard PC hardware + * (pics, kbd, timer, dma, ...) + * We should not get resource conflicts there, + * and the kernel reserves these anyway + * (see arch/i386/kernel/setup.c). + * So, do nothing + */ + continue; + if (pnp_port_end(dev, i) < pnp_port_start(dev, i)) + /* invalid endpoint */ + /* Do nothing */ + continue; + reserve_ioport_range( + dev->dev.bus_id, + pnp_port_start(dev, i), + pnp_port_end(dev, i) + ); } return; diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c Mon Jan 13 10:18:05 2003 +++ b/drivers/scsi/NCR53C9x.c Mon Jan 13 10:18:05 2003 @@ -1164,7 +1164,7 @@ * ID bit on the data bus even though the ESP is * at ID 7 and is the obvious winner for any * arbitration. The ESP is a poor sport and refuses - * to lose arbitration, it will continue indefinately + * to lose arbitration, it will continue indefinitely * trying to arbitrate for the bus and can only be * stopped via a chip reset or SCSI bus reset. * Therefore _no_ disconnects for SCSI1 targets diff -Nru a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c --- a/drivers/scsi/aha152x.c Mon Jan 13 10:18:05 2003 +++ b/drivers/scsi/aha152x.c Mon Jan 13 10:18:05 2003 @@ -970,7 +970,7 @@ } #ifdef __ISAPNP__ -static struct pci_dev *pnpdev[2]; +static struct pnp_dev *pnpdev[2]; static int num_pnpdevs; #endif int aha152x_detect(Scsi_Host_Template * tpnt) @@ -979,7 +979,7 @@ #if defined(AUTOCONF) aha152x_config conf; #ifdef __ISAPNP__ - struct pci_dev *dev = NULL; + struct pnp_dev *dev = NULL; #endif #endif tpnt->proc_name = "aha152x"; @@ -1128,22 +1128,23 @@ #endif #ifdef __ISAPNP__ - while ( setup_countprepare(dev) < 0) + while ( setup_countactive) + if (pnp_activate_dev(dev, NULL) < 0) { + pnp_device_detach(dev); continue; - if (!(dev->resource[0].flags & IORESOURCE_IO)) - continue; - dev->resource[0].flags |= IORESOURCE_AUTO; - if (dev->activate(dev) < 0) + } + if (!pnp_port_valid(dev, 0)) { + pnp_device_detach(dev); continue; - if ( setup_count==1 && dev->resource[0].start==setup[0].io_port) { - dev->deactivate(dev); + } + if (setup_count==1 && pnp_port_start(dev, 0)==setup[0].io_port) { + pnp_device_detach(dev); continue; } - setup[setup_count].io_port = dev->resource[0].start; - setup[setup_count].irq = dev->irq_resource[0].start; + setup[setup_count].io_port = pnp_port_start(dev, 0); + setup[setup_count].irq = pnp_irq(dev, 0); setup[setup_count].scsiid = 7; setup[setup_count].reconnect = 1; setup[setup_count].parity = 1; @@ -1421,7 +1422,7 @@ #ifdef __ISAPNP__ while (num_pnpdevs--) - pnpdev[num_pnpdevs]->deactivate(pnpdev[num_pnpdevs]); + pnp_device_detach(pnpdev[num_pnpdevs]); #endif scsi_unregister(shpnt); diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c Mon Jan 13 10:18:06 2003 +++ b/drivers/scsi/aha1542.c Mon Jan 13 10:18:06 2003 @@ -1144,12 +1144,12 @@ if(isapnp) { - struct pci_dev *pdev = NULL; + struct pnp_dev *pdev = NULL; for(indx = 0; indx prepare(pdev)<0) + if(pnp_device_attach(pdev)<0) continue; - - if(!(pdev->resource[0].flags&IORESOURCE_IO)) + + if(pnp_activate_dev(pdev, NULL)<0) { + pnp_device_detach(pdev); continue; - - pdev->resource[0].flags|=IORESOURCE_AUTO; - - if(pdev->activate(pdev)<0) + } + + if(!pnp_port_valid(pdev, 0)) { + pnp_device_detach(pdev); continue; + } - bases[indx] = pdev->resource[0].start; + bases[indx] = pnp_port_start(pdev, 0); /* The card can be queried for its DMA, we have the DMA set up that is enough */ diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c --- a/drivers/scsi/esp.c Mon Jan 13 10:18:07 2003 +++ b/drivers/scsi/esp.c Mon Jan 13 10:18:07 2003 @@ -1720,7 +1720,7 @@ * ID bit on the data bus even though the ESP is * at ID 7 and is the obvious winner for any * arbitration. The ESP is a poor sport and refuses - * to lose arbitration, it will continue indefinately + * to lose arbitration, it will continue indefinitely * trying to arbitrate for the bus and can only be * stopped via a chip reset or SCSI bus reset. * Therefore _no_ disconnects for SCSI1 targets diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c Mon Jan 13 10:18:06 2003 +++ b/drivers/scsi/fdomain.c Mon Jan 13 10:18:06 2003 @@ -301,7 +301,7 @@ /* START OF USER DEFINABLE OPTIONS */ -#define DEBUG 1 /* Enable debugging output */ +#define DEBUG 0 /* Enable debugging output */ #define ENABLE_PARITY 1 /* Enable SCSI Parity */ #define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ #define DO_DETECT 0 /* Do device detection here (see scsi.c) */ diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c Mon Jan 13 10:18:05 2003 +++ b/drivers/scsi/g_NCR5380.c Mon Jan 13 10:18:05 2003 @@ -314,30 +314,34 @@ overrides[0].board = BOARD_DTC3181E; if (!current_override && isapnp_present()) { - struct pci_dev *dev = NULL; + struct pnp_dev *dev = NULL; count = 0; - while ((dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { + while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { if (count >= NO_OVERRIDES) break; - if (!dev->active && dev->prepare(dev) < 0) { - printk(KERN_ERR "dtc436e probe: prepare failed\n"); + if (pnp_device_attach(dev) < 0) { + printk(KERN_ERR "dtc436e probe: attach failed\n"); continue; } - if (!(dev->resource[0].flags & IORESOURCE_IO)) - continue; - if (!dev->active && dev->activate(dev) < 0) { + if (pnp_activate_dev(dev, NULL) < 0) { printk(KERN_ERR "dtc436e probe: activate failed\n"); + pnp_device_detach(dev); + continue; + } + if (!pnp_port_valid(dev, 0)) { + printk(KERN_ERR "dtc436e probe: no valid port\n"); + pnp_device_detach(dev); continue; } - if (dev->irq_resource[0].flags & IORESOURCE_IRQ) - overrides[count].irq = dev->irq_resource[0].start; + if (pnp_irq_valid(dev, 0)) + overrides[count].irq = pnp_irq(dev, 0); else overrides[count].irq = IRQ_NONE; - if (dev->dma_resource[0].flags & IORESOURCE_DMA) - overrides[count].dma = dev->dma_resource[0].start; + if (pnp_dma_valid(dev, 0)) + overrides[count].dma = pnp_dma(dev, 0); else overrides[count].dma = DMA_NONE; - overrides[count].NCR5380_map_name = (NCR5380_map_type) dev->resource[0].start; + overrides[count].NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0); overrides[count].board = BOARD_DTC3181E; count++; } diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Mon Jan 13 10:18:05 2003 +++ b/drivers/scsi/ips.c Mon Jan 13 10:18:05 2003 @@ -186,7 +186,6 @@ #ifdef MODULE static char *ips = NULL; MODULE_PARM(ips, "s"); - MODULE_LICENSE("GPL"); #endif /* @@ -6974,9 +6973,7 @@ } -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,9) MODULE_LICENSE("GPL"); -#endif /* * Overrides for Emacs so that we almost follow Linus's tabbing style. diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Mon Jan 13 10:18:05 2003 +++ b/drivers/scsi/scsi_sysfs.c Mon Jan 13 10:18:05 2003 @@ -23,20 +23,16 @@ * Return: * number of bytes written into page. **/ -static ssize_t scsi_host_class_name_show(struct device *dev, char *page, - size_t count, loff_t off) +static ssize_t scsi_host_class_name_show(struct device *dev, char *page) { struct Scsi_Host *shost; - if (off) - return 0; - shost = to_scsi_host(dev); if (!shost) return 0; - return snprintf(page, count, "scsi%d\n", shost->host_no); + return snprintf(page, 20, "scsi%d\n", shost->host_no); } DEVICE_ATTR(class_name, S_IRUGO, scsi_host_class_name_show, NULL); @@ -138,13 +134,11 @@ */ #define show_function(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf, size_t count, loff_t off) \ +show_##field (struct device *dev, char *buf) \ { \ struct scsi_device *sdev; \ - if (off) \ - return 0; \ sdev = to_scsi_device(dev); \ - return snprintf (buf, count, format_string, sdev->field); \ + return snprintf (buf, 20, format_string, sdev->field); \ } \ /* @@ -164,14 +158,12 @@ show_function(field, format_string) \ \ static ssize_t \ -store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\ +store_##field (struct device *dev, const char *buf) \ { \ struct scsi_device *sdev; \ - \ - if (off) \ - return 0; \ sdev = to_scsi_device(dev); \ - return snscanf (buf, count, format_string, &sdev->field); \ + snscanf (buf, 20, format_string, &sdev->field); \ + return strlen(buf); \ } \ static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, store_##field) @@ -183,18 +175,15 @@ show_function(field, "%d\n") \ \ static ssize_t \ -store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\ +store_##field (struct device *dev, const char *buf) \ { \ int ret; \ struct scsi_device *sdev; \ - \ - if (off) \ - return 0; \ ret = scsi_sdev_check_buf_bit(buf); \ if (ret >= 0) { \ sdev = to_scsi_device(dev); \ sdev->field = ret; \ - ret = count; \ + ret = strlen(buf); \ } \ return ret; \ } \ diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Mon Jan 13 10:18:06 2003 +++ b/drivers/scsi/sg.c Mon Jan 13 10:18:06 2003 @@ -1350,20 +1350,18 @@ /* Driverfs file support */ static ssize_t -sg_device_kdev_read(struct device *driverfs_dev, char *page, - size_t count, loff_t off) +sg_device_kdev_read(struct device *driverfs_dev, char *page) { Sg_device *sdp = list_entry(driverfs_dev, Sg_device, sg_driverfs_dev); - return off ? 0 : sprintf(page, "%x\n", MKDEV(sdp->disk->major, - sdp->disk->first_minor)); + return sprintf(page, "%x\n", MKDEV(sdp->disk->major, + sdp->disk->first_minor)); } static DEVICE_ATTR(kdev,S_IRUGO,sg_device_kdev_read,NULL); static ssize_t -sg_device_type_read(struct device *driverfs_dev, char *page, - size_t count, loff_t off) +sg_device_type_read(struct device *driverfs_dev, char *page) { - return off ? 0 : sprintf(page, "CHR\n"); + return sprintf(page, "CHR\n"); } static DEVICE_ATTR(type,S_IRUGO,sg_device_type_read,NULL); diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c --- a/drivers/scsi/sym53c416.c Mon Jan 13 10:18:05 2003 +++ b/drivers/scsi/sym53c416.c Mon Jan 13 10:18:05 2003 @@ -635,7 +635,7 @@ struct Scsi_Host * shpnt = NULL; int i; int count; - struct pci_dev *idev = NULL; + struct pnp_dev *idev = NULL; #ifdef MODULE int ints[3]; @@ -669,26 +669,27 @@ printk(KERN_INFO "sym53c416.c: %s\n", VERSION_STRING); for (i=0; id_table[i].vendor != 0; i++) { - while((idev=isapnp_find_dev(NULL, id_table[i].vendor, + while((idev=pnp_find_dev(NULL, id_table[i].vendor, id_table[i].function, idev))!=NULL) { int i[3]; - if(idev->prepare(idev)<0) + if(pnp_device_attach(idev)<0) { - printk(KERN_WARNING "sym53c416: unable to prepare PnP card.\n"); + printk(KERN_WARNING "sym53c416: unable to attach PnP device.\n"); continue; } - if(idev->activate(idev)<0) + if(pnp_activate_dev(idev, NULL)<0) { - printk(KERN_WARNING "sym53c416: unable to activate PnP card.\n"); + printk(KERN_WARNING "sym53c416: unable to activate PnP device.\n"); + pnp_device_detach(idev); continue; } i[0] = 2; - i[1] = idev->resource[0].start; - i[2] = idev->irq_resource[0].start; + i[1] = pnp_port_start(idev, 0); + i[2] = pnp_irq(idev, 0); printk(KERN_INFO "sym53c416: ISAPnP card found and configured at 0x%X, IRQ %d.\n", i[1], i[2]); diff -Nru a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c --- a/drivers/serial/sunzilog.c Mon Jan 13 10:18:07 2003 +++ b/drivers/serial/sunzilog.c Mon Jan 13 10:18:07 2003 @@ -112,10 +112,7 @@ #define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->membase)) #define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT)) -#define SUNZILOG_GET_CURR_REG(PORT, REGNUM) \ - (UART_ZILOG(PORT)->curregs[REGNUM]) -#define SUNZILOG_SET_CURR_REG(PORT, REGNUM, REGVAL) \ - ((UART_ZILOG(PORT)->curregs[REGNUM]) = (REGVAL)) + #define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB) #define ZS_IS_MOUSE(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE) #define ZS_IS_CONS(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CONS) @@ -278,8 +275,7 @@ up->cflag &= ~CBAUD; up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud); - brg = BPS_TO_BRG(new_baud, - (ZS_CLOCK / ZS_CLOCK_DIVISOR)); + brg = BPS_TO_BRG(new_baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(&up->port)); @@ -332,7 +328,7 @@ struct zilog_channel *channel, struct pt_regs *regs) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ while (1) { unsigned char ch, r1; @@ -340,7 +336,7 @@ if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { tty->flip.work.func((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; + return; /* XXX Ignores SysRq when we need it most. Fix. */ } r1 = read_zsreg(channel, R1); @@ -474,7 +470,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, struct zilog_channel *channel) { - struct circ_buf *xmit = &up->port.info->xmit; + struct circ_buf *xmit; if (ZS_IS_CONS(up)) { unsigned char status = sbus_readb(&channel->control); @@ -499,7 +495,12 @@ if (ZS_TX_STOPPED(up)) { up->flags &= ~SUNZILOG_FLAG_TX_STOPPED; - goto disable_tx_int; + + sbus_writeb(RES_Tx_P, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + + return; } if (up->port.x_char) { @@ -512,8 +513,11 @@ return; } + if (up->port.info == NULL) + goto ack_tx_int; + xmit = &up->port.info->xmit; if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) - goto disable_tx_int; + goto ack_tx_int; sbus_writeb(xmit->buf[xmit->tail], &channel->data); ZSDELAY(); @@ -525,12 +529,15 @@ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); - if (!uart_circ_empty(xmit)) - return; + if (uart_circ_empty(xmit)) + goto ack_tx_int; -disable_tx_int: - up->curregs[R5] &= ~TxENAB; - write_zsreg(ZILOG_CHANNEL_FROM_PORT(&up->port), R5, up->curregs[R5]); + return; + +ack_tx_int: + sbus_writeb(RES_Tx_P, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); } static void sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -543,7 +550,7 @@ unsigned char r3; spin_lock(&up->port.lock); - r3 = read_zsreg(channel, 3); + r3 = read_zsreg(channel, R3); /* Channel A */ if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { @@ -679,13 +686,6 @@ up->flags |= SUNZILOG_FLAG_TX_ACTIVE; up->flags &= ~SUNZILOG_FLAG_TX_STOPPED; - /* Enable the transmitter. */ - if (!(up->curregs[R5] & TxENAB)) { - /* NOTE: Not subject to 'transmitter active' rule. */ - up->curregs[R5] |= TxENAB; - write_zsreg(channel, R5, up->curregs[R5]); - } - status = sbus_readb(&channel->control); ZSDELAY(); @@ -785,39 +785,69 @@ spin_unlock_irqrestore(&port->lock, flags); } -static int sunzilog_startup(struct uart_port *port) +static void __sunzilog_startup(struct uart_sunzilog_port *up) { - struct uart_sunzilog_port *up = UART_ZILOG(port); struct zilog_channel *channel; - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); - - channel = ZILOG_CHANNEL_FROM_PORT(port); + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); up->prev_status = sbus_readb(&channel->control); /* Enable receiver and transmitter. */ up->curregs[R3] |= RxENAB; up->curregs[R5] |= TxENAB; - /* Enable RX and status interrupts. TX interrupts are enabled - * as needed. - */ - up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx; - up->curregs[R9] |= MIE; + up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; sunzilog_maybe_update_regs(up, channel); +} - spin_unlock_irqrestore(&port->lock, flags); +static int sunzilog_startup(struct uart_port *port) +{ + struct uart_sunzilog_port *up = UART_ZILOG(port); + unsigned long flags; + if (ZS_IS_CONS(up)) + return 0; + + spin_lock_irqsave(&port->lock, flags); + __sunzilog_startup(up); + spin_unlock_irqrestore(&port->lock, flags); return 0; } +/* + * The test for ZS_IS_CONS is explained by the following e-mail: + ***** + * From: Russell King + * Date: Sun, 8 Dec 2002 10:18:38 +0000 + * + * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote: + * > I boot my 2.5 boxes using "console=ttyS0,9600" argument, + * > and I noticed that something is not right with reference + * > counting in this case. It seems that when the console + * > is open by kernel initially, this is not accounted + * > as an open, and uart_startup is not called. + * + * That is correct. We are unable to call uart_startup when the serial + * console is initialised because it may need to allocate memory (as + * request_irq does) and the memory allocators may not have been + * initialised. + * + * 1. initialise the port into a state where it can send characters in the + * console write method. + * + * 2. don't do the actual hardware shutdown in your shutdown() method (but + * do the normal software shutdown - ie, free irqs etc) + ***** + */ static void sunzilog_shutdown(struct uart_port *port) { struct uart_sunzilog_port *up = UART_ZILOG(port); struct zilog_channel *channel; unsigned long flags; + if (ZS_IS_CONS(up)) + return; + spin_lock_irqsave(&port->lock, flags); channel = ZILOG_CHANNEL_FROM_PORT(port); @@ -829,7 +859,6 @@ /* Disable all interrupts and BRK assertion. */ up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); up->curregs[R5] &= ~SND_BRK; - up->curregs[R9] &= ~MIE; sunzilog_maybe_update_regs(up, channel); spin_unlock_irqrestore(&port->lock, flags); @@ -843,18 +872,15 @@ unsigned int iflag, int brg) { - /* Don't modify MIE. */ - up->curregs[R9] |= NV; - up->curregs[R10] = NRZ; - up->curregs[11] = TCBR | RCBR; + up->curregs[R11] = TCBR | RCBR; /* Program BAUD and clock source. */ - up->curregs[4] &= ~XCLK_MASK; - up->curregs[4] |= X16CLK; - up->curregs[12] = brg & 0xff; - up->curregs[13] = (brg >> 8) & 0xff; - up->curregs[14] = BRSRC | BRENAB; + up->curregs[R4] &= ~XCLK_MASK; + up->curregs[R4] |= X16CLK; + up->curregs[R12] = brg & 0xff; + up->curregs[R13] = (brg >> 8) & 0xff; + up->curregs[R14] = BRSRC | BRENAB; /* Character size, stop bits, and parity. */ up->curregs[3] &= ~RxN_MASK; @@ -1027,7 +1053,7 @@ alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout *)); if (sunzilog_port_table == NULL || sunzilog_chip_regs == NULL) { - prom_printf("sunzilog_init: Cannot alloc SunZilog tables.\n"); + prom_printf("SunZilog: Cannot allocate tables.\n"); prom_halt(); } } @@ -1333,7 +1359,7 @@ unsigned long flags; int baud, brg; - printk("Console: ttyS%d (Zilog8530)\n", + printk("Console: ttyS%d (SunZilog)\n", (sunzilog_reg.minor - 64) + con->index); /* Get firmware console settings. */ @@ -1356,21 +1382,15 @@ brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); - /* - * Temporary fix. - */ - spin_lock_init(&up->port.lock); - spin_lock_irqsave(&up->port.lock, flags); up->curregs[R15] = BRKIE; - sunzilog_convert_to_zs(up, con->cflag, 0, brg); - spin_unlock_irqrestore(&up->port.lock, flags); - sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); - sunzilog_startup(&up->port); + __sunzilog_startup(up); + + spin_unlock_irqrestore(&up->port.lock, flags); return 0; } @@ -1401,6 +1421,7 @@ return 0; sunzilog_console.index = i; + sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS; register_console(&sunzilog_console); return 0; } @@ -1457,6 +1478,12 @@ struct zilog_layout *rp; int channel, chip; + /* + * Temporary fix. + */ + for (channel = 0; channel < NUM_CHANNELS - 1; channel++) + spin_lock_init(&sunzilog_port_table[channel].port.lock); + sunzilog_irq_chain = up = &sunzilog_port_table[0]; for (channel = 0; channel < NUM_CHANNELS - 1; channel++) up[channel].next = &up[channel + 1]; @@ -1504,7 +1531,7 @@ up->cflag = B4800 | CS8 | CLOCAL | CREAD; baud = 4800; } - printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a Zilog8530\n", + printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a SunZilog\n", channel, up->port.membase, __irq_itoa(zilog_irq)); up->curregs[R15] = BRKIE; @@ -1534,10 +1561,8 @@ serio_register_port(&up->serio); #endif - spin_unlock(&up->port.lock); sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); - sunzilog_startup(&up->port); - spin_lock(&up->port.lock); + __sunzilog_startup(up); } static void __init sunzilog_init_hw(void) @@ -1560,8 +1585,6 @@ if (i == KEYBOARD_LINE || i == MOUSE_LINE) { sunzilog_init_kbdms(up, i); - } else if (ZS_IS_CONS(up)) { - /* sunzilog_console_setup takes care of this */ } else { /* Normal serial TTY. */ up->parity_mask = 0xff; @@ -1572,11 +1595,12 @@ up->curregs[R10] = NRZ; up->curregs[R11] = TCBR | RCBR; baud = 9600; - brg = BPS_TO_BRG(baud, (ZS_CLOCK / ZS_CLOCK_DIVISOR)); + brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; up->curregs[R14] = BRSRC | BRENAB; - sunzilog_maybe_update_regs(up, channel); + __load_zsregs(channel, up->curregs); + write_zsreg(channel, R9, up->curregs[R9]); } spin_unlock_irqrestore(&up->port.lock, flags); diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c --- a/drivers/telephony/ixj.c Mon Jan 13 10:18:05 2003 +++ b/drivers/telephony/ixj.c Mon Jan 13 10:18:05 2003 @@ -7574,8 +7574,8 @@ kfree(j->read_buffer); if (j->write_buffer) kfree(j->write_buffer); - if (j->dev && j->dev->deactivate) - j->dev->deactivate(j->dev); + if (j->dev) + pnp_device_detach(j->dev); if (ixjdebug & 0x0002) printk(KERN_INFO "IXJ: Unregistering /dev/phone%d from LTAPI\n", cnt); phone_unregister_device(&j->p); @@ -7700,7 +7700,7 @@ { int probe = 0; int func = 0x110; - struct pci_dev *dev = NULL, *old_dev = NULL; + struct pnp_dev *dev = NULL, *old_dev = NULL; while (1) { do { @@ -7708,30 +7708,29 @@ int result; old_dev = dev; - dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'), + dev = pnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'), ISAPNP_FUNCTION(func), old_dev); - if (!dev) + if (!dev || !dev->card) break; - result = dev->prepare(dev); + result = pnp_device_attach(dev); if (result < 0) { - printk("preparing failed %d \n", result); + printk("pnp attach failed %d \n", result); break; } + if (pnp_activate_dev(dev, NULL) < 0) { + printk("pnp activate failed (out of resources?)\n"); + pnp_device_detach(dev); + return -ENOMEM; + } - if (!(dev->resource[0].flags & IORESOURCE_IO)) + if (!pnp_port_valid(dev, 0)) { + pnp_device_detach(dev); return -ENODEV; - - dev->resource[0].flags |= IORESOURCE_AUTO; - if (func != 0x110) - dev->resource[1].flags |= IORESOURCE_AUTO; - if (dev->activate(dev) < 0) { - printk("isapnp configure failed (out of resources?)\n"); - return -ENOMEM; } - result = check_region(dev->resource[0].start, 16); + result = check_region(pnp_port_start(dev, 0), 16); if (result) { - printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", dev->resource[0].start); + printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", pnp_port_start(dev, 0)); break; } @@ -7739,7 +7738,7 @@ request_region(j->DSPbase, 16, "ixj DSP"); if (func != 0x110) - j->XILINXbase = dev->resource[1].start; /* get real port */ + j->XILINXbase = pnp_port_start(dev, 1); /* get real port */ switch (func) { case (0x110): @@ -7755,7 +7754,7 @@ j->board = *cnt; probe = ixj_selfprobe(j); if(!probe) { - j->serial = dev->bus->serial; + j->serial = dev->card->serial; j->dev = dev; switch (func) { case 0x110: diff -Nru a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h --- a/drivers/telephony/ixj.h Mon Jan 13 10:18:07 2003 +++ b/drivers/telephony/ixj.h Mon Jan 13 10:18:07 2003 @@ -1182,11 +1182,7 @@ atomic_t DSPWrite; struct phone_capability caplist[30]; unsigned int caps; -#if LINUX_VERSION_CODE < 0x020400 struct pnp_dev *dev; -#else - struct pci_dev *dev; -#endif unsigned int cardtype; unsigned int rec_codec; unsigned int cid_rec_codec; diff -Nru a/drivers/usb/core/driverfs.c b/drivers/usb/core/driverfs.c --- a/drivers/usb/core/driverfs.c Mon Jan 13 10:18:05 2003 +++ b/drivers/usb/core/driverfs.c Mon Jan 13 10:18:05 2003 @@ -25,13 +25,10 @@ /* Active configuration fields */ #define usb_actconfig_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf, size_t count, loff_t off) \ +show_##field (struct device *dev, char *buf) \ { \ struct usb_device *udev; \ \ - if (off) \ - return 0; \ - \ udev = to_usb_device (dev); \ return sprintf (buf, format_string, udev->actconfig->desc.field); \ } \ @@ -43,13 +40,11 @@ usb_actconfig_attr (bMaxPower, "%3dmA\n") /* String fields */ -static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off) +static ssize_t show_product (struct device *dev, char *buf) { struct usb_device *udev; int len; - if (off) - return 0; udev = to_usb_device (dev); len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE); @@ -62,13 +57,11 @@ static DEVICE_ATTR(product,S_IRUGO,show_product,NULL); static ssize_t -show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off) +show_manufacturer (struct device *dev, char *buf) { struct usb_device *udev; int len; - if (off) - return 0; udev = to_usb_device (dev); len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE); @@ -81,13 +74,11 @@ static DEVICE_ATTR(manufacturer,S_IRUGO,show_manufacturer,NULL); static ssize_t -show_serial (struct device *dev, char *buf, size_t count, loff_t off) +show_serial (struct device *dev, char *buf) { struct usb_device *udev; int len; - if (off) - return 0; udev = to_usb_device (dev); len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE); @@ -100,13 +91,11 @@ static DEVICE_ATTR(serial,S_IRUGO,show_serial,NULL); static ssize_t -show_speed (struct device *dev, char *buf, size_t count, loff_t off) +show_speed (struct device *dev, char *buf) { struct usb_device *udev; char *speed; - if (off) - return 0; udev = to_usb_device (dev); switch (udev->speed) { @@ -130,13 +119,10 @@ /* Descriptor fields */ #define usb_descriptor_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf, size_t count, loff_t off) \ +show_##field (struct device *dev, char *buf) \ { \ struct usb_device *udev; \ \ - if (off) \ - return 0; \ - \ udev = to_usb_device (dev); \ return sprintf (buf, format_string, udev->descriptor.field); \ } \ @@ -185,13 +171,10 @@ /* Interface fields */ #define usb_intf_attr(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf, size_t count, loff_t off) \ +show_##field (struct device *dev, char *buf) \ { \ struct usb_interface *intf; \ int alt; \ - \ - if (off) \ - return 0; \ \ intf = to_usb_interface (dev); \ alt = intf->act_altsetting; \ diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c --- a/drivers/usb/host/ohci-sa1111.c Mon Jan 13 10:18:06 2003 +++ b/drivers/usb/host/ohci-sa1111.c Mon Jan 13 10:18:06 2003 @@ -185,7 +185,6 @@ goto err1; } - set_irq_type(hcd->irq, IRQT_RISING); retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT, hcd->description, hcd); if (retval != 0) { @@ -399,7 +398,7 @@ static struct sa1111_driver ohci_hcd_sa1111_driver = { .drv = { - .name = "SA1111 OHCI", + .name = "sa1111-ohci", .bus = &sa1111_bus_type, .probe = ohci_hcd_sa1111_drv_probe, .remove = ohci_hcd_sa1111_drv_remove, diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c --- a/drivers/video/sa1100fb.c Mon Jan 13 10:18:05 2003 +++ b/drivers/video/sa1100fb.c Mon Jan 13 10:18:05 2003 @@ -170,10 +170,11 @@ #include #include #include -#include #include #include #include +#include +#include #include #include @@ -183,12 +184,6 @@ #include #include -#include