Commit e701b0b3 authored by James Simmons's avatar James Simmons

Merge bk://linux.bkbits.net/linux-2.5

into maxwell.earthlink.net:/usr/src/linus-2.5
parents bb0cc78e 71660e15
Board Overview
-----------------------------
This is an beta release of the Xscale Linux port to the ADI 80200EVB
evaluation board.
The 80200EVB is an evaluation platform for ADI Engineering's high-performance
80200FCC chipset for the Intel 80200 XScale CPU. The 80200FCC is an open
source FPGA based system that contains a PCI unit and a high performance
memory controller.
In addition to the 80200FCC, the board also contains a 16C550 UART, and 4MB
of flash.
The board is still under development and currently only the UART is functional
as the PCI bits have not been programmed into the FPGA.
For more information on the board, see http://www.adiengineering.com
Port Status
-----------------------------
Supported:
- Onboard UART (Polled operation only)
- Cache/TLB locking on 80200 CPU
TODO:
- PCI when hardware supports it
Building the Kernel
-----------------------------
change Linux makefile
make adi_evb_config
make oldconfig
make dep
make zImage
Loading Linux
-----------------------------
Before you can use Linux on the ADI board, you need to grab the following:
ADI 80200EVB Monitor:
ftp://source.mvista.com/pub/xscale/ADI_EVB/monitor.srec
ADI JFFS2 Image:
ftp://source.mvista.com/pub/xscale/ADI_EVB/adi.jffs2
Once you've got the Cygnus prompt, type in the following command:
load
On another terminal window:
cat monitor.srec > /dev/ttyS0
(replace ttyS0 with the serial port you are using)
Once completed, just type 'go' at the cygmon prompt and you should see:
MontaVista IQ80310 Monitor Version 0.1
monitor>
Type 'b 115200' at the prompt and change your terminal speed to 115200
The first thing to do is to upload and burn the jffs2 filesystem image
onto the boards 4MB of flash:
monitor> u c1000000
Uploading file at 0xc1000000
Now send file with ymodem
Do as the monitor says and transfer the file adi.jffs2. Once complete,
the following will copy the jffs2 image to location 0x80000 in the flash.
monitor> f 8000 c1000000 200000
Erasing sector 0x00080000
Writing sector 0x00080000 with data at 0xC1000000
Erasing sector 0x000A0000
Writing sector 0x000A0000 with data at 0xC1020000
Erasing sector 0x000C0000
...
Now use the same command as above to upload your zImage to location c1000000.
When you've done that, type 'j c1000000' to run Linux. Login as
root and you're all set to go.
Misc Notes
-----------------------------
The current version of the HW does not have an onboard timer, so the 80200
PMU is not available for general use as it is being used for a timer source.
By default, the MTD driver reserves the first 512K for bootloaders and
the remaining 3.5MB for the filesystem. You can edit drivers/mtd/map/adi_evb.c
to change this as needed for your application.
Contributors
-----------------------------
Thanks to ADI Engineering for providing the hardware for development
Deepak Saxena <dsaxena@mvista.com> - Initial port
-----------------------------
Enjoy. If you have any problem please contact Deepak Saxena
dsaxena@mvista.com
This diff is collapsed.
......@@ -1592,6 +1592,11 @@ P: Julien Blache
M: jb@technologeek.org
S: Maintained
TI PARALLEL LINK CABLE DRIVER
P: Romain Lievin
M: roms@lpg.ticalc.org
S: Maintained
TIEMAN VOYAGER USB BRAILLE DISPLAY DRIVER
P: Stephane Dalton
M: sdalton@videotron.ca
......
......@@ -8,6 +8,7 @@
# Copyright (C) 1995-2001 by Russell King
LDFLAGS_vmlinux :=-p -X
AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
OBJCOPYFLAGS :=-O binary -R .note -R .comment -S
GZFLAGS :=-9
#CFLAGS +=-pipe
......@@ -50,18 +51,29 @@ tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm #-mtune=xscale
CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
# Force -mno-fpu to be passed to the assembler. Some versions of gcc don't
# do this with -msoft-float
CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu
CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu
AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float -Wa,-mno-fpu
ifeq ($(CONFIG_CPU_26),y)
PROCESSOR := armo
HEAD := arch/arm/mach-arc/head.o arch/arm/kernel/init_task.o
ifeq ($(CONFIG_ROM_KERNEL),y)
DATAADDR = 0x02080000
TEXTADDR = 0x03800000
LDSCRIPT = arch/arm/vmlinux-armo-rom.lds.in
else
TEXTADDR = 0x02080000
LDSCRIPT = arch/arm/vmlinux-armo.lds.in
endif
endif
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
HEAD := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
TEXTADDR = 0xC0008000
endif
ifeq ($(CONFIG_ARCH_ARCA5K),y)
......@@ -175,7 +187,7 @@ core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/
drivers-$(CONFIG_ARCH_L7200)) += drivers/acorn/char/
drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/
libs-y += arch/arm/lib/
......
......@@ -18,7 +18,7 @@ ZLDFLAGS = -p -X -T vmlinux.lds
#
ifeq ($(CONFIG_ARCH_ACORN),y)
OBJS += ll_char_wr.o font.o
ZLDFLAGS += -defsym params=$(PARAMS_PHYS)
CFLAGS += -DPARAMS_PHYS=$(PARAMS_PHYS)
endif
ifeq ($(CONFIG_ARCH_NETWINDER),y)
......
......@@ -55,6 +55,18 @@
.macro writeb, rb
strb \rb, [r3, #0]
.endm
#elif defined(CONFIG_ARCH_SA1100)
.macro loadsp, rb
mov \rb, #0x80000000 @ physical base address
# if defined(CONFIG_DEBUG_LL_SER3)
add \rb, \rb, #0x00050000 @ Ser3
# else
add \rb, \rb, #0x00010000 @ Ser1
# endif
.endm
.macro writeb, rb
str \rb, [r3, #0x14] @ UTDR
.endm
#else
#error no serial architecture defined
#endif
......@@ -151,22 +163,55 @@ not_angel:
ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp}
subs r0, r0, r1 @ calculate the delta offset
teq r0, #0 @ if delta is zero, we're
@ if delta is zero, we're
beq not_relocated @ running at the address we
@ were linked at.
add r2, r2, r0 @ different address, so we
add r3, r3, r0 @ need to fix up various
add r5, r5, r0 @ pointers.
/*
* We're running at a different address. We need to fix
* up various pointers:
* r5 - zImage base address
* r6 - GOT start
* ip - GOT end
*/
add r5, r5, r0
add r6, r6, r0
add ip, ip, r0
#ifndef CONFIG_ZBOOT_ROM
/*
* If we're running fully PIC === CONFIG_ZBOOT_ROM = n,
* we need to fix up pointers into the BSS region.
* r2 - BSS start
* r3 - BSS end
* sp - stack pointer
*/
add r2, r2, r0
add r3, r3, r0
add sp, sp, r0
/*
* Relocate all entries in the GOT table.
*/
1: ldr r1, [r6, #0] @ relocate entries in the GOT
add r1, r1, r0 @ table. This fixes up the
str r1, [r6], #4 @ C references.
cmp r6, ip
blo 1b
#else
/*
* Relocate entries in the GOT table. We only relocate
* the entries that are outside the (relocated) BSS region.
*/
1: ldr r1, [r6, #0] @ relocate entries in the GOT
cmp r1, r2 @ entry < bss_start ||
cmphs r3, r1 @ _end < entry
addlo r1, r1, r0 @ table. This fixes up the
str r1, [r6], #4 @ C references.
cmp r6, ip
blo 1b
#endif
not_relocated: mov r0, #0
1: str r0, [r2], #4 @ clear bss
......@@ -176,6 +221,11 @@ not_relocated: mov r0, #0
cmp r2, r3
blo 1b
/*
* The C runtime environment should now be setup
* sufficiently. Turn the cache on, set up some
* pointers, and start decompressing.
*/
bl cache_on
mov r1, sp @ malloc space above stack
......
......@@ -19,144 +19,116 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
.text
.text
#define BOLD 0x01
#define ITALIC 0x02
#define UNDERLINE 0x04
#define FLASH 0x08
#define INVERSE 0x10
LC0: .word bytes_per_char_h
.word video_size_row
.word acorndata_8x8
.word con_charconvtable
LC0: .word LC0
.word bytes_per_char_h
.word video_size_row
.word acorndata_8x8
.word con_charconvtable
/*
* r0 = ptr
* r1 = char
* r2 = white
*/
ENTRY(ll_write_char)
stmfd sp!, {r4 - r7, lr}
stmfd sp!, {r4 - r7, lr}
@
@ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc)
@
eor ip, r1, #UNDERLINE << 9
/*
* calculate colours
*/
tst r1, #INVERSE << 9
moveq r2, r1, lsr #16
moveq r3, r1, lsr #24
movne r2, r1, lsr #24
movne r3, r1, lsr #16
and r3, r3, #255
and r2, r2, #255
/*
* calculate offset into character table
*/
mov r1, r1, lsl #23
mov r1, r1, lsr #20
/*
* calculate offset required for each row [maybe I should make this an argument to this fn.
* Have to see what the register usage is like in the calling routines.
*/
adr r4, LC0
ldmia r4, {r4, r5, r6, lr}
ldr r4, [r4]
ldr r5, [r5]
/*
* Go to resolution-dependent routine...
*/
cmp r4, #4
blt Lrow1bpp
eor r2, r3, r2 @ Create eor mask to change colour from bg
orr r3, r3, r3, lsl #8 @ to fg.
orr r3, r3, r3, lsl #16
add r0, r0, r5, lsl #3 @ Move to bottom of character
add r1, r1, #7
ldrb r7, [r6, r1]
tst ip, #UNDERLINE << 9
eoreq r7, r7, #255
teq r4, #8
beq Lrow8bpplp
/*
* calculate offset into character table
*/
mov r1, r1, lsl #3
/*
* calculate offset required for each row.
*/
adr ip, LC0
ldmia ip, {r3, r4, r5, r6, lr}
sub ip, ip, r3
add r6, r6, ip
add lr, lr, ip
ldr r4, [r4, ip]
ldr r5, [r5, ip]
/*
* Go to resolution-dependent routine...
*/
cmp r4, #4
blt Lrow1bpp
add r0, r0, r5, lsl #3 @ Move to bottom of character
orr r1, r1, #7
ldrb r7, [r6, r1]
teq r4, #8
beq Lrow8bpplp
@
@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
@
orr r3, r3, r3, lsl #4
Lrow4bpplp: ldr r7, [lr, r7, lsl #2]
mul r7, r2, r7
tst r1, #7 @ avoid using r7 directly after
eor ip, r3, r7
str ip, [r0, -r5]!
LOADREGS(eqfd, sp!, {r4 - r7, pc})
sub r1, r1, #1
ldrb r7, [r6, r1]
ldr r7, [lr, r7, lsl #2]
mul r7, r2, r7
tst r1, #7 @ avoid using r7 directly after
eor ip, r3, r7
str ip, [r0, -r5]!
subne r1, r1, #1
ldrneb r7, [r6, r1]
bne Lrow4bpplp
LOADREGS(fd, sp!, {r4 - r7, pc})
Lrow4bpplp:
ldr r7, [lr, r7, lsl #2]
mul r7, r2, r7
sub r1, r1, #1 @ avoid using r7 directly after
str r7, [r0, -r5]!
ldrb r7, [r6, r1]
ldr r7, [lr, r7, lsl #2]
mul r7, r2, r7
tst r1, #7 @ avoid using r7 directly after
str r7, [r0, -r5]!
subne r1, r1, #1
ldrneb r7, [r6, r1]
bne Lrow4bpplp
LOADREGS(fd, sp!, {r4 - r7, pc})
@
@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
@
Lrow8bpplp: mov ip, r7, lsr #4
ldr ip, [lr, ip, lsl #2]
mul r4, r2, ip
and ip, r7, #15 @ avoid r4
ldr ip, [lr, ip, lsl #2] @ avoid r4
mul ip, r2, ip @ avoid r4
eor r4, r3, r4 @ avoid ip
tst r1, #7 @ avoid ip
sub r0, r0, r5 @ avoid ip
eor ip, r3, ip
stmia r0, {r4, ip}
LOADREGS(eqfd, sp!, {r4 - r7, pc})
sub r1, r1, #1
ldrb r7, [r6, r1]
mov ip, r7, lsr #4
ldr ip, [lr, ip, lsl #2]
mul r4, r2, ip
and ip, r7, #15 @ avoid r4
ldr ip, [lr, ip, lsl #2] @ avoid r4
mul ip, r2, ip @ avoid r4
eor r4, r3, r4 @ avoid ip
tst r1, #7 @ avoid ip
sub r0, r0, r5 @ avoid ip
eor ip, r3, ip
stmia r0, {r4, ip}
subne r1, r1, #1
ldrneb r7, [r6, r1]
bne Lrow8bpplp
LOADREGS(fd, sp!, {r4 - r7, pc})
Lrow8bpplp:
mov ip, r7, lsr #4
ldr ip, [lr, ip, lsl #2]
mul r4, r2, ip
and ip, r7, #15 @ avoid r4
ldr ip, [lr, ip, lsl #2] @ avoid r4
mul ip, r2, ip @ avoid r4
sub r1, r1, #1 @ avoid ip
sub r0, r0, r5 @ avoid ip
stmia r0, {r4, ip}
ldrb r7, [r6, r1]
mov ip, r7, lsr #4
ldr ip, [lr, ip, lsl #2]
mul r4, r2, ip
and ip, r7, #15 @ avoid r4
ldr ip, [lr, ip, lsl #2] @ avoid r4
mul ip, r2, ip @ avoid r4
tst r1, #7 @ avoid ip
sub r0, r0, r5 @ avoid ip
stmia r0, {r4, ip}
subne r1, r1, #1
ldrneb r7, [r6, r1]
bne Lrow8bpplp
LOADREGS(fd, sp!, {r4 - r7, pc})
@
@ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc)
@
Lrow1bpp: add r6, r6, r1
ldmia r6, {r4, r7}
tst ip, #INVERSE << 9
mvnne r4, r4
mvnne r7, r7
strb r4, [r0], r5
mov r4, r4, lsr #8
strb r4, [r0], r5
mov r4, r4, lsr #8
strb r4, [r0], r5
mov r4, r4, lsr #8
strb r4, [r0], r5
strb r7, [r0], r5
mov r7, r7, lsr #8
strb r7, [r0], r5
mov r7, r7, lsr #8
strb r7, [r0], r5
mov r7, r7, lsr #8
tst ip, #UNDERLINE << 9
mvneq r7, r7
strb r7, [r0], r5
LOADREGS(fd, sp!, {r4 - r7, pc})
Lrow1bpp:
add r6, r6, r1
ldmia r6, {r4, r7}
strb r4, [r0], r5
mov r4, r4, lsr #8
strb r4, [r0], r5
mov r4, r4, lsr #8
strb r4, [r0], r5
mov r4, r4, lsr #8
strb r4, [r0], r5
strb r7, [r0], r5
mov r7, r7, lsr #8
strb r7, [r0], r5
mov r7, r7, lsr #8
strb r7, [r0], r5
mov r7, r7, lsr #8
strb r7, [r0], r5
LOADREGS(fd, sp!, {r4 - r7, pc})
.bss
.bss
ENTRY(con_charconvtable)
.space 1024
.space 1024
......@@ -94,6 +94,8 @@ if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \
"$CONFIG_SA1100_XP860" = "y" ]; then
define_bool CONFIG_SA1111 y
define_int CONFIG_FORCE_MAX_ZONEORDER 9
else
define_bool CONFIG_SA1111 n
fi
comment 'Processor Type'
......@@ -231,6 +233,8 @@ if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \
"$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \
"$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_XSCALE" = "y" ]; then
dep_bool 'Support Thumb instructions (EXPERIMENTAL)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
else
define_bool CONFIG_ARM_THUMB n
fi
if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \
"$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" ]; then
......
......@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <asm/elf.h>
#include <asm/page.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
......
......@@ -599,7 +599,7 @@ void pcibios_align_resource(void *data, struct resource *res,
* pcibios_enable_device - Enable I/O and memory.
* @dev: PCI device to be enabled
*/
int pcibios_enable_device(struct pci_dev *dev)
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
int idx;
......@@ -608,6 +608,10 @@ int pcibios_enable_device(struct pci_dev *dev)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for (idx = 0; idx < 6; idx++) {
/* Only set up the requested stuff */
if (!(mask & (1 << idx)))
continue;
r = dev->resource + idx;
if (!r->start && r->end) {
printk(KERN_ERR "PCI: Device %s not available because"
......@@ -626,3 +630,29 @@ int pcibios_enable_device(struct pci_dev *dev)
}
return 0;
}
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
struct pci_sys_data *root = dev->sysdata;
unsigned long prot, phys;
if (mmap_state == pci_mmap_io) {
return -EINVAL;
} else {
phys = root->mem_offset + (vma->vm_pgoff << PAGE_SHIFT);
}
/*
* Mark this as IO
*/
vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (remap_page_range(vma, vma->vm_start, phys,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
return 0;
}
......@@ -38,6 +38,7 @@
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/notifier.h>
#include <linux/device.h>
#include <linux/init.h>
#include <asm/dma.h>
......@@ -48,6 +49,7 @@
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#include <asm/mach/irq.h>
#include <asm/tlbflush.h>
#ifndef CONFIG_ARCH_RPC
#define HAVE_EXPMASK
......@@ -92,6 +94,8 @@ ecard_loader_reset(volatile unsigned char *pa, loader_t loader);
asmlinkage extern int
ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader);
static const struct ecard_id *
ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
static inline unsigned short
ecard_getu16(unsigned char *v)
......@@ -969,6 +973,14 @@ ecard_probe(int slot, card_type_t type)
*ecp = ec;
slot_to_expcard[slot] = ec;
snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
strcpy(ec->dev.name, "fixme!");
ec->dev.parent = NULL;
ec->dev.bus = &ecard_bus_type;
device_register(&ec->dev);
return 0;
nodev:
......@@ -995,22 +1007,17 @@ ecard_t *ecard_find(int cid, const card_ids *cids)
if (finding_pos->claimed)
continue;
if (finding_pos->dev.driver)
continue;
if (!cids) {
if ((finding_pos->cid.id ^ cid) == 0)
break;
} else {
unsigned int manufacturer, product;
int i;
manufacturer = finding_pos->cid.manufacturer;
product = finding_pos->cid.product;
for (i = 0; cids[i].manufacturer != 65535; i++)
if (manufacturer == cids[i].manufacturer &&
product == cids[i].product)
break;
const struct ecard_id *id;
if (cids[i].manufacturer != 65535)
id = ecard_match_device(cids, finding_pos);
if (id)
break;
}
}
......@@ -1023,7 +1030,7 @@ ecard_t *ecard_find(int cid, const card_ids *cids)
* Locate all hardware - interrupt management and
* actual cards.
*/
void __init ecard_init(void)
static int __init ecard_init(void)
{
int slot, irqhw;
......@@ -1053,11 +1060,96 @@ void __init ecard_init(void)
irqhw ? ecard_irqexp_handler : ecard_irq_handler);
ecard_proc_init();
return 0;
}
subsys_initcall(ecard_init);
/*
* ECARD "bus"
*/
static const struct ecard_id *
ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec)
{
int i;
for (i = 0; ids[i].manufacturer != 65535; i++)
if (ec->cid.manufacturer == ids[i].manufacturer &&
ec->cid.product == ids[i].product)
return ids + i;
return NULL;
}
static int ecard_drv_probe(struct device *dev)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct ecard_driver *drv = ECARD_DRV(dev->driver);
const struct ecard_id *id;
id = ecard_match_device(drv->id_table, ec);
return drv->probe(ec, id);
}
static int ecard_drv_remove(struct device *dev)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct ecard_driver *drv = ECARD_DRV(dev->driver);
drv->remove(ec);
return 0;
}
int ecard_register_driver(struct ecard_driver *drv)
{
drv->drv.bus = &ecard_bus_type;
drv->drv.probe = ecard_drv_probe;
drv->drv.remove = ecard_drv_remove;
return driver_register(&drv->drv);
}
void ecard_remove_driver(struct ecard_driver *drv)
{
remove_driver(&drv->drv);
}
static int ecard_match(struct device *_dev, struct device_driver *_drv)
{
struct expansion_card *ec = ECARD_DEV(_dev);
struct ecard_driver *drv = ECARD_DRV(_drv);
int ret;
if (drv->id_table) {
ret = ecard_match_device(drv->id_table, ec) != NULL;
} else {
ret = ec->cid.id == drv->id;
}
return ret;
}
struct bus_type ecard_bus_type = {
.name = "ecard",
.match = ecard_match,
};
static int ecard_bus_init(void)
{
return bus_register(&ecard_bus_type);
}
postcore_initcall(ecard_bus_init);
EXPORT_SYMBOL(ecard_startfind);
EXPORT_SYMBOL(ecard_find);
EXPORT_SYMBOL(ecard_readchunk);
EXPORT_SYMBOL(ecard_address);
EXPORT_SYMBOL(ecard_register_driver);
EXPORT_SYMBOL(ecard_remove_driver);
EXPORT_SYMBOL(ecard_bus_type);
......@@ -189,11 +189,10 @@ irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xe0000000
orr r4, r4, #0x20
mov \irqstat, #0x0C
strb \irqstat, [r4] @outb(0x0C, 0x20) /* Poll command */
ldrb \irqnr, [r4] @irq = inb(0x20) & 7
strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */
ldrb \irqnr, [r4, #0x10] @irq = inb(0x20) & 7
and \irqstat, \irqnr, #0x80
teq \irqstat, #0
beq 43f
......@@ -201,8 +200,8 @@ irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
teq \irqnr, #2
bne 44f
43: mov \irqstat, #0x0C
strb \irqstat, [r4, #0x80] @outb(0x0C, 0xA0) /* Poll command */
ldrb \irqnr, [r4, #0x80] @irq = (inb(0xA0) & 7) + 8
strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */
ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8
and \irqstat, \irqnr, #0x80
teq \irqstat, #0
beq 44f
......@@ -655,7 +654,7 @@ __und_invalid: sub sp, sp, #S_FRAME_SIZE
and r2, r6, #31 @ int mode
b bad_mode
#if defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE
#if 1 /* defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE */
/* The FPE is always present */
.equ fpe_not_present, fpundefinstr
#else
......@@ -766,6 +765,8 @@ preempt_return:
msr spsr, r0
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
.ltorg
#ifdef CONFIG_PREEMPT
svc_preempt: teq r9, #0 @ was preempt count = 0
ldreq r6, .LCirq_stat
......@@ -902,6 +903,8 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE
mov why, #0
b ret_to_user
.ltorg
.align 5
__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia sp, {r0 - r12} @ Save r0 - r12
......
......@@ -367,8 +367,8 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_debugreg[0] = tsk->thread.debug.bp[0].address;
dump->u_debugreg[1] = tsk->thread.debug.bp[1].address;
dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn;
dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn;
dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn.arm;
dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn.arm;
dump->u_debugreg[4] = tsk->thread.debug.nsaved;
if (dump->start_stack < 0x04000000)
......
......@@ -32,10 +32,24 @@
* in exit.c or in signal.c.
*/
#if 1
/*
* Breakpoint SWI instruction: SWI &9F0001
*/
#define BREAKINST_ARM 0xef9f0001
#define BREAKINST_THUMB 0xdf00 /* fill this in later */
#else
/*
* New breakpoints - use an undefined instruction. The ARM architecture
* reference manual guarantees that the following instruction space
* will produce an undefined instruction exception on all CPUs:
*
* ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
* Thumb: 1101 1110 xxxx xxxx
*/
#define BREAKINST_ARM 0xe7f001f0
#define BREAKINST_THUMB 0xde01
#endif
/*
* Get the address of the live pt_regs for the specified task.
......@@ -89,23 +103,32 @@ put_user_reg(struct task_struct *task, int offset, long data)
}
static inline int
read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res)
read_u32(struct task_struct *task, unsigned long addr, u32 *res)
{
int copied;
int ret;
copied = access_process_vm(child, addr, res, sizeof(*res), 0);
ret = access_process_vm(task, addr, res, sizeof(*res), 0);
return copied != sizeof(*res) ? -EIO : 0;
return ret == sizeof(*res) ? 0 : -EIO;
}
static inline int
write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val)
read_instr(struct task_struct *task, unsigned long addr, u32 *res)
{
int copied;
copied = access_process_vm(child, addr, &val, sizeof(val), 1);
int ret;
return copied != sizeof(val) ? -EIO : 0;
if (addr & 1) {
u16 val;
ret = access_process_vm(task, addr & ~1, &val, sizeof(val), 0);
ret = ret == sizeof(val) ? 0 : -EIO;
*res = val;
} else {
u32 val;
ret = access_process_vm(task, addr & ~3, &val, sizeof(val), 0);
ret = ret == sizeof(val) ? 0 : -EIO;
*res = val;
}
return ret;
}
/*
......@@ -206,7 +229,7 @@ ptrace_getldrop2(struct task_struct *child, unsigned long insn)
static unsigned long
get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
{
unsigned long alt = 0;
u32 alt = 0;
switch (insn & 0x0e000000) {
case 0x00000000:
......@@ -262,7 +285,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
else
base -= aluop2;
}
if (read_tsk_long(child, base, &alt) == 0)
if (read_u32(child, base, &alt) == 0)
alt = pc_pointer(alt);
}
break;
......@@ -289,7 +312,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
base = ptrace_getrn(child, insn);
if (read_tsk_long(child, base + nr_regs, &alt) == 0)
if (read_u32(child, base + nr_regs, &alt) == 0)
alt = pc_pointer(alt);
break;
}
......@@ -319,30 +342,71 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
}
static int
add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr)
swap_insn(struct task_struct *task, unsigned long addr,
void *old_insn, void *new_insn, int size)
{
int ret;
ret = access_process_vm(task, addr, old_insn, size, 0);
if (ret == size)
ret = access_process_vm(task, addr, new_insn, size, 1);
return ret;
}
static void
add_breakpoint(struct task_struct *task, struct debug_info *dbg, unsigned long addr)
{
int nr = dbg->nsaved;
int res = -EINVAL;
if (nr < 2) {
res = read_tsk_long(child, addr, &dbg->bp[nr].insn);
if (res == 0)
res = write_tsk_long(child, addr, BREAKINST_ARM);
u32 new_insn = BREAKINST_ARM;
int res;
if (res == 0) {
res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4);
if (res == 4) {
dbg->bp[nr].address = addr;
dbg->nsaved += 1;
}
} else
printk(KERN_ERR "ptrace: too many breakpoints\n");
}
/*
* Clear one breakpoint in the user program. We copy what the hardware
* does and use bit 0 of the address to indicate whether this is a Thumb
* breakpoint or an ARM breakpoint.
*/
static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp)
{
unsigned long addr = bp->address;
union debug_insn old_insn;
int ret;
if (addr & 1) {
ret = swap_insn(task, addr & ~1, &old_insn.thumb,
&bp->insn.thumb, 2);
return res;
if (ret != 2 || old_insn.thumb != BREAKINST_THUMB)
printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at "
"0x%08lx (0x%04x)\n", task->comm, task->pid,
addr, old_insn.thumb);
} else {
ret = swap_insn(task, addr & ~3, &old_insn.arm,
&bp->insn.arm, 4);
if (ret != 4 || old_insn.arm != BREAKINST_ARM)
printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at "
"0x%08lx (0x%08x)\n", task->comm, task->pid,
addr, old_insn.arm);
}
}
void ptrace_set_bpt(struct task_struct *child)
{
struct pt_regs *regs;
unsigned long pc, insn;
unsigned long pc;
u32 insn;
int res;
regs = get_user_regs(child);
......@@ -353,7 +417,7 @@ void ptrace_set_bpt(struct task_struct *child)
return;
}
res = read_tsk_long(child, pc, &insn);
res = read_instr(child, pc, &insn);
if (!res) {
struct debug_info *dbg = &child->thread.debug;
unsigned long alt;
......@@ -362,7 +426,7 @@ void ptrace_set_bpt(struct task_struct *child)
alt = get_branch_address(child, pc, insn);
if (alt)
res = add_breakpoint(child, dbg, alt);
add_breakpoint(child, dbg, alt);
/*
* Note that we ignore the result of setting the above
......@@ -374,7 +438,7 @@ void ptrace_set_bpt(struct task_struct *child)
* loose control of the thread during single stepping.
*/
if (!alt || predicate(insn) != PREDICATE_ALWAYS)
res = add_breakpoint(child, dbg, pc + 4);
add_breakpoint(child, dbg, pc + 4);
}
}
......@@ -384,24 +448,17 @@ void ptrace_set_bpt(struct task_struct *child)
*/
void __ptrace_cancel_bpt(struct task_struct *child)
{
struct debug_info *dbg = &child->thread.debug;
int i, nsaved = dbg->nsaved;
int i, nsaved = child->thread.debug.nsaved;
dbg->nsaved = 0;
child->thread.debug.nsaved = 0;
if (nsaved > 2) {
printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
nsaved = 2;
}
for (i = 0; i < nsaved; i++) {
unsigned long tmp;
read_tsk_long(child, dbg->bp[i].address, &tmp);
write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn);
if (tmp != BREAKINST_ARM)
printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n");
}
for (i = 0; i < nsaved; i++)
clear_breakpoint(child, &child->thread.debug.bp[i]);
}
/*
......@@ -537,9 +594,12 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
*/
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
ret = read_tsk_long(child, addr, &tmp);
if (!ret)
ret = access_process_vm(child, addr, &tmp,
sizeof(unsigned long), 0);
if (ret == sizeof(unsigned long))
ret = put_user(tmp, (unsigned long *) data);
else
ret = -EIO;
break;
case PTRACE_PEEKUSR:
......@@ -551,7 +611,12 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
*/
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
ret = write_tsk_long(child, addr, data);
ret = access_process_vm(child, addr, &data,
sizeof(unsigned long), 1);
if (ret == sizeof(unsigned long))
ret = 0;
else
ret = -EIO;
break;
case PTRACE_POKEUSR:
......
......@@ -193,26 +193,25 @@ static inline void dump_cache(const char *prefix, unsigned int cache)
CACHE_LINE(cache)));
}
static inline void dump_cpu_cache_id(void)
static void __init dump_cpu_info(void)
{
unsigned int cache_info;
unsigned int info;
asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (info));
if (cache_info == processor_id)
return;
printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(cache_info)]);
if (CACHE_S(cache_info)) {
dump_cache("CPU: I cache", CACHE_ISIZE(cache_info));
dump_cache("CPU: D cache", CACHE_DSIZE(cache_info));
} else {
dump_cache("CPU: cache", CACHE_ISIZE(cache_info));
if (info != processor_id) {
printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(info)]);
if (CACHE_S(info)) {
dump_cache("CPU: I cache", CACHE_ISIZE(info));
dump_cache("CPU: D cache", CACHE_DSIZE(info));
} else {
dump_cache("CPU: cache", CACHE_ISIZE(info));
}
}
}
#else
#define dump_cpu_cache_id() do { } while (0)
#define dump_cpu_info() do { } while (0)
#endif
static void __init setup_processor(void)
......@@ -255,7 +254,7 @@ static void __init setup_processor(void)
proc_info.manufacturer, proc_info.cpu_name,
(int)processor_id & 15);
dump_cpu_cache_id();
dump_cpu_info();
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
......
......@@ -59,11 +59,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t m
sigset_t saveset;
mask &= _BLOCKABLE;
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
regs->ARM_r0 = -EINTR;
while (1) {
......@@ -87,11 +87,11 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
regs->ARM_r0 = -EINTR;
while (1) {
......@@ -207,10 +207,10 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->sc))
goto badframe;
......@@ -247,10 +247,10 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
......@@ -477,12 +477,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&tsk->sigmask_lock);
spin_lock_irq(&tsk->sig->siglock);
sigorsets(&tsk->blocked, &tsk->blocked,
&ka->sa.sa_mask);
sigaddset(&tsk->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&tsk->sigmask_lock);
spin_unlock_irq(&tsk->sig->siglock);
}
return;
}
......@@ -520,20 +520,10 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
for (;;) {
unsigned long signr = 0;
struct k_sigaction *ka;
sigset_t *mask = &current->blocked;
local_irq_disable();
if (current->sig->shared_pending.head) {
spin_lock(&current->sig->siglock);
signr = dequeue_signal(&current->sig->shared_pending, mask, &info);
spin_unlock(&current->sig->siglock);
}
if (!signr) {
spin_lock(&current->sigmask_lock);
signr = dequeue_signal(&current->pending, mask, &info);
spin_unlock(&current->sigmask_lock);
}
local_irq_enable();
spin_lock_irq(&current->sig->siglock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sig->siglock);
if (!signr)
break;
......
......@@ -25,44 +25,37 @@ extern unsigned long (*gettimeoffset)(void);
static unsigned long ioctime_gettimeoffset(void)
{
unsigned int count1, count2, status1, status2;
unsigned long offset = 0;
unsigned int count1, count2, status;
long offset;
status1 = ioc_readb(IOC_IRQREQA);
barrier ();
ioc_writeb (0, IOC_T0LATCH);
barrier ();
count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
barrier ();
status2 = ioc_readb(IOC_IRQREQA);
status = ioc_readb(IOC_IRQREQA);
barrier ();
ioc_writeb (0, IOC_T0LATCH);
barrier ();
count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
offset = count2;
if (count2 < count1) {
/*
* This means that we haven't just had an interrupt
* while reading into status2.
* We have not had an interrupt between reading count1
* and count2.
*/
if (status2 & (1 << 5))
offset = tick;
count1 = count2;
if (status & (1 << 5))
offset -= LATCH;
} else if (count2 > count1) {
/*
* We have just had another interrupt while reading
* status2.
* We have just had another interrupt between reading
* count1 and count2.
*/
offset += tick;
count1 = count2;
offset -= LATCH;
}
count1 = LATCH - count1;
/*
* count1 = number of clock ticks since last interrupt
*/
offset += count1 * tick / LATCH;
return offset;
offset = (LATCH - offset) * (tick_nsec / 1000);
return (offset + LATCH/2) / LATCH;
}
void __init ioctime_init(void)
......
......@@ -115,8 +115,8 @@ static inline void do_set_rtc(void)
time_before(xtime.tv_sec, next_rtc_update))
return;
if (xtime.tv_usec < 50000 - (tick >> 1) &&
xtime.tv_usec >= 50000 + (tick >> 1))
if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
return;
if (set_rtc())
......@@ -166,7 +166,7 @@ void do_gettimeofday(struct timeval *tv)
usec += lost * USECS_PER_JIFFY;
sec = xtime.tv_sec;
usec += xtime.tv_usec;
usec += xtime.tv_nsec / 1000;
read_unlock_irqrestore(&xtime_lock, flags);
/* usec may have gone up a lot: be safe */
......@@ -196,7 +196,8 @@ void do_settimeofday(struct timeval *tv)
tv->tv_sec--;
}
xtime = *tv;
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_usec * 1000;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......
......@@ -32,6 +32,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/semaphore.h>
#include "ptrace.h"
......@@ -77,8 +78,7 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
fs = get_fs();
set_fs(KERNEL_DS);
printk("%s", str);
printk("(0x%08lx to 0x%08lx)\n", bottom, top);
printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
for (p = bottom & ~31; p < top;) {
printk("%04lx: ", p & 0xffff);
......@@ -136,7 +136,7 @@ static void dump_instr(struct pt_regs *regs)
set_fs(fs);
}
static void dump_stack(struct task_struct *tsk, unsigned long sp)
static void __dump_stack(struct task_struct *tsk, unsigned long sp)
{
dump_mem("Stack: ", sp, 8192+(unsigned long)tsk->thread_info);
}
......@@ -163,15 +163,20 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
}
/*
* This is called from SysRq-T (show_task) to display the current
* call trace for each process. Very useful.
* This is called from SysRq-T (show_task) to display the current call
* trace for each process. This version will also display the running
* threads call trace (ie, us.)
*/
void show_trace_task(struct task_struct *tsk)
{
if (tsk != current) {
unsigned int fp = thread_saved_fp(tsk);
c_backtrace(fp, 0x10);
}
unsigned int fp;
if (tsk != current)
fp = thread_saved_fp(tsk);
else
asm("mov%? %0, fp" : "=r" (fp));
c_backtrace(fp, 0x10);
}
spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
......@@ -193,7 +198,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
current->comm, current->pid, tsk->thread_info + 1);
if (!user_mode(regs) || in_interrupt()) {
dump_stack(tsk, (unsigned long)(regs + 1));
__dump_stack(tsk, (unsigned long)(regs + 1));
dump_backtrace(regs, tsk);
dump_instr(regs);
}
......
......@@ -73,36 +73,37 @@ static struct vco freq_to_vco(unsigned int freq_khz, int factor)
* Validate the speed in khz. If it is outside our
* range, then return the lowest.
*/
static unsigned int
integrator_validatespeed(unsigned int cpu, unsigned int freq_khz)
static void integrator_verify_speed(struct cpufreq_policy *policy)
{
struct vco vco;
if (freq_khz < 12000)
freq_khz = 12000;
if (freq_khz > 160000)
freq_khz = 160000;
if (policy->max > policy->max_cpu_freq)
policy->max = policy->max_cpu_freq;
vco = freq_to_vco(freq_khz, 1);
if (policy->max < 12000)
policy->max = 12000;
if (policy->max > 160000)
policy->max = 160000;
if (vco.vdw < 4 || vco.vdw > 152)
return -EINVAL;
vco = freq_to_vco(policy->max, 1);
return vco_to_freq(vco, 1);
if (vco.vdw < 4)
vco.vdw = 4;
if (vco.vdw > 152)
vco.vdw = 152;
policy->min = policy->max = vco_to_freq(vco, 1);
}
static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz)
static void do_set_policy(int cpu, struct cpufreq_policy *policy)
{
struct vco vco = freq_to_vco(freq_khz, 1);
unsigned long cpus_allowed;
struct vco vco = freq_to_vco(policy->max, 1);
u_int cm_osc;
/*
* Save this threads cpus_allowed mask, and bind to the
* specified CPU. When this call returns, we should be
* running on the right CPU.
* Bind to the specified CPU. When this call returns,
* we should be running on the right CPU.
*/
cpus_allowed = current->cpus_allowed;
set_cpus_allowed(current, 1 << cpu);
BUG_ON(cpu != smp_processor_id());
......@@ -113,6 +114,26 @@ static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz)
__raw_writel(0xa05f, CM_LOCK);
__raw_writel(cm_osc, CM_OSC);
__raw_writel(0, CM_LOCK);
}
static void 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.
......@@ -120,23 +141,30 @@ static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz)
set_cpus_allowed(current, cpus_allowed);
}
static struct cpufreq_policy integrator_policy = {
.cpu = 0,
.policy = CPUFREQ_POLICY_POWERSAVE,
.max_cpu_freq = 160000,
};
static struct cpufreq_driver integrator_driver = {
.validate = integrator_validatespeed,
.setspeed = integrator_setspeed,
.sync = 1,
.verify = integrator_verify_speed,
.setpolicy = integrator_set_policy,
.policy = &integrator_policy,
.cpu_min_freq = 12000,
};
#endif
static int __init integrator_cpu_init(void)
{
struct cpufreq_freqs *freqs;
struct cpufreq_policy *policies;
unsigned long cpus_allowed;
int cpu;
freqs = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS,
GFP_KERNEL);
if (!freqs) {
printk(KERN_ERR "CPU: unable to allocate cpufreqs structure\n");
policies = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS,
GFP_KERNEL);
if (!policies) {
printk(KERN_ERR "CPU: unable to allocate policies structure\n");
return -ENOMEM;
}
......@@ -164,18 +192,20 @@ static int __init integrator_cpu_init(void)
vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255;
freqs[cpu].min = 12000;
freqs[cpu].max = 160000;
freqs[cpu].cur = vco_to_freq(vco, 1);
policies[cpu].cpu = cpu;
policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE,
policies[cpu].max_cpu_freq = 160000;
policies[cpu].min =
policies[cpu].max = vco_to_freq(vco, 1);
}
set_cpus_allowed(current, cpus_allowed);
#ifdef CONFIG_CPU_FREQ
integrator_driver.freq = freqs;
integrator_driver.policy = policies;
cpufreq_register(&integrator_driver);
#else
kfree(freqs);
kfree(policies);
#endif
return 0;
......
......@@ -145,7 +145,7 @@ iop310_pri_read_config(struct pci_bus *bus, unsigned int devfn, int where,
}
static int
iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 value)
{
unsigned long addr = iop310_cfg_address(bus, devfn, where);
......@@ -163,7 +163,7 @@ iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
else
val &= ~(0xffff << where);
*IOP310_POCCDR = val | v << where;
*IOP310_POCCDR = val | value << where;
} else {
asm volatile(
"str %1, [%2]\n\t"
......@@ -173,7 +173,7 @@ iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr),
: "r" (value), "r" (addr),
"r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
}
......@@ -246,7 +246,7 @@ iop310_sec_read_config(struct pci_bus *bus, unsigned int devfn, int where,
}
static int
iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 value)
{
unsigned long addr = iop310_cfg_address(bus, devfn, where);
......@@ -265,7 +265,7 @@ iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
else
val &= ~(0xffff << where);
*IOP310_SOCCDR = val | v << where;
*IOP310_SOCCDR = val | value << where;
} else {
asm volatile(
"str %1, [%2]\n\t"
......@@ -275,7 +275,7 @@ iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr),
: "r" (value), "r" (addr),
"r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
}
......
......@@ -85,7 +85,7 @@ static unsigned long iq80310_gettimeoffset (void)
/*
* Now convert them to usec.
*/
usec = (unsigned long)(elapsed*tick)/LATCH;
usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
return usec;
}
......
......@@ -2,20 +2,17 @@
# Makefile for the linux kernel.
#
# Common support (must be linked before board specific support)
# Common support
obj-y := generic.o irq.o dma.o
obj-m :=
obj-n :=
obj- :=
led-y := leds.o
export-objs := dma.o generic.o pcipool.o pm.o sa1111.o sa1111-pcibuf.o \
usb_ctl.o usb_recv.o usb_send.o
export-objs := dma.o generic.o pcipool.o pm.o sa1111.o sa1111-pcibuf.o
# This needs to be cleaned up. We probably need to have SA1100
# and SA1110 config symbols.
#
# We link the CPU support next, so that RAM timings can be tuned.
ifeq ($(CONFIG_CPU_FREQ),y)
obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
......@@ -107,10 +104,7 @@ export-objs += yopy.o
obj-$(CONFIG_LEDS) += $(led-y)
# SA1110 USB client support
sa1100usb_core-objs := usb_ctl.o usb_ep0.o usb_recv.o usb_send.o
obj-$(CONFIG_SA1100_USB) += sa1100usb_core.o
obj-$(CONFIG_SA1100_USB_NETLINK) += usb-eth.o
obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o
#obj-$(CONFIG_SA1100_USB) += usb/
# Miscelaneous functions
obj-$(CONFIG_PM) += pm.o sleep.o
......
......@@ -302,21 +302,24 @@ static void __init assabet_map_io(void)
*/
neponset_map_io();
#endif
/*
* When Neponset is attached, the first UART should be
* UART3. That's what Angel is doing and many documents
* are stating this.
* We do the Neponset mapping even if Neponset support
* isn't compiled in so the user will still get something on
* the expected physical serial port.
*/
sa1100_register_uart(0, 3);
sa1100_register_uart(2, 1);
} else {
sa1100_register_uart_fns(&assabet_port_fns);
sa1100_register_uart(0, 1); /* com port */
sa1100_register_uart(2, 3); /* radio module */
}
/*
* When Neponset is attached, the first UART should be
* UART3. That's what Angel is doing and many documents
* are stating this.
*
* We do the Neponset mapping even if Neponset support
* isn't compiled in so the user will still get something on
* the expected physical serial port.
*
* We no longer do this; not all boot loaders support it,
* and UART3 appears to be somewhat unreliable with blob.
*/
sa1100_register_uart(0, 1);
sa1100_register_uart(2, 3);
}
......
......@@ -55,8 +55,8 @@ unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
khz /= 100;
for (i = 0; i < ARRAY_SIZE(cclk_frequency_100khz); i--)
if (cclk_frequency_100khz[i] >= khz)
for (i = NR_FREQS - 1; i > 0; i--)
if (cclk_frequency_100khz[i] <= khz)
break;
return i;
......
......@@ -193,20 +193,30 @@ static int neponset_resume(struct device *dev, u32 level)
}
static struct device_driver neponset_device_driver = {
.suspend = neponset_suspend,
.resume = neponset_resume,
.name = "NEPONSET",
.bus = &system_bus_type,
.suspend = neponset_suspend,
.resume = neponset_resume,
};
static struct device neponset_device = {
.name = "Neponset",
.bus_id = "neponset",
.driver = &neponset_device_driver,
static struct sys_device neponset_device = {
.name = "NEPONSET",
.id = 0,
.root = NULL,
.dev = {
.name = "Neponset",
.bus_id = "neponset",
.bus = &system_bus_type,
.driver = &neponset_device_driver,
},
};
static int __init neponset_init(void)
{
int ret;
driver_register(&neponset_device_driver);
/*
* The Neponset is only present on the Assabet machine type.
*/
......@@ -231,7 +241,7 @@ static int __init neponset_init(void)
return -ENODEV;
}
ret = register_sys_device(&neponset_device);
ret = sys_device_register(&neponset_device);
if (ret)
return ret;
......@@ -256,7 +266,7 @@ static int __init neponset_init(void)
return sa1111_init(0x40000000, IRQ_NEPONSET_SA1111);
}
arch_initcall(neponset_init);
subsys_initcall(neponset_init);
static struct map_desc neponset_io_desc[] __initdata = {
/* virtual physical length type */
......
This diff is collapsed.
......@@ -16,8 +16,10 @@
#include <linux/bitops.h>
#include <linux/init.h>
#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include "fault.h"
......
......@@ -519,6 +519,10 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
}
#ifndef CONFIG_DISCONTIGMEM
mem_map = contig_page_data.node_mem_map;
#endif
/*
* finish off the bad pages once
* the mem_map is initialised
......@@ -559,7 +563,9 @@ void __init mem_init(void)
initpages = &__init_end - &__init_begin;
high_memory = (void *)__va(meminfo.end);
#ifndef CONFIG_DISCONTIGMEM
max_mapnr = virt_to_page(high_memory) - mem_map;
#endif
/*
* We may have non-contiguous memory.
......
......@@ -15,9 +15,11 @@
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
/*
* 0xffff8000 to 0xffffffff is reserved for any ARM architecture
......
......@@ -13,6 +13,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
......@@ -20,6 +21,7 @@
#include <asm/rmap.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/tlbflush.h>
#include <asm/mach/map.h>
......@@ -213,6 +215,50 @@ static inline void clear_mapping(unsigned long virt)
pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
}
struct mem_types {
unsigned int prot_pte;
unsigned int prot_sect;
unsigned int domain;
};
static struct mem_types mem_types[] __initdata = {
[MT_DEVICE] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
L_PTE_WRITE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
.domain = DOMAIN_IO,
},
[MT_CACHECLEAN] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
L_PTE_CACHEABLE | L_PTE_BUFFERABLE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE |
PMD_SECT_BUFFERABLE,
.domain = DOMAIN_KERNEL,
},
[MT_MINICLEAN] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
L_PTE_CACHEABLE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE,
.domain = DOMAIN_KERNEL,
},
[MT_VECTORS] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
L_PTE_CACHEABLE | L_PTE_BUFFERABLE |
L_PTE_EXEC,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE |
PMD_SECT_BUFFERABLE,
.domain = DOMAIN_USER,
},
[MT_MEMORY] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
L_PTE_CACHEABLE | L_PTE_BUFFERABLE |
L_PTE_EXEC | L_PTE_WRITE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE |
PMD_SECT_BUFFERABLE | PMD_SECT_AP_WRITE,
.domain = DOMAIN_KERNEL,
}
};
/*
* Create the page directory entries and any necessary
* page tables for the mapping specified by `md'. We
......@@ -232,42 +278,9 @@ static void __init create_mapping(struct map_desc *md)
return;
}
prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY;
prot_sect = PMD_TYPE_SECT;
switch (md->type) {
case MT_DEVICE:
prot_pte |= L_PTE_WRITE;
prot_sect |= PMD_SECT_AP_WRITE;
domain = DOMAIN_IO;
break;
case MT_CACHECLEAN:
prot_pte |= L_PTE_CACHEABLE | L_PTE_BUFFERABLE;
prot_sect |= PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE;
domain = DOMAIN_KERNEL;
break;
case MT_MINICLEAN:
prot_pte |= L_PTE_CACHEABLE;
prot_sect |= PMD_SECT_CACHEABLE;
domain = DOMAIN_KERNEL;
break;
case MT_VECTORS:
prot_pte |= L_PTE_EXEC | L_PTE_CACHEABLE | L_PTE_BUFFERABLE;
prot_sect |= PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE;
domain = DOMAIN_USER;
break;
case MT_MEMORY:
prot_pte |= L_PTE_WRITE | L_PTE_EXEC | L_PTE_CACHEABLE | L_PTE_BUFFERABLE;
prot_sect |= PMD_SECT_AP_WRITE | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE;
domain = DOMAIN_KERNEL;
break;
}
prot_sect |= PMD_DOMAIN(domain);
domain = mem_types[md->type].domain;
prot_pte = mem_types[md->type].prot_pte;
prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
virt = md->virtual;
off = md->physical - virt;
......
......@@ -10,8 +10,10 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
#include <asm/proc-fns.h>
#include <asm/tlbflush.h>
#ifndef MULTI_CPU
EXPORT_SYMBOL(cpu_cache_clean_invalidate_all);
......@@ -29,11 +31,11 @@ EXPORT_SYMBOL(cpu_set_pte);
EXPORT_SYMBOL(processor);
#endif
#ifndef MULTI_TLB
EXPORT_SYMBOL_NOVERS(__cpu_flush_kern_tlb_all);
EXPORT_SYMBOL_NOVERS(__cpu_flush_user_tlb_mm);
EXPORT_SYMBOL_NOVERS(__cpu_flush_user_tlb_range);
EXPORT_SYMBOL_NOVERS(__cpu_flush_user_tlb_page);
#else
/*
* No module should need to touch the TLB (and currently
* no modules do. We export this for "loadkernel" support
* (booting a new kernel from within a running kernel.)
*/
#ifdef MULTI_TLB
EXPORT_SYMBOL(cpu_tlb);
#endif
......@@ -13,31 +13,10 @@
*/
#include <linux/linkage.h>
#include <asm/constants.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
.align 5
/*
* v3_flush_user_tlb_mm(mm)
*
* Invalidate all TLB entries in a particular address space
*
* - mm - mm_struct describing address space
*/
ENTRY(v3_flush_user_tlb_mm)
act_mm r1 @ get current->active_mm
teq r0, r1 @ == mm ?
movne pc, lr @ no, we dont do anything
/*
* v3_flush_kern_tlb_all()
*
* Invalidate the entire TLB
*/
ENTRY(v3_flush_kern_tlb_all)
mov r0, #0
mcr p15, 0, r0, c5, c0, 0 @ invalidate TLB
mov pc, lr
/*
* v3_flush_user_tlb_range(start, end, mm)
*
......@@ -62,32 +41,11 @@ ENTRY(v3_flush_kern_tlb_range)
blo 1b
mov pc, lr
/*
* v3_flush_user_tlb_page(vaddr,vma)
*
* Invalidate the specified page in the specified address space.
*
* - vaddr - virtual address (may not be aligned)
* - vma - vma_struct describing address range
*/
.align 5
ENTRY(v3_flush_user_tlb_page)
vma_vm_mm r2, r1 @ get vma->vm_mm
act_mm r3 @ get current->active_mm
teq r2, r3 @ equal
movne pc, lr @ no
ENTRY(v3_flush_kern_tlb_page)
mcr p15, 0, r0, c6, c0, 0 @ invalidate TLB entry
mov pc, lr
.section ".text.init", #alloc, #execinstr
.type v3_tlb_fns, #object
ENTRY(v3_tlb_fns)
.long v3_flush_kern_tlb_all
.long v3_flush_user_tlb_mm
.long v3_flush_user_tlb_range
.long v3_flush_user_tlb_page
.long v3_flush_kern_tlb_range
.long v3_flush_kern_tlb_page
.long v3_tlb_flags
.size v3_tlb_fns, . - v3_tlb_fns
......@@ -14,31 +14,10 @@
*/
#include <linux/linkage.h>
#include <asm/constants.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
.align 5
/*
* v4_flush_user_tlb_mm(mm)
*
* Invalidate all TLB entries in a particular address space
*
* - mm - mm_struct describing address space
*/
ENTRY(v4_flush_user_tlb_mm)
act_mm r1 @ get current->active_mm
teq r0, r1 @ == mm ?
movne pc, lr @ no, we dont do anything
/*
* v4_flush_kern_tlb_all()
*
* Invalidate the entire TLB
*/
ENTRY(v4_flush_kern_tlb_all)
mov r0, #0
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mov pc, lr
/*
* v4_flush_user_tlb_range(start, end, mm)
*
......@@ -64,25 +43,6 @@ ENTRY(v4_flush_user_tlb_range)
blo 1b
mov pc, lr
/*
* v4_flush_user_tlb_page(vaddr,vma)
*
* Invalidate the specified page in the specified address space.
*
* - vaddr - virtual address (may not be aligned)
* - vma - vma_struct describing address range
*/
.align 5
ENTRY(v4_flush_user_tlb_page)
vma_vm_mm r2, r1 @ get vma->vm_mm
act_mm r3 @ get current->active_mm
teq r2, r3 @ equal
movne pc, lr @ no
vma_vm_flags r2, r1
.v4_flush_kern_tlb_page:
mcr p15, 0, r0, c8, c7, 1 @ invalidate TLB entry
mov pc, lr
/*
* v4_flush_kerm_tlb_range(start, end)
*
......@@ -95,27 +55,11 @@ ENTRY(v4_flush_user_tlb_page)
.globl v4_flush_kern_tlb_range
.equ v4_flush_kern_tlb_range, .v4_flush_kern_tlb_range
/*
* v4_flush_kern_tlb_page(kaddr)
*
* Invalidate the TLB entry for the specified page. The address
* will be in the kernels virtual memory space. Current uses
* only require the D-TLB to be invalidated.
*
* - kaddr - Kernel virtual memory address
*/
.globl v4_flush_kern_tlb_page
.equ v4_flush_kern_tlb_page, .v4_flush_kern_tlb_page
.section ".text.init", #alloc, #execinstr
.type v4_tlb_fns, #object
ENTRY(v4_tlb_fns)
.long v4_flush_kern_tlb_all
.long v4_flush_user_tlb_mm
.long v4_flush_user_tlb_range
.long v4_flush_user_tlb_page
.long v4_flush_kern_tlb_range
.long v4_flush_kern_tlb_page
.long v4_tlb_flags
.size v4_tlb_fns, . - v4_tlb_fns
......@@ -14,34 +14,10 @@
*/
#include <linux/linkage.h>
#include <asm/constants.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
.align 5
/*
* v4wb_flush_user_tlb_mm(mm)
*
* Invalidate all TLB entries in a particular address space
*
* - mm - mm_struct describing address space
*/
ENTRY(v4wb_flush_user_tlb_mm)
ENTRY(v4wbi_flush_user_tlb_mm)
act_mm r1 @ get current->active_mm
teq r0, r1 @ == mm ?
movne pc, lr @ no, we dont do anything
/*
* v4wb_flush_tlb_all()
*
* Invalidate the entire TLB
*/
ENTRY(v4wb_flush_kern_tlb_all)
ENTRY(v4wbi_flush_kern_tlb_all)
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mov pc, lr
/*
* v4wb_flush_user_tlb_range(start, end, mm)
*
......@@ -69,28 +45,6 @@ ENTRY(v4wb_flush_user_tlb_range)
blo 1b
mov pc, lr
/*
* v4wb_flush_user_tlb_page(vaddr,vma)
*
* Invalidate the specified page in the specified address space.
*
* - vaddr - virtual address (may not be aligned)
* - vma - vma_struct describing address range
*/
.align 5
ENTRY(v4wb_flush_user_tlb_page)
vma_vm_mm r2, r1 @ get vma->vm_mm
act_mm r3 @ get current->active_mm
teq r2, r3 @ equal
movne pc, lr @ no
vma_vm_flags r2, r1
mov r3, #0
mcr p15, 0, r3, c7, c10, 4 @ drain WB
tst r2, #VM_EXEC
mcrne p15, 0, r3, c8, c5, 0 @ invalidate I TLB
mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
mov pc, lr
/*
* v4_flush_kerm_tlb_range(start, end)
*
......@@ -112,20 +66,6 @@ ENTRY(v4wb_flush_kern_tlb_range)
blo 1b
mov pc, lr
/*
* v4_flush_kern_tlb_page(kaddr)
*
* Invalidate the TLB entry for the specified page. The address
* will be in the kernels virtual memory space. Current uses
* only require the D-TLB to be invalidated.
*
* - kaddr - Kernel virtual memory address
*/
ENTRY(v4wb_flush_kern_tlb_page)
mcr p15, 0, r3, c8, c5, 0 @ invalidate I TLB
mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
mov pc, lr
/*
* These two are optimised for ARM920, ARM922, ARM926, Xscale
*/
......@@ -158,28 +98,6 @@ ENTRY(v4wbi_flush_user_tlb_range)
blo 1b
mov pc, lr
/*
* v4wb_flush_tlb_page(vaddr,vma)
*
* Invalidate the specified page in the specified address space.
*
* - vaddr - virtual address (may not be aligned)
* - vma - vma_struct describing address range
*/
.align 5
ENTRY(v4wbi_flush_user_tlb_page)
vma_vm_mm r2, r1 @ get vma->vm_mm
act_mm r3 @ get current->active_mm
teq r2, r3 @ equal
movne pc, lr @ no
vma_vm_flags r2, r1
mov r3, #0
mcr p15, 0, r3, c7, c10, 4 @ drain WB
tst r2, #VM_EXEC
mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
mov pc, lr
ENTRY(v4wbi_flush_kern_tlb_range)
mov r3, #0
mcr p15, 0, r3, c7, c10, 4 @ drain WB
......@@ -192,29 +110,18 @@ ENTRY(v4wbi_flush_kern_tlb_range)
blo 1b
mov pc, lr
ENTRY(v4wbi_flush_kern_tlb_page)
mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
mov pc, lr
.section ".text.init", #alloc, #execinstr
.type v4wb_tlb_fns, #object
ENTRY(v4wb_tlb_fns)
.long v4wb_flush_kern_tlb_all
.long v4wb_flush_user_tlb_mm
.long v4wb_flush_user_tlb_range
.long v4wb_flush_user_tlb_page
.long v4wb_flush_kern_tlb_range
.long v4wb_flush_kern_tlb_page
.long v4wb_tlb_flags
.size v4wb_tlb_fns, . - v4wb_tlb_fns
.type v4wbi_tlb_fns, #object
ENTRY(v4wbi_tlb_fns)
.long v4wbi_flush_kern_tlb_all
.long v4wbi_flush_user_tlb_mm
.long v4wbi_flush_user_tlb_range
.long v4wbi_flush_user_tlb_page
.long v4wbi_flush_kern_tlb_range
.long v4wbi_flush_kern_tlb_page
.long v4wbi_tlb_flags
.size v4wbi_tlb_fns, . - v4wbi_tlb_fns
......@@ -4,13 +4,10 @@
#ifdef CONFIG_ROM_KERNEL
#define DATAADDR 0x02080000
#define TEXTADDR 0x03800000
#include "vmlinux-armo-rom.lds.in"
#else
#define TEXTADDR 0x02080000
#include "vmlinux-armo.lds.in"
#endif
......@@ -19,7 +16,6 @@
#ifdef CONFIG_CPU_32
#define TEXTADDR 0xC0008000
#include "vmlinux-armv.lds.in"
#endif
/*
* Example showing how to pin down a range of virtual pages from user-space
* to be able to do for example DMA directly into them.
*
* It is necessary because the pages the virtual pointers reference, might
* not exist in memory (could be mapped to the zero-page, filemapped etc)
* and DMA cannot trigger the MMU to force them in (and would have time
* contraints making it impossible to wait for it anyway).
*
* Author: Bjorn Wesen
*
* $Log: kiobuftest.c,v $
* Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
* Import of Linux 2.5.1
*
* Revision 1.2 2001/02/27 13:52:50 bjornw
* malloc.h -> slab.h
*
* Revision 1.1 2001/01/19 15:57:49 bjornw
* Example of how to do direct HW -> user-mode DMA
*
*
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/iobuf.h>
#define KIOBUFTEST_MAJOR 124 /* in the local range, experimental */
static ssize_t
kiobuf_read(struct file *filp, char *buf, size_t len, loff_t *ppos)
{
struct kiobuf *iobuf;
int res, i;
/* Make a kiobuf that maps the entire length the reader has given
* us
*/
res = alloc_kiovec(1, &iobuf);
if (res)
return res;
if((res = map_user_kiobuf(READ, iobuf, (unsigned long)buf, len))) {
printk("map_user_kiobuf failed, return %d\n", res);
return res;
}
/* At this point, the virtual area buf[0] -> buf[len-1] will
* have corresponding pages mapped in physical memory and locked
* until we unmap the kiobuf. They cannot be swapped out or moved
* around.
*/
printk("nr_pages == %d\noffset == %d\nlength == %d\n",
iobuf->nr_pages, iobuf->offset, iobuf->length);
for(i = 0; i < iobuf->nr_pages; i++) {
printk("page_add(maplist[%d]) == 0x%x\n", i,
page_address(iobuf->maplist[i]));
}
/* This is the place to create the necessary scatter-gather vector
* for the DMA using the iobuf->maplist array and page_address
* (don't forget __pa if the DMA needs the actual physical DRAM address)
* and run it.
*/
/* Release the mapping and exit */
unmap_kiobuf(iobuf); /* The unlock_kiobuf is implicit here */
return len;
}
static struct file_operations kiobuf_fops = {
owner: THIS_MODULE,
read: kiobuf_read
};
static int __init
kiobuftest_init(void)
{
int res;
/* register char device */
res = register_chrdev(KIOBUFTEST_MAJOR, "kiobuftest", &kiobuf_fops);
if(res < 0) {
printk(KERN_ERR "kiobuftest: couldn't get a major number.\n");
return res;
}
printk("Initializing kiobuf-test device\n");
}
module_init(kiobuftest_init);
......@@ -70,6 +70,7 @@ static void __init allocate_pgdat(int nid)
node_datasz = PFN_UP(sizeof(struct pglist_data));
NODE_DATA(nid) = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
min_low_pfn += node_datasz;
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
}
/*
......
......@@ -345,8 +345,6 @@ static void fd_select_drive(int drive);
static void fd_deselect(void);
static void fd_motor_off_timer(unsigned long dummy);
static void check_change(unsigned long dummy);
static __inline__ void set_head_settle_flag(void);
static __inline__ int get_head_settle_flag(void);
static void floppy_irqconsequencehandler(void);
static void fd_error(void);
static void do_fd_action(int drive);
......@@ -363,7 +361,6 @@ static void fd_times_out(unsigned long dummy);
static void finish_fdc(void);
static void finish_fdc_done(int dummy);
static void floppy_off(unsigned int nr);
static __inline__ void copy_buffer(void *from, void *to);
static void setup_req_params(int drive);
static void redo_fd_request(void);
static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
......@@ -543,12 +540,12 @@ static void check_change(unsigned long dummy)
* seek operation, because we don't use seeks with verify.
*/
static __inline__ void set_head_settle_flag(void)
static inline void set_head_settle_flag(void)
{
HeadSettleFlag = FDC1772CMDADD_E;
}
static __inline__ int get_head_settle_flag(void)
static inline int get_head_settle_flag(void)
{
int tmp = HeadSettleFlag;
HeadSettleFlag = 0;
......@@ -560,6 +557,15 @@ static __inline__ int get_head_settle_flag(void)
/* General Interrupt Handling */
static inline void copy_buffer(void *from, void *to)
{
ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
int cnt;
for (cnt = 512 / 4; cnt; cnt--)
*p2++ = *p1++;
}
static void (*FloppyIRQHandler) (int status) = NULL;
static void floppy_irqconsequencehandler(void)
......@@ -1175,16 +1181,6 @@ static int floppy_revalidate(dev_t dev)
return 0;
}
static __inline__ void copy_buffer(void *from, void *to)
{
ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
int cnt;
for (cnt = 512 / 4; cnt; cnt--)
*p2++ = *p1++;
}
/* This sets up the global variables describing the current request. */
static void setup_req_params(int drive)
......
......@@ -3,18 +3,11 @@
#
# All the objects that export symbols.
obj-arc := keyb_arc.o
obj-rpc := keyb_ps2.o
obj-clps7500 := keyb_ps2.o defkeymap-acorn.o
obj-$(CONFIG_RPCMOUSE) += mouse_rpc.o
obj-$(CONFIG_ATOMWIDE_SERIAL) += serial-atomwide.o
obj-$(CONFIG_DUALSP_SERIAL) += serial-dualsp.o
obj-$(CONFIG_ARCH_ACORN) += defkeymap-acorn.o i2c.o pcf8583.o
obj-$(CONFIG_L7200_KEYB) += defkeymap-l7200.o keyb_l7200.o
obj-arc := keyb_arc.o defkeymap-acorn.o
# Do the i2c and rtc last
obj-y += $(obj-$(MACHINE))
obj-$(CONFIG_ARCH_ACORN) += i2c.o pcf8583.o
obj-$(CONFIG_L7200_KEYB) += defkeymap-l7200.o keyb_l7200.o
obj-y += $(obj-$(MACHINE))
include $(TOPDIR)/Rules.make
......
......@@ -132,7 +132,7 @@ static int k_set_rtc_time(void)
if (rtc_command(RTC_GETDATETIME, &old_rtctm))
return 0;
new_rtctm.cs = xtime.tv_usec / 10000;
new_rtctm.cs = xtime.tv_nsec / 10000000;
new_rtctm.secs = nowtime % 60; nowtime /= 60;
new_rtctm.mins = nowtime % 60; nowtime /= 60;
new_rtctm.hours = nowtime % 24;
......@@ -283,7 +283,7 @@ static int ioc_client_reg(struct i2c_client *client)
rtc_client = client;
get_rtc_time(&rtctm, &year);
xtime.tv_usec = rtctm.cs * 10000;
xtime.tv_nsec = rtctm.cs * 10000000;
xtime.tv_sec = mktime(year, rtctm.mon, rtctm.mday,
rtctm.hours, rtctm.mins, rtctm.secs);
set_rtc = k_set_rtc_time;
......
This diff is collapsed.
/*
* linux/drivers/char/mouse_rpc.c
*
* Copyright (C) 1996-1998 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This handles the Acorn RiscPCs mouse. We basically have a couple
* of hardware registers that track the sensor count for the X-Y movement
* and another register holding the button state. On every VSYNC interrupt
* we read the complete state and then work out if something has changed.
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/hardware/iomd.h>
#include "../../char/busmouse.h"
static short old_x, old_y, old_b;
static int mousedev;
void
mouse_rpc_irq(int irq, void *dev_id, struct pt_regs *regs)
{
short x, y, dx, dy;
int buttons;
x = (short)iomd_readl(IOMD_MOUSEX);
y = (short)iomd_readl(IOMD_MOUSEY);
buttons = (__raw_readl(0xe0310000) >> 4) & 7;
dx = x - old_x;
old_x = x;
dy = y - old_y;
old_y = y;
if (dx || dy || buttons != old_b) {
busmouse_add_movementbuttons(mousedev, dx, dy, buttons);
old_b = buttons;
}
}
static struct busmouse rpcmouse = {
6, "arcmouse", NULL, NULL, NULL, 7
};
static int __init mouse_rpc_init(void)
{
mousedev = register_busmouse(&rpcmouse);
if (mousedev < 0)
printk("rpcmouse: could not register mouse driver\n");
else {
old_x = (short)iomd_readl(IOMD_MOUSEX);
old_y = (short)iomd_readl(IOMD_MOUSEY);
old_b = (__raw_readl(0xe0310000) >> 4) & 7;
if (request_irq(IRQ_VSYNCPULSE, mouse_rpc_irq, SA_SHIRQ, "mouse", &mousedev)) {
printk("rpcmouse: unable to allocate VSYNC interrupt\n");
unregister_busmouse(mousedev);
mousedev = -1;
}
}
return mousedev >= 0 ? 0 : -ENODEV;
}
static void __exit mouse_rpc_exit(void)
{
if (mousedev >= 0) {
unregister_busmouse(mousedev);
free_irq(IRQ_VSYNCPULSE, &mousedev);
}
}
module_init(mouse_rpc_init);
module_exit(mouse_rpc_exit);
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("RiscPC mouse driver");
MODULE_LICENSE("GPL");
/*
* linux/arch/arm/drivers/char/serial-atomwide.c
*
* Copyright (C) 1996 Russell King.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Changelog:
* 02-05-1996 RMK Created
* 07-05-1996 RMK Altered for greater number of cards.
* 30-07-1996 RMK Now uses generic card code.
*/
#define MY_CARD_LIST { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL }
#define MY_NUMPORTS 3
#define MY_BAUD_BASE (7372800 / 16)
#define MY_BASE_ADDRESS(ec) \
ecard_address ((ec), ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2)
#define MY_PORT_ADDRESS(port,cardaddr) \
((cardaddr) + 0x200 - (port) * 0x100)
#include "serial-card.c"
/*
* linux/drivers/acorn/char/serial-card.c
*
* Copyright (C) 1996-1999 Russell King.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* A generic handler of serial expansion cards that use 16550s or
* the like.
*
* Definitions:
* MY_PRODS Product numbers to identify this card by
* MY_MANUS Manufacturer numbers to identify this card by
* MY_NUMPORTS Number of ports per card
* MY_BAUD_BASE Baud base for the card
* MY_INIT Initialisation routine name
* MY_BASE_ADDRESS(ec) Return base address for ports
* MY_PORT_ADDRESS
* (port,cardaddr) Return address for port using base address
* from above.
*
* Changelog:
* 30-07-1996 RMK Created
* 22-04-1998 RMK Removed old register_pre_init_serial
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/serial.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/ecard.h>
#include <asm/string.h>
#ifndef NUM_SERIALS
#define NUM_SERIALS MY_NUMPORTS * MAX_ECARDS
#endif
static int serial_ports[NUM_SERIALS];
static int serial_pcount;
static int serial_addr[NUM_SERIALS];
static struct expansion_card *expcard[MAX_ECARDS];
static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } };
static inline int serial_register_onedev (unsigned long port, int irq)
{
struct serial_struct req;
memset(&req, 0, sizeof(req));
req.baud_base = MY_BAUD_BASE;
req.irq = irq;
req.port = port;
req.flags = 0;
return register_serial(&req);
}
static int __init serial_card_init(void)
{
int card = 0;
ecard_startfind ();
do {
struct expansion_card *ec;
unsigned long cardaddr;
int port;
ec = ecard_find (0, serial_cids);
if (!ec)
break;
cardaddr = MY_BASE_ADDRESS(ec);
for (port = 0; port < MY_NUMPORTS; port ++) {
unsigned long address;
int line;
address = MY_PORT_ADDRESS(port, cardaddr);
line = serial_register_onedev (address, ec->irq);
if (line < 0)
break;
serial_ports[serial_pcount] = line;
serial_addr[serial_pcount] = address;
serial_pcount += 1;
}
if (port) {
ecard_claim (ec);
expcard[card] = ec;
} else
break;
} while (++card < MAX_ECARDS);
return card ? 0 : -ENODEV;
}
static void __exit serial_card_exit(void)
{
int i;
for (i = 0; i < serial_pcount; i++) {
unregister_serial(serial_ports[i]);
release_region(serial_addr[i], 8);
}
for (i = 0; i < MAX_ECARDS; i++)
if (expcard[i])
ecard_release (expcard[i]);
}
MODULE_AUTHOR("Russell King");
MODULE_LICENSE("GPL");
module_init(serial_card_init);
module_exit(serial_card_exit);
......@@ -43,6 +43,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
......@@ -80,11 +81,6 @@ static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King
#define BUS_16 16
#define BUS_8 8
static const card_ids __init ether1_cids[] = {
{ MANU_ACORN, PROD_ACORN_ETHER1 },
{ 0xffff, 0xffff }
};
/* ------------------------------------------------------------------------- */
#define DISABLEIRQS 1
......@@ -647,6 +643,12 @@ ether1_open (struct net_device *dev)
{
struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
if (!is_valid_ether_addr(dev->dev_addr)) {
printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
dev->name);
return -EINVAL;
}
if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
return -EAGAIN;
......@@ -971,6 +973,23 @@ ether1_getstats (struct net_device *dev)
return &priv->stats;
}
static int
ether1_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
/*
* We'll set the MAC address on the chip when we open it.
*/
return 0;
}
/*
* Set or clear the multicast filter for this adaptor.
* num_addrs == -1 Promiscuous mode, receive all packets.
......@@ -993,19 +1012,22 @@ static void __init ether1_banner(void)
printk(KERN_INFO "%s", version);
}
static struct net_device * __init ether1_init_one(struct expansion_card *ec)
static int __devinit
ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct net_device *dev;
struct ether1_priv *priv;
int i;
int i, ret = 0;
ether1_banner();
ecard_claim(ec);
dev = init_etherdev(NULL, sizeof(struct ether1_priv));
if (!dev)
if (!dev) {
ret = -ENOMEM;
goto out;
}
SET_MODULE_OWNER(dev);
......@@ -1019,8 +1041,10 @@ static struct net_device * __init ether1_init_one(struct expansion_card *ec)
request_region(dev->base_addr + 0x800, 4096, dev->name);
priv = (struct ether1_priv *)dev->priv;
if ((priv->bus_type = ether1_reset(dev)) == 0)
if ((priv->bus_type = ether1_reset(dev)) == 0) {
ret = -ENODEV;
goto release;
}
printk(KERN_INFO "%s: ether1 in slot %d, ",
dev->name, ec->slot_no);
......@@ -1030,16 +1054,21 @@ static struct net_device * __init ether1_init_one(struct expansion_card *ec)
printk ("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
}
if (ether1_init_2(dev))
if (ether1_init_2(dev)) {
ret = -ENODEV;
goto release;
}
dev->open = ether1_open;
dev->stop = ether1_close;
dev->hard_start_xmit = ether1_sendpacket;
dev->get_stats = ether1_getstats;
dev->set_multicast_list = ether1_setmulticastlist;
dev->set_mac_address = ether1_set_mac_address;
dev->tx_timeout = ether1_timeout;
dev->watchdog_timeo = 5 * HZ / 100;
ecard_set_drvdata(ec, dev);
return 0;
release:
......@@ -1049,55 +1078,46 @@ static struct net_device * __init ether1_init_one(struct expansion_card *ec)
kfree(dev);
out:
ecard_release(ec);
return dev;
return ret;
}
static struct expansion_card *e_card[MAX_ECARDS];
static struct net_device *e_dev[MAX_ECARDS];
static int __init ether1_init(void)
static void __devexit ether1_remove(struct expansion_card *ec)
{
int i, ret = -ENODEV;
struct net_device *dev = ecard_get_drvdata(ec);
ecard_startfind();
ecard_set_drvdata(ec, NULL);
for (i = 0; i < MAX_ECARDS; i++) {
struct expansion_card *ec;
struct net_device *dev;
unregister_netdev(dev);
ec = ecard_find(0, ether1_cids);
if (!ec)
break;
release_region(dev->base_addr, 16);
release_region(dev->base_addr + 0x800, 4096);
kfree(dev);
dev = ether1_init_one(ec);
if (!dev)
break;
ecard_release(ec);
}
e_card[i] = ec;
e_dev[i] = dev;
ret = 0;
}
static const struct ecard_id ether1_ids[] = {
{ MANU_ACORN, PROD_ACORN_ETHER1 },
{ 0xffff, 0xffff }
};
return ret;
static struct ecard_driver ether1_driver = {
.probe = ether1_probe,
.remove = __devexit_p(ether1_remove),
.id_table = ether1_ids,
.drv = {
.name = "ether1",
},
};
static int __init ether1_init(void)
{
return ecard_register_driver(&ether1_driver);
}
static void __exit ether1_exit(void)
{
int i;
for (i = 0; i < MAX_ECARDS; i++) {
if (e_dev[i]) {
unregister_netdev(e_dev[i]);
release_region(e_dev[i]->base_addr, 16);
release_region(e_dev[i]->base_addr + 0x800, 4096);
kfree(e_dev[i]);
e_dev[i] = NULL;
}
if (e_card[i]) {
ecard_release(e_card[i]);
e_card[i] = NULL;
}
}
ecard_remove_driver(&ether1_driver);
}
module_init(ether1_init);
......
......@@ -61,6 +61,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/delay.h>
......@@ -75,12 +76,6 @@ static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.Kin
#include "ether3.h"
static unsigned int net_debug = NET_DEBUG;
static const card_ids __init ether3_cids[] = {
{ MANU_ANT2, PROD_ANT_ETHER3 },
{ MANU_ANT, PROD_ANT_ETHER3 },
{ MANU_ANT, PROD_ANT_ETHERB },
{ 0xffff, 0xffff }
};
static void ether3_setmulticastlist(struct net_device *dev);
static int ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt);
......@@ -417,6 +412,12 @@ ether3_probe_bus_16(struct net_device *dev, int val)
static int
ether3_open(struct net_device *dev)
{
if (!is_valid_ether_addr(dev->dev_addr)) {
printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
dev->name);
return -EINVAL;
}
if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
return -EAGAIN;
......@@ -460,6 +461,23 @@ static struct net_device_stats *ether3_getstats(struct net_device *dev)
return &priv->stats;
}
static int
ether3_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
/*
* We'll set the MAC address on the chip when we open it.
*/
return 0;
}
/*
* Set or clear promiscuous/multicast mode filter for this adaptor.
*
......@@ -784,6 +802,7 @@ static const char * __init
ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
{
const char *name = "ether3";
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
dev->irq = ec->irq;
......@@ -796,38 +815,44 @@ ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
ec->irqmask = 0xf0;
if (ether3_addr(dev->dev_addr, ec))
name = NULL;
ether3_addr(dev->dev_addr, ec);
return name;
}
static struct net_device * __init ether3_init_one(struct expansion_card *ec)
static int __devinit
ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct net_device *dev;
struct dev_priv *priv;
const char *name;
int i, bus_type;
int i, bus_type, ret;
ether3_banner();
ecard_claim(ec);
dev = init_etherdev(NULL, sizeof(struct dev_priv));
if (!dev)
if (!dev) {
ret = -ENOMEM;
goto out;
}
SET_MODULE_OWNER(dev);
name = ether3_get_dev(dev, ec);
if (!name)
if (!name) {
ret = -ENODEV;
goto free;
}
/*
* this will not fail - the nature of the bus ensures this
*/
if (!request_region(dev->base_addr, 128, dev->name))
if (!request_region(dev->base_addr, 128, dev->name)) {
ret = -EBUSY;
goto free;
}
priv = (struct dev_priv *) dev->priv;
......@@ -852,11 +877,13 @@ static struct net_device * __init ether3_init_one(struct expansion_card *ec)
switch (bus_type) {
case BUS_UNKNOWN:
printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
ret = -ENODEV;
goto failed;
case BUS_8:
printk(KERN_ERR "%s: %s found, but is an unsupported "
"8-bit card\n", dev->name, name);
ret = -ENODEV;
goto failed;
default:
......@@ -867,16 +894,21 @@ static struct net_device * __init ether3_init_one(struct expansion_card *ec)
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
if (ether3_init_2(dev))
if (ether3_init_2(dev)) {
ret = -ENODEV;
goto failed;
}
dev->open = ether3_open;
dev->stop = ether3_close;
dev->hard_start_xmit = ether3_sendpacket;
dev->get_stats = ether3_getstats;
dev->set_multicast_list = ether3_setmulticastlist;
dev->set_mac_address = ether3_set_mac_address;
dev->tx_timeout = ether3_timeout;
dev->watchdog_timeo = 5 * HZ / 100;
ecard_set_drvdata(ec, dev);
return 0;
failed:
......@@ -886,54 +918,46 @@ static struct net_device * __init ether3_init_one(struct expansion_card *ec)
kfree(dev);
out:
ecard_release(ec);
return NULL;
return ret;
}
static struct expansion_card *e_card[MAX_ECARDS];
static struct net_device *e_dev[MAX_ECARDS];
static int ether3_init(void)
static void __devexit ether3_remove(struct expansion_card *ec)
{
int i, ret = -ENODEV;
struct net_device *dev = ecard_get_drvdata(ec);
ecard_startfind();
ecard_set_drvdata(ec, NULL);
for (i = 0; i < MAX_ECARDS; i++) {
struct net_device *dev;
struct expansion_card *ec;
unregister_netdev(dev);
release_region(dev->base_addr, 128);
kfree(dev);
ec = ecard_find(0, ether3_cids);
if (!ec)
break;
ecard_release(ec);
}
dev = ether3_init_one(ec);
if (!dev)
break;
static const struct ecard_id ether3_ids[] = {
{ MANU_ANT2, PROD_ANT_ETHER3 },
{ MANU_ANT, PROD_ANT_ETHER3 },
{ MANU_ANT, PROD_ANT_ETHERB },
{ 0xffff, 0xffff }
};
e_card[i] = ec;
e_dev[i] = dev;
ret = 0;
}
static struct ecard_driver ether3_driver = {
.probe = ether3_probe,
.remove = __devexit_p(ether3_remove),
.id_table = ether3_ids,
.drv = {
.name = "ether3",
},
};
return ret;
static int __init ether3_init(void)
{
return ecard_register_driver(&ether3_driver);
}
static void ether3_exit(void)
static void __exit ether3_exit(void)
{
int i;
for (i = 0; i < MAX_ECARDS; i++) {
if (e_dev[i]) {
unregister_netdev(e_dev[i]);
release_region(e_dev[i]->base_addr, 128);
kfree(e_dev[i]);
e_dev[i] = NULL;
}
if (e_card[i]) {
ecard_release(e_card[i]);
e_card[i] = NULL;
}
}
ecard_remove_driver(&ether3_driver);
}
module_init(ether3_init);
......
......@@ -42,6 +42,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <asm/system.h>
......@@ -57,14 +58,6 @@
static unsigned int net_debug = NET_DEBUG;
static const card_ids __init etherh_cids[] = {
{ MANU_ANT, PROD_ANT_ETHERM },
{ MANU_I3, PROD_I3_ETHERLAN500 },
{ MANU_I3, PROD_I3_ETHERLAN600 },
{ MANU_I3, PROD_I3_ETHERLAN600A },
{ 0xffff, 0xffff }
};
struct etherh_priv {
struct ei_device eidev;
unsigned int id;
......@@ -441,6 +434,12 @@ etherh_open(struct net_device *dev)
{
struct ei_device *ei_local = (struct ei_device *) dev->priv;
if (!is_valid_ether_addr(dev->dev_addr)) {
printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
dev->name);
return -EINVAL;
}
if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))
return -EAGAIN;
......@@ -483,6 +482,23 @@ etherh_close(struct net_device *dev)
return 0;
}
static int
etherh_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
/*
* We'll set the MAC address on the chip when we open it.
*/
return 0;
}
/*
* Initialisation
*/
......@@ -541,21 +557,24 @@ static int __init etherm_addr(char *addr)
static u32 etherh_regoffsets[16];
static u32 etherm_regoffsets[16];
static struct net_device * __init etherh_init_one(struct expansion_card *ec)
static int __init
etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct ei_device *ei_local;
struct net_device *dev;
struct etherh_priv *eh;
const char *dev_type;
int i, size;
int i, size, ret;
etherh_banner();
ecard_claim(ec);
dev = init_etherdev(NULL, sizeof(struct etherh_priv));
if (!dev)
if (!dev) {
ret = -ENOMEM;
goto out;
}
/*
* init_etherdev allocs and zeros dev->priv
......@@ -566,33 +585,33 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
SET_MODULE_OWNER(dev);
dev->open = etherh_open;
dev->stop = etherh_close;
dev->set_config = etherh_set_config;
dev->irq = ec->irq;
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
dev->priv = eh;
dev->open = etherh_open;
dev->stop = etherh_close;
dev->set_mac_address = etherh_set_mac_address;
dev->set_config = etherh_set_config;
dev->irq = ec->irq;
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
/*
* IRQ and control port handling
*/
ec->ops = &etherh_ops;
ec->irq_data = eh;
eh->ctrl = 0;
eh->id = ec->cid.product;
if (ec->irq != 11) {
ec->ops = &etherh_ops;
ec->irq_data = eh;
}
eh->ctrl = 0;
eh->id = ec->cid.product;
switch (ec->cid.product) {
case PROD_ANT_ETHERM:
if (etherm_addr(dev->dev_addr))
goto free;
etherm_addr(dev->dev_addr);
dev->base_addr += ETHERM_NS8390;
dev->mem_start = dev->base_addr + ETHERM_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT;
break;
case PROD_I3_ETHERLAN500:
if (etherh_addr(dev->dev_addr, ec))
goto free;
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
......@@ -601,8 +620,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
if (etherh_addr(dev->dev_addr, ec))
goto free;
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH600_NS8390;
dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT;
......@@ -611,6 +629,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
default:
printk(KERN_ERR "%s: unknown card type %x\n",
dev->name, ec->cid.product);
ret = -ENODEV;
goto free;
}
......@@ -618,11 +637,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (ec->cid.product == PROD_ANT_ETHERM)
size <<= 3;
if (!request_region(dev->base_addr, size, dev->name))
if (!request_region(dev->base_addr, size, dev->name)) {
ret = -EBUSY;
goto free;
}
if (ethdev_init(dev))
if (ethdev_init(dev)) {
ret = -ENODEV;
goto release;
}
/*
* If we're in the NIC slot, make sure the IRQ is enabled
......@@ -690,7 +713,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
etherh_reset(dev);
NS8390_init(dev, 0);
return dev;
ecard_set_drvdata(ec, dev);
return 0;
release:
release_region(dev->base_addr, 16);
......@@ -700,67 +726,59 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
kfree(dev);
out:
ecard_release(ec);
return NULL;
return ret;
}
static void __devexit etherh_remove(struct expansion_card *ec)
{
struct net_device *dev = ecard_get_drvdata(ec);
int size = 16;
ecard_set_drvdata(ec, NULL);
unregister_netdev(dev);
if (ec->cid.product == PROD_ANT_ETHERM)
size <<= 3;
release_region(dev->base_addr, size);
kfree(dev);
ec->ops = NULL;
kfree(ec->irq_data);
ecard_release(ec);
}
#define MAX_ETHERH_CARDS 2
static const struct ecard_id etherh_ids[] = {
{ MANU_ANT, PROD_ANT_ETHERM },
{ MANU_I3, PROD_I3_ETHERLAN500 },
{ MANU_I3, PROD_I3_ETHERLAN600 },
{ MANU_I3, PROD_I3_ETHERLAN600A },
{ 0xffff, 0xffff }
};
static struct net_device *e_dev[MAX_ETHERH_CARDS];
static struct expansion_card *e_card[MAX_ETHERH_CARDS];
static struct ecard_driver etherh_driver = {
.probe = etherh_probe,
.remove = __devexit_p(etherh_remove),
.id_table = etherh_ids,
.drv = {
.name = "etherh",
},
};
static int __init etherh_init(void)
{
int i, ret = -ENODEV;
int i;
for (i = 0; i < 16; i++) {
etherh_regoffsets[i] = i;
etherm_regoffsets[i] = i << 3;
}
ecard_startfind();
for (i = 0; i < MAX_ECARDS; i++) {
struct expansion_card *ec;
struct net_device *dev;
ec = ecard_find(0, etherh_cids);
if (!ec)
break;
dev = etherh_init_one(ec);
if (!dev)
break;
e_card[i] = ec;
e_dev[i] = dev;
ret = 0;
}
return ret;
return ecard_register_driver(&etherh_driver);
}
static void __exit etherh_exit(void)
{
int i;
for (i = 0; i < MAX_ETHERH_CARDS; i++) {
if (e_dev[i]) {
int size;
unregister_netdev(e_dev[i]);
size = 16;
if (e_card[i]->cid.product == PROD_ANT_ETHERM)
size <<= 3;
release_region(e_dev[i]->base_addr, size);
kfree(e_dev[i]);
e_dev[i] = NULL;
}
if (e_card[i]) {
e_card[i]->ops = NULL;
kfree(e_card[i]->irq_data);
ecard_release(e_card[i]);
e_card[i] = NULL;
}
}
ecard_remove_driver(&etherh_driver);
}
module_init(etherh_init);
......
......@@ -319,12 +319,12 @@ acornscsi_csdelay(unsigned int cs)
target_jiffies = jiffies + 1 + cs * HZ / 100;
save_flags(flags);
sti();
local_save_flags(flags);
local_irq_enable();
while (time_before(jiffies, target_jiffies)) barrier();
restore_flags(flags);
local_irq_restore(flags);
}
static
......@@ -403,8 +403,9 @@ void acornscsi_resetcard(AS_Host *host)
host->scsi.phase = PHASE_IDLE;
host->scsi.disconnectable = 0;
memset(host->busyluns, 0, sizeof(host->busyluns));
for (i = 0; i < 8; i++) {
host->busyluns[i] = 0;
host->device[i].sync_state = SYNC_NEGOCIATE;
host->device[i].disconnect_ok = 1;
}
......@@ -1593,7 +1594,7 @@ void acornscsi_message(AS_Host *host)
printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
host->host->host_no, acornscsi_target(host));
host->SCpnt->device->tagged_queue = 0;
set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);
set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, host->busyluns);
break;
#endif
case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
......@@ -2637,8 +2638,7 @@ acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
printk("executing ");
//#endif
save_flags(flags);
cli();
local_irq_save(flags);
switch (host->scsi.phase) {
/*
* If the interface is idle, and the command is 'disconnectable',
......@@ -2671,7 +2671,7 @@ acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
acornscsi_abortcmd(host, host->SCpnt->tag);
res = res_snooze;
}
restore_flags(flags);
local_irq_restore(flags);
} else if (host->origSCpnt == SCpnt) {
/*
* The command will be executed next, but a command
......
......@@ -326,7 +326,7 @@ typedef struct acornscsi_hostdata {
syncxfer_t sync_state; /* sync xfer negociation state */
unsigned char disconnect_ok:1; /* device can disconnect */
} device[8];
unsigned char busyluns[8]; /* array of bits indicating LUNs busy */
unsigned long busyluns[64 / sizeof(unsigned long)];/* array of bits indicating LUNs busy */
/* DMA info */
struct {
......
......@@ -83,11 +83,9 @@ static const card_ids cumanascsi_cids[] = {
#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
#define do_NCR5380_intr do_cumanascsi_intr
#define NCR5380_queue_command cumanascsi_queue_command
#define NCR5380_abort cumanascsi_abort
#define NCR5380_reset cumanascsi_reset
#define NCR5380_proc_info cumanascsi_proc_info
#define NCR5380_intr cumanascsi_intr
#define NCR5380_queue_command cumanascsi_queue_command
#define NCR5380_proc_info cumanascsi_proc_info
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout);
......@@ -159,7 +157,7 @@ int cumanascsi_detect(Scsi_Host_Template * tpnt)
outb(0x00, instance->io_port - 577);
if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
if (request_irq(instance->irq, cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
printk("scsi%d: IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
......@@ -401,8 +399,10 @@ static Scsi_Host_Template cumanascsi_template = {
.release = cumanascsi_release,
.info = cumanascsi_info,
.queuecommand = cumanascsi_queue_command,
.abort = cumanascsi_abort,
.reset = cumanascsi_reset,
.eh_abort_handler = NCR5380_abort,
.eh_device_reset_handler= NCR5380_device_reset,
.eh_bus_reset_handler = NCR5380_bus_reset,
.eh_host_reset_handler = NCR5380_host_reset,
.bios_param = scsicam_bios_param,
.can_queue = 16,
.this_id = 7,
......
......@@ -248,11 +248,9 @@ printk("reading %p len %d\n",addr, len);
#define NCR5380_read(reg) ecoscsi_read(_instance, reg)
#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
#define do_NCR5380_intr do_ecoscsi_intr
#define NCR5380_queue_command ecoscsi_queue_command
#define NCR5380_abort ecoscsi_abort
#define NCR5380_reset ecoscsi_reset
#define NCR5380_proc_info ecoscsi_proc_info
#define NCR5380_intr ecoscsi_intr
#define NCR5380_queue_command ecoscsi_queue_command
#define NCR5380_proc_info ecoscsi_proc_info
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout);
......@@ -269,8 +267,10 @@ static Scsi_Host_Template ecoscsi_template = {
.release = ecoscsi_release,
.info = ecoscsi_info,
.queuecommand = ecoscsi_queue_command,
.abort = ecoscsi_abort,
.reset = ecoscsi_reset,
.eh_abort_handler = NCR5380_abort,
.eh_device_reset_handler= NCR5380_device_reset,
.eh_bus_reset_handler = NCR5380_bus_reset,
.eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
......
......@@ -603,7 +603,7 @@ fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
* next buffer.
*/
bytes_transferred -= SCp->this_residual;
if (!next_SCp(&info->scsi.SCp)) {
if (!next_SCp(&info->scsi.SCp) && bytes_transferred) {
printk(KERN_WARNING "scsi%d.%c: out of buffers\n",
info->host->host_no, '0' + info->SCpnt->target);
return;
......@@ -2300,8 +2300,8 @@ int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
{
FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
printk("scsi%d.%c: "__FUNCTION__": called\n",
info->host->host_no, '0' + SCpnt->target);
printk("scsi%d.%c: %s: called\n",
info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
return FAILED;
}
......@@ -2320,8 +2320,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
info->stats.bus_resets += 1;
printk("scsi%d.%c: "__FUNCTION__": resetting bus\n",
info->host->host_no, '0' + SCpnt->target);
printk("scsi%d.%c: %s: resetting bus\n",
info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
/*
* Attempt to stop all activity on this interface.
......@@ -2381,8 +2381,8 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
fas216_checkmagic(info);
printk("scsi%d.%c: "__FUNCTION__": resetting host\n",
info->host->host_no, '0' + SCpnt->target);
printk("scsi%d.%c: %s: resetting host\n",
info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
/*
* Reset the SCSI chip.
......
......@@ -288,7 +288,7 @@ typedef struct {
neg_t sync_state; /* synchronous transfer mode */
neg_t wide_state; /* wide transfer mode */
} device[8];
unsigned char busyluns[8]; /* array of bits indicating LUNs busy */
unsigned long busyluns[64/sizeof(unsigned long)];/* array of bits indicating LUNs busy */
/* dma */
struct {
......
......@@ -64,10 +64,8 @@
#define NCR5380_read(reg) oakscsi_read(_instance, reg)
#define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value)
#define do_NCR5380_intr do_oakscsi_intr
#define NCR5380_intr oakscsi_intr
#define NCR5380_queue_command oakscsi_queue_command
#define NCR5380_abort oakscsi_abort
#define NCR5380_reset oakscsi_reset
#define NCR5380_proc_info oakscsi_proc_info
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
......@@ -142,7 +140,7 @@ int oakscsi_detect(Scsi_Host_Template * tpnt)
}
if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
if (request_irq(instance->irq, oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
printk("scsi%d: IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
......@@ -264,8 +262,10 @@ static Scsi_Host_Template oakscsi_template = {
.release = oakscsi_release,
.info = oakscsi_info,
.queuecommand = oakscsi_queue_command,
.abort = oakscsi_abort,
.reset = oakscsi_reset,
.eh_abort_handler = NCR5380_abort,
.eh_device_reset_handler= NCR5380_device_reset,
.eh_bus_reset_handler = NCR5380_bus_reset,
.eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
......
......@@ -161,7 +161,7 @@ static Scsi_Cmnd *__queue_remove(Queue_t *queue, struct list_head *ent)
* exclude - bit array of target&lun which is busy
* Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
*/
Scsi_Cmnd *queue_remove_exclude(Queue_t *queue, void *exclude)
Scsi_Cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude)
{
unsigned long flags;
struct list_head *l;
......
......@@ -46,7 +46,7 @@ extern Scsi_Cmnd *queue_remove (Queue_t *queue);
* exclude - array of busy LUNs
* Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
*/
extern Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, void *exclude);
extern Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned long *exclude);
#define queue_add_cmd_ordered(queue,SCpnt) \
__queue_add(queue,SCpnt,(SCpnt)->cmnd[0] == REQUEST_SENSE)
......
......@@ -51,7 +51,7 @@ static inline int next_SCp(Scsi_Pointer *SCp)
static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp)
{
char c = SCp->ptr;
char c = *SCp->ptr;
SCp->ptr += 1;
SCp->this_residual -= 1;
......@@ -63,7 +63,7 @@ static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp)
static inline void put_next_SCp_byte(Scsi_Pointer *SCp, unsigned char c)
{
SCp->ptr = c;
*SCp->ptr = c;
SCp->ptr += 1;
SCp->this_residual -= 1;
if (SCp->this_residual == 0)
......
......@@ -49,7 +49,6 @@ fi
dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
if [ "$CONFIG_X86" = "y" -o "$CONFIG_PPC32" = "y" ]; then
# bool 'Support for Large Block Devices' CONFIG_LBD
define_bool CONFIG_LBD y
bool 'Support for Large Block Devices' CONFIG_LBD
fi
endmenu
......@@ -1878,7 +1878,7 @@ void generic_make_request(struct bio *bio)
*/
int submit_bio(int rw, struct bio *bio)
{
int count = bio_sectors(bio) >> 1;
int count = bio_sectors(bio);
BUG_ON(!bio->bi_end_io);
BIO_BUG_ON(!bio->bi_size);
......
......@@ -1033,3 +1033,24 @@ CONFIG_SCx200_GPIO
If compiled as a module, it will be called scx200_gpio.o.
Texas Instruments parallel link cable support
CONFIG_TIPAR
If you own a Texas Instruments graphing calculator and use a
parallel link cable, then you might be interested in this driver.
If you enable this driver, you will be able to communicate with
your calculator through a set of device nodes under /dev. The
main advantage of this driver is that you don't have to be root
to use this precise link cable (depending on the permissions on
the device nodes, though).
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called tipar.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
If you don't know what a parallel link cable is or what a Texas
Instruments graphing calculator is, then you probably don't need this
driver.
If unsure, say N.
\ No newline at end of file
......@@ -80,6 +80,7 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
bool ' Support for console on line printer' CONFIG_LP_CONSOLE
fi
dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
dep_tristate 'Texas Instruments parallel link cable support' CONFIG_TIPAR $CONFIG_PARPORT
fi
if [ "$CONFIG_PPC_PSERIES" = "y" ]; then
bool 'pSeries Hypervisor Virtual Console support' CONFIG_HVC_CONSOLE
......
......@@ -50,6 +50,7 @@ obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_PRINTER) += lp.o
obj-$(CONFIG_TIPAR) += tipar.o
obj-$(CONFIG_BUSMOUSE) += busmouse.o
obj-$(CONFIG_DTLK) += dtlk.o
......
This diff is collapsed.
......@@ -678,7 +678,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
*startstop = DRIVER(drive)->error(drive, "request sense failure", stat);
return 1;
} else if (rq->flags & REQ_PC) {
} else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
/* All other functions, except for READ. */
struct completion *wait = NULL;
pc = (struct packet_command *) rq->buffer;
......
......@@ -29,7 +29,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/iobuf.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <asm/page.h>
......
......@@ -31,7 +31,6 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/videodev.h>
#include <linux/iobuf.h>
#include <linux/pci.h>
#include <asm/scatterlist.h>
......
......@@ -18,8 +18,8 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/iobuf.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
......@@ -65,32 +65,31 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
return NULL;
}
struct scatterlist*
videobuf_iobuf_to_sg(struct kiobuf *iobuf)
struct scatterlist *
videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
{
struct scatterlist *sglist;
int i = 0;
sglist = kmalloc(sizeof(struct scatterlist) * iobuf->nr_pages,
GFP_KERNEL);
if (NULL == pages[0])
return NULL;
sglist = kmalloc(sizeof(*sglist) * nr_pages, GFP_KERNEL);
if (NULL == sglist)
return NULL;
memset(sglist,0,sizeof(struct scatterlist) * iobuf->nr_pages);
memset(sglist, 0, sizeof(*sglist) * nr_pages);
if (NULL == iobuf->maplist[0])
goto err;
if (PageHighMem(iobuf->maplist[0]))
if (PageHighMem(pages[0]))
/* DMA to highmem pages might not work */
goto err;
sglist[0].page = iobuf->maplist[0];
sglist[0].offset = iobuf->offset;
sglist[0].length = PAGE_SIZE - iobuf->offset;
for (i = 1; i < iobuf->nr_pages; i++) {
if (NULL == iobuf->maplist[i])
sglist[0].page = pages[0];
sglist[0].offset = offset;
sglist[0].length = PAGE_SIZE - offset;
for (i = 1; i < nr_pages; i++) {
if (NULL == pages[i])
goto err;
if (PageHighMem(iobuf->maplist[i]))
if (PageHighMem(pages[i]))
goto err;
sglist[i].page = iobuf->maplist[i];
sglist[i].page = pages[i];
sglist[i].length = PAGE_SIZE;
}
return sglist;
......@@ -100,6 +99,30 @@ videobuf_iobuf_to_sg(struct kiobuf *iobuf)
return NULL;
}
int videobuf_lock(struct page **pages, int nr_pages)
{
int i;
for (i = 0; i < nr_pages; i++)
if (TestSetPageLocked(pages[i]))
goto err;
return 0;
err:
while (i > 0)
unlock_page(pages[--i]);
return -EINVAL;
}
int videobuf_unlock(struct page **pages, int nr_pages)
{
int i;
for (i = 0; i < nr_pages; i++)
unlock_page(pages[i]);
return 0;
}
/* --------------------------------------------------------------------- */
int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
......@@ -113,14 +136,21 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
case PCI_DMA_TODEVICE: rw = WRITE; break;
default: BUG();
}
if (0 != (err = alloc_kiovec(1,&dma->iobuf)))
return err;
if (0 != (err = map_user_kiobuf(rw, dma->iobuf, data, size))) {
dprintk(1,"map_user_kiobuf: %d\n",err);
return err;
}
dma->nr_pages = dma->iobuf->nr_pages;
return 0;
dma->offset = data & PAGE_MASK;
dma->nr_pages = ((((data+size) & ~PAGE_MASK) -
(data & ~PAGE_MASK)) >> PAGE_SHIFT) +1;
dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*),
GFP_KERNEL);
if (NULL == dma->pages)
return -ENOMEM;
down_read(&current->mm->mmap_sem);
err = get_user_pages(current,current->mm,
data, dma->nr_pages,
rw == READ, 0, /* don't force */
dma->pages, NULL);
up_read(&current->mm->mmap_sem);
return err;
}
int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
......@@ -144,13 +174,15 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
if (0 == dma->nr_pages)
BUG();
if (dma->iobuf) {
if (0 != (err = lock_kiovec(1,&dma->iobuf,1))) {
dprintk(1,"lock_kiovec: %d\n",err);
if (dma->pages) {
if (0 != (err = videobuf_lock(dma->pages, dma->nr_pages))) {
dprintk(1,"videobuf_lock_pages: %d\n",err);
return err;
}
dma->sglist = videobuf_iobuf_to_sg(dma->iobuf);
dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
dma->offset);
}
if (dma->vmalloc) {
dma->sglist = videobuf_vmalloc_to_sg
(dma->vmalloc,dma->nr_pages);
......@@ -160,7 +192,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
return -ENOMEM;
}
dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages,
dma->direction);
dma->direction);
return 0;
}
......@@ -182,8 +214,8 @@ int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma)
kfree(dma->sglist);
dma->sglist = NULL;
dma->sglen = 0;
if (dma->iobuf)
unlock_kiovec(1,&dma->iobuf);
if (dma->pages)
videobuf_lock(dma->pages, dma->nr_pages);
return 0;
}
......@@ -192,11 +224,14 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
if (dma->sglen)
BUG();
if (dma->iobuf) {
unmap_kiobuf(dma->iobuf);
free_kiovec(1,&dma->iobuf);
dma->iobuf = NULL;
if (dma->pages) {
int i;
for (i=0; i < dma->nr_pages; i++)
page_cache_release(dma->pages[i]);
kfree(dma->pages);
dma->pages = NULL;
}
if (dma->vmalloc) {
vfree(dma->vmalloc);
dma->vmalloc = NULL;
......@@ -959,6 +994,7 @@ int videobuf_mmap_mapper(struct vm_area_struct *vma,
map->q = q;
vma->vm_ops = &videobuf_vm_ops;
vma->vm_flags |= VM_DONTEXPAND;
vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
vma->vm_private_data = map;
dprintk(1,"mmap %p: %08lx-%08lx pgoff %08lx bufs %d-%d\n",
map,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last);
......@@ -972,7 +1008,6 @@ int videobuf_mmap_mapper(struct vm_area_struct *vma,
/* --------------------------------------------------------------------- */
EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg);
EXPORT_SYMBOL_GPL(videobuf_iobuf_to_sg);
EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
......
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.
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.
......@@ -13,6 +13,7 @@ obj-$(CONFIG_SERIAL_CORE) += core.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
obj-$(CONFIG_SERIAL_8250_CS) += 8250_cs.o
obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o
obj-$(CONFIG_SERIAL_AMBA) += amba.o
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
......
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.
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.
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.
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.
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.
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.
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