Commit f3ae5c72 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/for-alan
parents eb4b3b48 291b901b
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
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.
Support functions for the SA11x0 internal DMA channels
======================================================
Nicolas Pitre <nico@cam.org>
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.
......@@ -366,9 +366,12 @@ __armv4_cache_on:
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 @@ __arm6_cache_on:
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 @@ __common_cache_on:
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 @@ cache_clean_flush:
__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
......
......@@ -978,6 +978,8 @@ ecard_probe(int slot, card_type_t type)
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);
......
......@@ -81,7 +81,7 @@ unsigned long phys_initrd_start __initdata = 0;
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 @@ static void __init setup_processor(void)
while (1);
}
proc_info = *list->info;
cpu_name = list->cpu_name;
#ifdef MULTI_CPU
processor = *list->proc;
......@@ -287,9 +287,9 @@ static void __init setup_processor(void)
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 @@ static int c_show(struct seq_file *m, void *v)
{
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),
......
......@@ -97,11 +97,19 @@ static int integrator_verify_speed(struct cpufreq_policy *policy)
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.
......@@ -109,6 +117,23 @@ static void do_set_policy(int cpu, struct cpufreq_policy *policy)
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 @@ static void do_set_policy(int cpu, struct cpufreq_policy *policy)
__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 @@ static struct cpufreq_policy integrator_policy = {
.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 @@ static int __init integrator_cpu_init(void)
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");
......
......@@ -183,7 +183,7 @@ static int sa1100_setspeed(struct cpufreq_policy *policy)
freqs.old = cur;
freqs.new = policy->max;
freqs.cpu = CPUFREQ_ALL_CPUS;
freqs.cpu = 0;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
......
......@@ -242,7 +242,7 @@ static int sa1110_setspeed(struct cpufreq_policy *policy)
freqs.old = sa11x0_getspeed();
freqs.new = policy->max;
freqs.cpu = CPUFREQ_ALL_CPUS;
freqs.cpu = 0;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
......
This diff is collapsed.
/*
* linux/arch/arm/mm/extable.c
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
extern const struct exception_table_entry __start___ex_table[];
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 *
search_extable(const struct exception_table_entry *first,
const struct exception_table_entry *last,
unsigned long value)
{
......@@ -22,44 +16,11 @@ search_one_table(const struct exception_table_entry *first,
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;
}
......@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
......@@ -102,23 +103,25 @@ static void
__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 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
show_pte(mm, addr);
die("Oops", regs, fsr);
bust_spinlocks(0);
do_exit(SIGKILL);
}
......
......@@ -420,8 +420,6 @@ ENTRY(cpu_arm1020_set_pte)
mov pc, lr
cpu_manu_name:
.asciz "ARM/VLSI"
ENTRY(cpu_arm1020_name)
.ascii "Arm1020"
#ifndef CONFIG_CPU_ICACHE_DISABLE
......@@ -518,15 +516,9 @@ arm1020_processor_functions:
.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 @@ __arm1020_proc_info:
.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
......
......@@ -276,10 +276,12 @@ _arm3_xchg_4: swp r0, r0, [r1]
_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 @@ arm2_processor_functions:
.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 @@ arm250_processor_functions:
.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 @@ arm3_processor_functions:
.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 @@ arm3_elf_name: .asciz "v2"
.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 @@ arm3_elf_name: .asciz "v2"
.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 @@ arm3_elf_name: .asciz "v2"
.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
......
......@@ -287,14 +287,12 @@ ENTRY(cpu_arm7_reset)
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 @@ ENTRY(arm7_processor_functions)
.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 @@ __arm6_proc_info:
.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 @@ __arm610_proc_info:
.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 @@ __arm7_proc_info:
.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 @@ __arm710_proc_info:
.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
......
......@@ -168,8 +168,6 @@ ENTRY(cpu_arm720_reset)
mov pc, r0
cpu_armvlsi_name:
.asciz "ARM"
cpu_arm720_name:
.asciz "ARM720T"
.align
......@@ -223,14 +221,8 @@ ENTRY(arm720_processor_functions)
.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 @@ __arm720_proc_info:
.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
......
......@@ -419,8 +419,6 @@ ENTRY(cpu_arm920_set_pte)
mov pc, lr
cpu_manu_name:
.asciz "ARM/CIRRUS"
ENTRY(cpu_arm920_name)
.ascii "Arm920T"
#ifndef CONFIG_CPU_ICACHE_DISABLE
......@@ -506,15 +504,9 @@ arm920_processor_functions:
.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 @@ __arm920_proc_info:
.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
......
......@@ -418,8 +418,6 @@ ENTRY(cpu_arm922_set_pte)
mov pc, lr
cpu_manu_name:
.asciz "ARM/ALTERA"
ENTRY(cpu_arm922_name)
.ascii "Arm922T"
#ifndef CONFIG_CPU_ICACHE_DISABLE
......@@ -505,15 +503,9 @@ arm922_processor_functions:
.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 @@ __arm922_proc_info:
.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
......
......@@ -403,8 +403,6 @@ ENTRY(cpu_arm926_set_pte)
mov pc, lr
cpu_manu_name:
.asciz "ARM"
ENTRY(cpu_arm926_name)
.ascii "ARM926EJ-S"
#ifndef CONFIG_CPU_ICACHE_DISABLE
......@@ -503,12 +501,6 @@ arm926_processor_functions:
.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 @@ __arm926_proc_info:
.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
......
......@@ -473,8 +473,6 @@ ENTRY(cpu_sa1100_set_pte)
mov pc, lr
cpu_manu_name:
.asciz "Intel"
cpu_sa110_name:
.asciz "StrongARM-110"
cpu_sa1100_name:
......@@ -547,13 +545,6 @@ ENTRY(sa110_processor_functions)
.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 @@ ENTRY(sa1100_processor_functions)
.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 @@ __sa110_proc_info:
.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 @@ __sa1100_proc_info:
.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 @@ __sa1110_proc_info:
.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
......
......@@ -651,9 +651,6 @@ ENTRY(cpu_xscale_set_pte)
.ltorg
cpu_manu_name:
.asciz "Intel"
cpu_80200_name:
.asciz "XScale-80200"
......@@ -723,24 +720,6 @@ ENTRY(xscale_processor_functions)
.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 @@ __80200_proc_info:
.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 @@ __pxa250_proc_info:
.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 @@ __pxa210_proc_info:
.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
......
......@@ -75,6 +75,12 @@ SECTIONS
__stop___ex_table = .;
}
__gpl_ksymtab : { /* GPL Kernel symbol table */
__start___gpl_ksymtab = .;
*(__gpl_ksymtab)
__stop___gpl_ksymtab = .;
}
__ksymtab : { /* Kernel symbol table */
__start___ksymtab = .;
*(__ksymtab)
......
......@@ -117,9 +117,9 @@ config M386
(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-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.
- "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
- "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
......@@ -159,18 +159,28 @@ config M586MMX
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"
......@@ -258,7 +268,7 @@ config X86_XADD
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 +320,22 @@ config X86_ALIGNMENT_16
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
......
......@@ -34,6 +34,7 @@ cflags-$(CONFIG_M586) += -march=i586
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)
......
......@@ -350,6 +350,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
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 @@ static void setup_frame(int sig, struct k_sigaction *ka,
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_frame(int sig, struct k_sigaction *ka,
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 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
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
......
......@@ -71,12 +71,16 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
*/
static pte_t * __init one_page_table_init(pmd_t *pmd)
{
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 pte_offset_kernel(pmd, 0);
}
/*
......
......@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <asm/dma.h>
#include <asm/ecard.h>
......@@ -163,26 +164,27 @@ cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
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);
......
......@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
......@@ -165,22 +166,23 @@ eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
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);
......
......@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <asm/dma.h>
#include <asm/ecard.h>
......@@ -135,22 +136,23 @@ powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
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);
......
......@@ -168,6 +168,19 @@ config 977_WATCHDOG
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
......
......@@ -21,6 +21,7 @@ obj-$(CONFIG_977_WATCHDOG) += wdt977.o
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
......
/*
* Watchdog driver for the SA11x0
*
* (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
* Based on SoftDog driver by Alan Cox <alan@redhat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Neither 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 <green@crimea.edu>
*
* 27/11/2000 Initial release
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#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 <green@crimea.edu>");
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");
......@@ -453,6 +453,13 @@ config BLK_DEV_CMD64X
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
......
......@@ -21,10 +21,7 @@
#include <linux/isapnp.h>
#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 @@ static int generic_ide_offsets[IDE_NR_PORTS] __initdata = {
/* 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 @@ static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
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 @@ struct pnp_dev_t idepnp_devices[] __initdata = {
#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 @@ static int pnp_ide_dev_idx = 0;
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 @@ void __init pnpide_init(int enable)
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
/*
......
......@@ -26,6 +26,7 @@ obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o
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
......
/*
* 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 <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
*
* 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, &reg4a);
* pci_read_config_word(HWIF(drive)->pci_dev, 0x54, &reg54);
*
* 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 <linux/config.h>
......@@ -77,6 +114,7 @@ static u8 piix_proc = 0;
#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
......@@ -442,6 +480,33 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return (ide_config_drive_speed(drive, speed));
}
/**
* 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
......@@ -455,7 +520,14 @@ 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 @@ static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_
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 struct pci_driver driver = {
static int piix_ide_init(void)
{
piix_check_450nx();
return ide_pci_register_driver(&driver);
}
......
/*
* 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 <torben.mathiasen@hp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/init.h>
#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");
/*
* triflex.h
*
* Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
* Author: Torben Mathiasen <torben.mathiasen@hp.com>
*
*/
#ifndef TRIFLEX_H
#define TRIFLEX_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
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 */
......@@ -16,7 +16,6 @@
#include <linux/init.h>
#include <linux/gameport.h>
#include <linux/slab.h>
#include <linux/isapnp.h>
#include <linux/stddef.h>
#include <linux/delay.h>
......
......@@ -194,7 +194,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
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;
}
......
......@@ -89,6 +89,7 @@ config SERIO_PARKBD
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.
......
......@@ -262,7 +262,7 @@ static struct isapnp_device_id asus_ids[] __initdata = {
};
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
......@@ -279,29 +279,38 @@ setup_asuscom(struct IsdnCard *card)
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");
......
......@@ -604,8 +604,8 @@ static struct card_ops avm_pci_ops = {
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
......@@ -627,32 +627,36 @@ setup_avm_pcipnp(struct IsdnCard *card)
} 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;
}
......
......@@ -606,7 +606,7 @@ static struct isapnp_device_id diva_ids[] __initdata = {
};
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
......@@ -648,31 +648,38 @@ setup_diva(struct IsdnCard *card)
} 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)) {
......
......@@ -825,7 +825,7 @@ static struct isapnp_device_id elsa_ids[] __initdata = {
};
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
......@@ -905,31 +905,39 @@ setup_elsa(struct IsdnCard *card)
} 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
......
......@@ -1179,7 +1179,7 @@ static struct isapnp_device_id hfc_ids[] __initdata = {
};
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 +1192,38 @@ setup_hfcsx(struct IsdnCard *card)
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");
......
......@@ -167,7 +167,7 @@ static struct isapnp_device_id hfc_ids[] __initdata = {
};
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
......@@ -181,29 +181,38 @@ setup_hfcs(struct IsdnCard *card)
#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");
......
......@@ -27,7 +27,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/pnp.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
......@@ -55,13 +55,11 @@ static struct pci_device_id fcpci_ids[] __devinitdata = {
};
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 const 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);
static int protocol = 2; /* EURO-ISDN Default */
MODULE_PARM(protocol, "i");
......@@ -908,50 +906,47 @@ static struct pci_driver fcpci_driver = {
#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;
int retval;
struct pnp_dev *pnp_dev;
pnp_dev = pnp_request_card_device(card, card_id->devs[0], NULL);
if (pnp_dev == NULL)
return;
retval = -ENOMEM;
adapter = new_adapter(pdev);
if (!adapter)
goto err;
return -ENOMEM;
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;
if (!pnp_port_valid(pnp_dev, 0) || !pnp_irq_valid(pnp_dev, 0)) {
delete_adapter(adapter);
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;
return 0;
err_free:
if (retval) {
delete_adapter(adapter);
err:
return retval;
}
return 0;
}
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 = pci_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 +967,7 @@ static int __init hisax_fcpcipnp_init(void)
pci_nr_found = retval;
#ifdef __ISAPNP__
retval = isapnp_register_driver(&fcpnp_driver);
retval = pnpc_register_driver(&fcpnp_driver);
#else
retval = 0;
#endif
......@@ -990,7 +985,7 @@ static int __init hisax_fcpcipnp_init(void)
#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:
......
......@@ -19,7 +19,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
......
......@@ -198,7 +198,7 @@ static struct card_ops isurf_ops = {
};
#ifdef __ISAPNP__
static struct pci_bus *pnp_surf __devinitdata = NULL;
static struct pnp_card *pnp_surf __devinitdata = NULL;
#endif
int __init
......@@ -219,34 +219,40 @@ setup_isurf(struct IsdnCard *card)
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);
cs->hw.isurf.phymem = pnp_port_start(pd, 1);
cs->irq = pnp_irq(pd, 0);
} else {
printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
return(0);
......
......@@ -187,7 +187,7 @@ static struct isapnp_device_id itk_ids[] __initdata = {
};
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
......@@ -204,29 +204,38 @@ setup_ix1micro(struct IsdnCard *card)
#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");
......
......@@ -211,7 +211,7 @@ static struct card_ops niccy_ops = {
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
......@@ -226,32 +226,38 @@ setup_niccy(struct IsdnCard *card)
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");
}
......
......@@ -484,7 +484,7 @@ static struct isapnp_device_id sedl_ids[] __initdata = {
};
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
......@@ -523,31 +523,38 @@ setup_sedlbauer(struct IsdnCard *card)
} 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);
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.sedl.cfg_reg = card->para[1];
cs->irq = card->para[0];
if (pdev->function == ISAPNP_FUNCTION(0x2)) {
......
......@@ -225,7 +225,7 @@ static struct isapnp_device_id teles_ids[] __initdata = {
};
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
......@@ -243,31 +243,41 @@ setup_teles3(struct IsdnCard *card)
#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,
if ((pnp_card = pnp_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))) {
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");
......
......@@ -47,7 +47,7 @@ static unsigned char rdsbuf[RDS_BUFFER];
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 struct video_device cadet_radio=
static int isapnp_cadet_probe(void)
{
dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'),
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 @@ static void __exit cadet_cleanup_module(void)
release_region(io,2);
if (dev)
dev->deactivate(dev);
pnp_device_detach(dev);
}
module_init(cadet_init);
......
......@@ -36,7 +36,7 @@ struct fmi_device
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 @@ static int isapnp_fmi_probe(void)
int i = 0;
while (id_table[i].card_vendor != 0 && dev == NULL) {
dev = isapnp_find_dev(NULL, id_table[i].vendor,
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 @@ static void __exit fmi_cleanup_module(void)
video_unregister_device(&fmi_radio);
release_region(io, 2);
if (dev)
dev->deactivate(dev);
pnp_device_detach(dev);
}
module_init(fmi_init);
......
This diff is collapsed.
......@@ -167,6 +167,9 @@ struct el3_private {
#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 __init el3_probe(struct net_device *dev, int card_idx)
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 @@ int __init el3_probe(struct net_device *dev, int card_idx)
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,
while ((idev = pnp_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))
if (pnp_device_attach(idev) < 0)
continue;
if (pnp_activate_dev(idev, NULL) < 0) {
__again:
pnp_device_detach(idev);
continue;
ioaddr = idev->resource[0].start;
if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP"))
}
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 @@ int __init el3_probe(struct net_device *dev, int card_idx)
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 @@ cleanup_module(void)
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;
}
......
......@@ -460,33 +460,34 @@ static int corkscrew_scan(struct net_device *dev)
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,
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,9 +499,11 @@ static int corkscrew_scan(struct net_device *dev)
== 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));
/* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */
......
......@@ -573,7 +573,7 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
len = skblen;
if (len < ETH_ZLEN) {
len = ETH_ZLEN:
len = ETH_ZLEN;
skb = skb_padto(skb, ETH_ZLEN);
if (skb == NULL)
return 0;
......
......@@ -273,16 +273,17 @@ static void awc_pci_release(void) {
#include <linux/isapnp.h>
#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 @@ int awc4500_pnp_hw_reset(struct net_device *dev){
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;
}
......@@ -347,26 +341,27 @@ int awc4500_pnp_probe(struct net_device *dev)
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;
}
}
......
This diff is collapsed.
......@@ -196,29 +196,31 @@ static int __init ne_probe_isapnp(struct net_device *dev)
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,
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);
}
/* 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;
......
......@@ -145,7 +145,7 @@ sb1000_probe(struct net_device *dev)
{
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 @@ sb1000_probe(struct net_device *dev)
* 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 @@ sb1000_probe(struct net_device *dev)
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. */
......
......@@ -284,29 +284,33 @@ static int __init ultra_probe_isapnp(struct net_device *dev)
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,
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))
if (pnp_device_attach(idev) < 0)
continue;
if (idev->activate(idev))
continue;
/* if no irq, search for next */
if (idev->irq_resource[0].start == 0)
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;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -19,12 +19,12 @@
*
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/isapnp.h>
#include <linux/pnp.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -160,6 +160,7 @@ struct expansion_card {
const char *card_desc; /* Card description */
CONST unsigned int podaddr; /* Base Linux address for card */
CONST loader_t loader; /* loader program */
u64 dma_mask;
};
struct in_chunk_dir {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment