- The TCP socket leak patch _really_ went in this time.
- get rid of more suser() checks in networking.. It's "capable(CAP_NET_ADMIN)".
- sparc updates
- alpha updates. Fast alpha xor for raid. AP1000 updates.
- Wonders never cease. digiboard driver updates. Christoph Lameter is BAAACK!
- SiS frame buffer driver updates. Can be used without a BIOS.
- nfsd interface cleanup.
- fix potential buffer overruns in get_partition_list. Remove
limitation of one page.
- floppy driver capability cleanups. Use "request_region()".
- handle dcache flushing when there are shared user mappings that
may be dirty.
- get rid of the "xxxx_ret()" user access macros. They are more complex than
just doing the return directly and they hide what's going on.
- fix up broken BIOSes that don't give unique ID's to different APICs
- make more of the drm drivers compile on other platforms and know
about the signal blocking issues.
- net/atm/mpoa_proc.c: user-space access thinko
- pcmcia: David Hinds: merge updates from 3.1.20
- pcmcia: non-ISA machines really shouldn't use ISA interrupts ;)
- ext2: truncate races and error code return fixes
- true shared signals for pthreads..
@@ -8,11+8,6 @@ The Digiboard Driver for Linux supports the following boards: switches) You can use up to 4 cards with this driver and it should work
on other architectures than intel also.
-In case you have problems with this version (1.6.1) of this driver, please
-email directly to me as I made the last update. It you have a report about
-running it on other architectures than intel, email me, so I can document
-it here.
-
A version of this driver has been taken by Digiboard to make a driver
software package which supports also PC/Xem cards and newer PCI cards
but it doesn't support the old PC/Xi cards and it isn't yet ported to
@@ -154,22+149,12 @@ Sources of Information ----------------------
Please contact digi directly digilnux@dgii.com. Forward any information of
-general interest to me.
+general interest to me so that I can include it on the webpage.
-Web page (mainly of historical interest): http://lameter.com/digi
+Web page: http://lameter.com/digi
Christoph Lameter (christoph@lameter.com) Aug 14, 2000.
-Supporting Tools
-----------------
-
-Some (old) tools and more detailed information can be found at
-ftp://lameter.com/digi
-
-The "ditty" tool described in the Digiboard Manuals for other Unixes
-is also available.
-
-
Device file creation
--------------------
@@ -655,10+655,12 @@ L: autofs@linux.kernel.org S: Maintained
KERNEL NFSD
-P: G. Allen Morris III
-M: gam3@acm.org
+P: Neil Brown
+M: neilb@cse.unsw.edu.au
L: nfs-devel@linux.kernel.org (Linux NFS)
-W: http://csua.berkeley.edu/~gam3/knfsd
+L: nfs@lists.sourceforge.net
+W: http://nfs.sourceforge.net/
+W: http://www.cse.unsw.edu.au/~neilb/oss/knfsd/
S: Maintained
LANMEDIA WAN CARD DRIVER
@@ -894,7+896,7 @@ PCMCIA SUBSYSTEM P: David Hinds
M: dhinds@zen.stanford.edu
L: linux-kernel@vger.kernel.org
-W: http://pcmcia.sourceforge.org
+W: http://pcmcia-cs.sourceforge.net
S: Maintained
PCNET32 NETWORK DRIVER
@@ -23,6+23,8 @@ have_mcpu_pca56 := $(shell if $(CC) -mcpu=pca56 -S -o /dev/null -xc /dev/null >
have_mcpu_ev6 := $(shell if $(CC) -mcpu=ev6 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+have_mcpu_ev67 := $(shell if $(CC) -mcpu=ev67 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+
# Turn on the proper cpu optimizations.
ifeq ($(have_mcpu),y)
# If GENERIC, make sure to turn off any instruction set extensions that
@@ -754,6+754,364 @@ cia_pci_clr_err(void) *(vip)CIA_IOC_CIA_ERR; /* re-read to force write. */
}
+static void
+cia_decode_pci_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
+{
+ static const char * const pci_cmd_desc[16] = {
+ "Interrupt Acknowledge", "Special Cycle", "I/O Read",
+ "I/O Write", "Reserved 0x4", "Reserved 0x5", "Memory Read",
+ "Memory Write", "Reserved 0x8", "Reserved 0x9",
+ "Configuration Read", "Configuration Write",
+ "Memory Read Multiple", "Dual Address Cycle",
+ "Memory Read Line", "Memory Write and Invalidate"
+ };
+
+ if (cia->cia_err & (CIA_ERR_COR_ERR
+ | CIA_ERR_UN_COR_ERR
+ | CIA_ERR_MEM_NEM
+ | CIA_ERR_PA_PTE_INV)) {
+ static const char * const window_desc[6] = {
+ "No window active", "Window 0 hit", "Window 1 hit",
+ "Window 2 hit", "Window 3 hit", "Monster window hit"
+ };
+
+ const char *window;
+ const char *cmd;
+ unsigned long addr, tmp;
+ int lock, dac;
+
+ cmd = pci_cmd_desc[cia->pci_err0 & 0x7];
+ lock = (cia->pci_err0 >> 4) & 1;
+ dac = (cia->pci_err0 >> 5) & 1;
+
+ tmp = (cia->pci_err0 >> 8) & 0x1F;
+ tmp = ffs(tmp);
+ window = window_desc[tmp];
+
+ addr = cia->pci_err1;
+ if (dac) {
+ tmp = *(vip)CIA_IOC_PCI_W_DAC & 0xFFUL;
+ addr |= tmp << 32;
+ }
+
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
+ printk(KERN_CRIT " DMA command: %s\n", cmd);
+ printk(KERN_CRIT " PCI address: %#010lx\n", addr);
+ printk(KERN_CRIT " %s, Lock: %d, DAC: %d\n",
+ window, lock, dac);
+ } else if (cia->cia_err & (CIA_ERR_PERR
+ | CIA_ERR_PCI_ADDR_PE
+ | CIA_ERR_RCVD_MAS_ABT
+ | CIA_ERR_RCVD_TAR_ABT
+ | CIA_ERR_IOA_TIMEOUT)) {
+ static const char * const master_st_desc[16] = {
+ "Idle", "Drive bus", "Address step cycle",
+ "Address cycle", "Data cycle", "Last read data cycle",
+ "Last write data cycle", "Read stop cycle",
+ "Write stop cycle", "Read turnaround cycle",
+ "Write turnaround cycle", "Reserved 0xB",
+ "Reserved 0xC", "Reserved 0xD", "Reserved 0xE",
+ "Unknown state"
+ };
+ static const char * const target_st_desc[16] = {
+ "Idle", "Busy", "Read data cycle", "Write data cycle",
+ "Read stop cycle", "Write stop cycle",
+ "Read turnaround cycle", "Write turnaround cycle",
+ "Read wait cycle", "Write wait cycle",
+ "Reserved 0xA", "Reserved 0xB", "Reserved 0xC",
+ "Reserved 0xD", "Reserved 0xE", "Unknown state"
+ };
+
+ const char *cmd;
+ const char *master, *target;
+ unsigned long addr, tmp;
+ int dac;
+
+ master = master_st_desc[(cia->pci_err0 >> 16) & 0xF];
+ target = target_st_desc[(cia->pci_err0 >> 20) & 0xF];
+ cmd = pci_cmd_desc[(cia->pci_err0 >> 24) & 0xF];
+ dac = (cia->pci_err0 >> 28) & 1;
+
+ addr = cia->pci_err2;
+ if (dac) {
+ tmp = *(volatile int *)CIA_IOC_PCI_W_DAC & 0xFFUL;
+ addr |= tmp << 32;
+ }
+
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
+ printk(KERN_CRIT " PCI command: %s\n", cmd);
+ printk(KERN_CRIT " Master state: %s, Target state: %s\n",
+ master, target);
+ printk(KERN_CRIT " PCI address: %#010lx, DAC: %d\n",
+ addr, dac);
+ } else {
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
+ printk(KERN_CRIT " Unknown PCI error\n");
+ printk(KERN_CRIT " PCI_ERR0 = %#08lx", cia->pci_err0);
+ printk(KERN_CRIT " PCI_ERR1 = %#08lx", cia->pci_err1);
+ printk(KERN_CRIT " PCI_ERR2 = %#08lx", cia->pci_err2);
+ }
+}
+
+static void
+cia_decode_mem_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
+{
+ unsigned long mem_port_addr;
+ unsigned long mem_port_mask;
+ const char *mem_port_cmd;
+ const char *seq_state;
+ const char *set_select;
+ unsigned long tmp;
+
+ /* If this is a DMA command, also decode the PCI bits. */
+ if ((cia->mem_err1 >> 20) & 1)
+ cia_decode_pci_error(cia, msg);
+ else
+ printk(KERN_CRIT "CIA machine check: %s\n", msg);
+
+ mem_port_addr = cia->mem_err0 & 0xfffffff0;
+ mem_port_addr |= (cia->mem_err1 & 0x83UL) << 32;
+
+ mem_port_mask = (cia->mem_err1 >> 12) & 0xF;
+
+ tmp = (cia->mem_err1 >> 8) & 0xF;
+ tmp |= ((cia->mem_err1 >> 20) & 1) << 4;
+ if ((tmp & 0x1E) == 0x06)
+ mem_port_cmd = "WRITE BLOCK or WRITE BLOCK LOCK";
+ else if ((tmp & 0x1C) == 0x08)
+ mem_port_cmd = "READ MISS or READ MISS MODIFY";
+ else if (tmp == 0x1C)
+ mem_port_cmd = "BC VICTIM";
+ else if ((tmp & 0x1E) == 0x0E)
+ mem_port_cmd = "READ MISS MODIFY";
+ else if ((tmp & 0x1C) == 0x18)
+ mem_port_cmd = "DMA READ or DMA READ MODIFY";
+ else if ((tmp & 0x1E) == 0x12)
+ mem_port_cmd = "DMA WRITE";
+ else
+ mem_port_cmd = "Unknown";
+
+ tmp = (cia->mem_err1 >> 16) & 0xF;
+ switch (tmp) {
+ case 0x0:
+ seq_state = "Idle";
+ break;
+ case 0x1:
+ seq_state = "DMA READ or DMA WRITE";
+ break;
+ case 0x2: case 0x3:
+ seq_state = "READ MISS (or READ MISS MODIFY) with victim";
+ break;
+ case 0x4: case 0x5: case 0x6:
+ seq_state = "READ MISS (or READ MISS MODIFY) with no victim";
+ break;
+ case 0x8: case 0x9: case 0xB:
+ seq_state = "Refresh";
+ break;
+ case 0xC:
+ seq_state = "Idle, waiting for DMA pending read";
+ break;
+ case 0xE: case 0xF:
+ seq_state = "Idle, ras precharge";
+ break;
+ default:
+ seq_state = "Unknown";
+ break;
+ }
+
+ tmp = (cia->mem_err1 >> 24) & 0x1F;
+ switch (tmp) {
+ case 0x00: set_select = "Set 0 selected"; break;
+ case 0x01: set_select = "Set 1 selected"; break;
+ case 0x02: set_select = "Set 2 selected"; break;
+ case 0x03: set_select = "Set 3 selected"; break;
+ case 0x04: set_select = "Set 4 selected"; break;
+ case 0x05: set_select = "Set 5 selected"; break;
+ case 0x06: set_select = "Set 6 selected"; break;
+ case 0x07: set_select = "Set 7 selected"; break;
+ case 0x08: set_select = "Set 8 selected"; break;
+ case 0x09: set_select = "Set 9 selected"; break;
+ case 0x0A: set_select = "Set A selected"; break;
+ case 0x0B: set_select = "Set B selected"; break;
+ case 0x0C: set_select = "Set C selected"; break;
+ case 0x0D: set_select = "Set D selected"; break;
+ case 0x0E: set_select = "Set E selected"; break;
+ case 0x0F: set_select = "Set F selected"; break;
+ case 0x10: set_select = "No set selected"; break;
+ case 0x1F: set_select = "Refresh cycle"; break;
+ default: set_select = "Unknown"; break;
+ }
+
+ printk(KERN_CRIT " Memory port command: %s\n", mem_port_cmd);
+ printk(KERN_CRIT " Memory port address: %#010lx, mask: %#lx\n",
+ mem_port_addr, mem_port_mask);
+ printk(KERN_CRIT " Memory sequencer state: %s\n", seq_state);
+ printk(KERN_CRIT " Memory set: %s\n", set_select);
+}
+
+static void
+cia_decode_ecc_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
+{
+ long syn;
+ long i;
+ const char *fmt;
+
+ cia_decode_mem_error(cia, msg);
+
+ syn = cia->cia_syn & 0xff;
+ if (syn == (syn & -syn)) {
+ fmt = KERN_CRIT " ECC syndrome %#x -- check bit %d\n";
+ i = ffs(syn) - 1;
+ } else {
+ static unsigned char const data_bit[64] = {
+ 0xCE, 0xCB, 0xD3, 0xD5,
+ 0xD6, 0xD9, 0xDA, 0xDC,
+ 0x23, 0x25, 0x26, 0x29,
+ 0x2A, 0x2C, 0x31, 0x34,
+ 0x0E, 0x0B, 0x13, 0x15,
+ 0x16, 0x19, 0x1A, 0x1C,
+ 0xE3, 0xE5, 0xE6, 0xE9,
+ 0xEA, 0xEC, 0xF1, 0xF4,
+ 0x4F, 0x4A, 0x52, 0x54,
+ 0x57, 0x58, 0x5B, 0x5D,
+ 0xA2, 0xA4, 0xA7, 0xA8,
+ 0xAB, 0xAD, 0xB0, 0xB5,
+ 0x8F, 0x8A, 0x92, 0x94,
+ 0x97, 0x98, 0x9B, 0x9D,
+ 0x62, 0x64, 0x67, 0x68,
+ 0x6B, 0x6D, 0x70, 0x75
+ };
+
+ for (i = 0; i < 64; ++i)
+ if (data_bit[i] == syn)
+ break;
+
+ if (i < 64)
+ fmt = KERN_CRIT " ECC syndrome %#x -- data bit %d\n";
+ else
+ fmt = KERN_CRIT " ECC syndrome %#x -- unknown bit\n";
+ }
+
+ printk (fmt, syn, i);
+}
+
+static void
+cia_decode_parity_error(struct el_CIA_sysdata_mcheck *cia)
+{
+ static const char * const cmd_desc[16] = {
+ "NOP", "LOCK", "FETCH", "FETCH_M", "MEMORY BARRIER",
+ "SET DIRTY", "WRITE BLOCK", "WRITE BLOCK LOCK",
+ "READ MISS0", "READ MISS1", "READ MISS MOD0",
+ "READ MISS MOD1", "BCACHE VICTIM", "Spare",
+ "READ MISS MOD STC0", "READ MISS MOD STC1"
+ };
+
+ unsigned long addr;
+ unsigned long mask;
+ const char *cmd;
+ int par;
+
+ addr = cia->cpu_err0 & 0xfffffff0;
+ addr |= (cia->cpu_err1 & 0x83UL) << 32;
+ cmd = cmd_desc[(cia->cpu_err1 >> 8) & 0xF];
+ mask = (cia->cpu_err1 >> 12) & 0xF;
+ par = (cia->cpu_err1 >> 21) & 1;
+
+ printk(KERN_CRIT "CIA machine check: System bus parity error\n");
+ printk(KERN_CRIT " Command: %s, Parity bit: %d\n", cmd, par);
+ printk(KERN_CRIT " Address: %#010lx, Mask: %#lx\n", addr, mask);
+}
+
+static int
+cia_decode_mchk(unsigned long la_ptr)
+{
+ struct el_common *com;
+ struct el_CIA_sysdata_mcheck *cia;
+ int which;
+
+ com = (void *)la_ptr;
+ cia = (void *)(la_ptr + com->sys_offset);
+
+ if ((cia->cia_err & CIA_ERR_VALID) == 0)
+ return 0;
+
+ which = cia->cia_err & 0xfff;
+ switch (ffs(which) - 1) {
+ case 0: /* CIA_ERR_COR_ERR */
+ cia_decode_ecc_error(cia, "Corrected ECC error");
+ break;
+ case 1: /* CIA_ERR_UN_COR_ERR */
+ cia_decode_ecc_error(cia, "Uncorrected ECC error");
+ break;
+ case 2: /* CIA_ERR_CPU_PE */
+ cia_decode_parity_error(cia);
+ break;
+ case 3: /* CIA_ERR_MEM_NEM */
+ cia_decode_mem_error(cia, "Access to nonexistent memory");
+ break;
+ case 4: /* CIA_ERR_PCI_SERR */
+ cia_decode_pci_error(cia, "PCI bus system error");
+ break;
+ case 5: /* CIA_ERR_PERR */
+ cia_decode_pci_error(cia, "PCI data parity error");
+ break;
+ case 6: /* CIA_ERR_PCI_ADDR_PE */
+ cia_decode_pci_error(cia, "PCI address parity error");
+ break;
+ case 7: /* CIA_ERR_RCVD_MAS_ABT */
+ cia_decode_pci_error(cia, "PCI master abort");
+ break;
+ case 8: /* CIA_ERR_RCVD_TAR_ABT */
+ cia_decode_pci_error(cia, "PCI target abort");
+ break;
+ case 9: /* CIA_ERR_PA_PTE_INV */
+ cia_decode_pci_error(cia, "PCI invalid PTE");
+ break;
+ case 10: /* CIA_ERR_FROM_WRT_ERR */
+ cia_decode_mem_error(cia, "Write to flash ROM attempted");
+ break;
+ case 11: /* CIA_ERR_IOA_TIMEOUT */
+ cia_decode_pci_error(cia, "I/O timeout");
+ break;
+ }
+
+ if (cia->cia_err & CIA_ERR_LOST_CORR_ERR)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "Correctable ECC error\n");
+ if (cia->cia_err & CIA_ERR_LOST_UN_CORR_ERR)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "Uncorrectable ECC error\n");
+ if (cia->cia_err & CIA_ERR_LOST_CPU_PE)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "System bus parity error\n");
+ if (cia->cia_err & CIA_ERR_LOST_MEM_NEM)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "Access to nonexistent memory\n");
+ if (cia->cia_err & CIA_ERR_LOST_PERR)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "PCI data parity error\n");
+ if (cia->cia_err & CIA_ERR_LOST_PCI_ADDR_PE)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "PCI address parity error\n");
+ if (cia->cia_err & CIA_ERR_LOST_RCVD_MAS_ABT)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "PCI master abort\n");
+ if (cia->cia_err & CIA_ERR_LOST_RCVD_TAR_ABT)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "PCI target abort\n");
+ if (cia->cia_err & CIA_ERR_LOST_PA_PTE_INV)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "PCI invalid PTE\n");
+ if (cia->cia_err & CIA_ERR_LOST_FROM_WRT_ERR)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "Write to flash ROM attempted\n");
+ if (cia->cia_err & CIA_ERR_LOST_IOA_TIMEOUT)
+ printk(KERN_CRIT "CIA lost machine check: "
+ "I/O timeout\n");
+
+ return 1;
+}
+
void
cia_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
@@ -769,30+1127,7 @@ cia_machine_check(unsigned long vector, unsigned long la_ptr, mb();
expected = mcheck_expected(0);
- if (!expected && vector == 0x660) {
- struct el_common *com;
- struct el_common_EV5_uncorrectable_mcheck *ev5;
- struct el_CIA_sysdata_mcheck *cia;
-
- com = (void *)la_ptr;
- ev5 = (void *)(la_ptr + com->proc_offset);
- cia = (void *)(la_ptr + com->sys_offset);
-
- if (com->code == 0x202) {
- printk(KERN_CRIT "CIA PCI machine check: code=%x\n"
- " cpu_err0=%08x cpu_err1=%08x cia_err=%08x\n"
- " cia_stat=%08x err_mask=%08x cia_syn=%08x\n"
- " mem_err0=%08x mem_err1=%08x\n"
- " pci_err0=%08x pci_err1=%08x pci_err2=%08x\n",
- (int) com->code,
- (int) cia->cpu_err0, (int) cia->cpu_err1,
- (int) cia->cia_err, (int) cia->cia_stat,
- (int) cia->err_mask, (int) cia->cia_syn,
- (int) cia->mem_err0, (int) cia->mem_err1,
- (int) cia->pci_err0, (int) cia->pci_err1,
- (int) cia->pci_err2);
- expected = 1;
- }
- }
+ if (!expected && vector == 0x660)
+ expected = cia_decode_mchk(la_ptr);
process_mcheck_info(vector, la_ptr, regs, "CIA", expected);
}
#include "proto.h"
#include "pci_impl.h"
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the I/O controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
+#undef DEBUG_IRONGATE /* define to enable verbose Irongate debug */
/*
* BIOS32-style PCI interface:
@@ -200,11+195,12 @@ struct pci_ops irongate_pci_ops = write_dword: irongate_write_config_dword
};
\f
-#if 0
+#ifdef DEBUG_IRONGATE
static void
irongate_register_dump(const char *function_name)
{
printk("%s: Irongate registers:\n"
+ "\tFunction 0:\n"
"\tdev_vendor\t0x%08x\n"
"\tstat_cmd\t0x%08x\n"
"\tclass\t\t0x%08x\n"
@@ -249,7+245,26 @@ irongate_register_dump(const char *function_name) "\tagpstat\t\t0x%08x\n"
"\tagpcmd\t\t0x%08x\n"
"\tagpva\t\t0x%08x\n"
- "\tagpmode\t\t0x%08x\n",
+ "\tagpmode\t\t0x%08x\n"
+
+ "\n\tFunction 1:\n"
+ "\tdev_vendor:\t0x%08x\n"
+ "\tcmd_status:\t0x%08x\n"
+ "\trevid_etc :\t0x%08x\n"
+ "\thtype_etc :\t0x%08x\n"
+ "\trsrvd0[0] :\t0x%08x\n"
+ "\trsrvd0[1] :\t0x%08x\n"
+ "\tbus_nmbers:\t0x%08x\n"
+ "\tio_baselim:\t0x%08x\n"
+ "\tmem_bselim:\t0x%08x\n"
+ "\tpf_baselib:\t0x%08x\n"
+ "\trsrvd1[0] :\t0x%08x\n"
+ "\trsrvd1[1] :\t0x%08x\n"
+ "\tio_baselim:\t0x%08x\n"
+ "\trsrvd2[0] :\t0x%08x\n"
+ "\trsrvd2[1] :\t0x%08x\n"
+ "\tinterrupt :\t0x%08x\n",
+
function_name,
IRONGATE0->dev_vendor,
IRONGATE0->stat_cmd,
@@ -295,7+310,23 @@ irongate_register_dump(const char *function_name) IRONGATE0->agpstat,
IRONGATE0->agpcmd,
IRONGATE0->agpva,
- IRONGATE0->agpmode);
+ IRONGATE0->agpmode,
+ IRONGATE1->dev_vendor,
+ IRONGATE1->stat_cmd,
+ IRONGATE1->class,
+ IRONGATE1->htype,
+ IRONGATE1->rsrvd0[0],
+ IRONGATE1->rsrvd0[1],
+ IRONGATE1->busnos,
+ IRONGATE1->io_baselim_regs,
+ IRONGATE1->mem_baselim,
+ IRONGATE1->pfmem_baselim,
+ IRONGATE1->rsrvd1[0],
+ IRONGATE1->rsrvd1[1],
+ IRONGATE1->io_baselim,
+ IRONGATE1->rsrvd2[0],
+ IRONGATE1->rsrvd2[1],
+ IRONGATE1->interrupt );
}
#else
#define irongate_register_dump(x)
@@ -501,10+501,6 @@ CONFIG_PCMCIA_SERIAL=y #
# Multimedia devices
#
-
-#
-# Video For Linux
-#
# CONFIG_VIDEO_DEV is not set
#
@@ -279,7+279,6 @@ static inline int save_i387_fsave( struct _fpstate *buf ) {
struct task_struct *tsk = current;
- unlazy_fpu( tsk );
tsk->thread.i387.fsave.status = tsk->thread.i387.fsave.swd;
if ( __copy_to_user( buf, &tsk->thread.i387.fsave,
sizeof(struct i387_fsave_struct) ) )
@@ -292,8+291,6 @@ static inline int save_i387_fxsave( struct _fpstate *buf ) struct task_struct *tsk = current;
int err = 0;
- unlazy_fpu( tsk );
-
if ( convert_fxsr_to_user( buf, &tsk->thread.i387.fxsave ) )
return -1;
@@ -982,7+982,10 @@ void disable_IO_APIC(void) static void __init setup_ioapic_ids_from_mpc (void)
{
struct IO_APIC_reg_00 reg_00;
+ unsigned long phys_id_present_map = phys_cpu_present_map;
int apic;
+ int i;
+ unsigned char old_id;
/*
* Set the IOAPIC ID to the value stored in the MPC table.
@@ -992,6+995,8 @@ static void __init setup_ioapic_ids_from_mpc (void) /* Read the register 0 value */
*(int *)®_00 = io_apic_read(apic, 0);
+ old_id = mp_ioapics[apic].mpc_apicid;
+
if (mp_ioapics[apic].mpc_apicid >= 0xf) {
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
apic, mp_ioapics[apic].mpc_apicid);
@@ -1001,21+1006,41 @@ static void __init setup_ioapic_ids_from_mpc (void) }
/*
+ * Sanity check, is the ID really free? Every APIC in a
+ * system must have a unique ID or we get lots of nice
+ * 'stuck on smp_invalidate_needed IPI wait' messages.
+ */
+ if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) {
+ printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+ apic, mp_ioapics[apic].mpc_apicid);
+ for (i = 0; i < 0xf; i++)
+ if (!(phys_id_present_map & (1 << i)))
+ break;
+ if (i >= 0xf)
+ panic("Max APIC ID exceeded!\n");
+ printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+ i);
+ phys_id_present_map |= 1 << i;
+ mp_ioapics[apic].mpc_apicid = i;
+ }
+
+ /*
+ * We need to adjust the IRQ routing table
+ * if the ID changed.
+ */
+ if (old_id != mp_ioapics[apic].mpc_apicid)
+ for (i = 0; i < mp_irq_entries; i++)
+ if (mp_irqs[i].mpc_dstapic == old_id)
+ mp_irqs[i].mpc_dstapic
+ = mp_ioapics[apic].mpc_apicid;
+
+ /*
* Read the right value from the MPC table and
* write it into the ID register.
*/
printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
mp_ioapics[apic].mpc_apicid);
- /*
- * Sanity check, is the ID really free? Every APIC in the
- * system must have a unique ID or we get lots of nice
- * 'stuck on smp_invalidate_needed IPI wait' messages.
- */
- if (phys_cpu_present_map & (1<<mp_ioapics[apic].mpc_apicid))
- panic("APIC ID %d already used",
- mp_ioapics[apic].mpc_apicid);
-
reg_00.ID = mp_ioapics[apic].mpc_apicid;
io_apic_write(apic, 0, *(int *)®_00);
@@ -682,7+682,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* FALLTHRU */
default:
- sigaddset(¤t->signal, signr);
+ sigaddset(¤t->pending.signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
do_exit(exit_code);
-/* $Id: irq.c,v 1.106 2000/08/05 10:48:40 davem Exp $
+/* $Id: irq.c,v 1.107 2000/08/26 02:42:28 anton Exp $
* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
* Sparc the IRQ's are basically 'cast in stone'
* and you are supposed to probe the prom's device
* Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1995 Pete A. Zaitcev (zaitcev@metabyte.com)
* Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
- * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
+ * Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com)
*/
#include <linux/config.h>
@@ -196,41+196,29 @@ void free_irq(unsigned int irq, void *dev_id) }
#ifdef CONFIG_SMP
-/* SMP interrupt locking on Sparc. */
/* Who has global_irq_lock. */
unsigned char global_irq_holder = NO_PROC_ID;
-/* This protects IRQ's. */
-spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
-
-/* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT(0);
-
void smp_show_backtrace_all_cpus(void);
void show_backtrace(void);
-#define MAXCOUNT 100000000
#define VERBOSE_DEBUG_IRQLOCK
+#define MAXCOUNT 100000000
static void show(char * str)
{
- int i;
int cpu = smp_processor_id();
+ int i;
printk("\n%s, CPU %d:\n", str, cpu);
- printk("irq: %d [ ", atomic_read(&global_irq_count));
-
- for (i = 0; i < NR_CPUS; i++) {
- printk("%d ", local_irq_count(i));
- }
- printk("]\n");
-
- printk("bh: %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0));
-
- for (i = 0; i < NR_CPUS; i++) {
- printk("%d ", local_bh_count(cpu));
- }
+ printk("irq: %d [ ", irqs_running());
+ for (i = 0; i < smp_num_cpus; i++)
+ printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]);
+ printk("]\nbh: %d [ ",
+ (spin_is_locked(&global_bh_lock) ? 1 : 0));
+ for (i = 0; i < smp_num_cpus; i++)
+ printk("%u ", local_bh_count(i));
printk("]\n");
#ifdef VERBOSE_DEBUG_IRQLOCK
@@ -240,48+228,11 @@ static void show(char * str) #endif
}
+
/*
* We have to allow irqs to arrive between __sti and __cli
*/
-#define SYNC_OTHER_CORES(x) udelay(x+1)
-
-static inline void wait_on_irq(int cpu)
-{
- int count = MAXCOUNT;
-
- for (;;) {
- /*
- * Wait until all interrupts are gone. Wait
- * for bottom half handlers unless we're
- * already executing in one..
- */
- if (!atomic_read(&global_irq_count)) {
- if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
- break;
- }
-
- /* Duh, we have to loop. Release the lock to avoid deadlocks */
- spin_unlock(&global_irq_lock);
-
- for (;;) {
- if (!--count) {
- show("wait_on_irq");
- count = ~0;
- }
- __sti();
- SYNC_OTHER_CORES(cpu);
- __cli();
- if (atomic_read(&global_irq_count))
- continue;
- if (spin_is_locked (&global_irq_lock))
- continue;
- if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
- continue;
- if (spin_trylock(&global_irq_lock))
- break;
- }
- }
-}
+#define SYNC_OTHER_CORES(x) barrier()
/*
* This is called when we want to synchronize with
@@ -292,8+243,7 @@ static inline void wait_on_irq(int cpu) */
void synchronize_irq(void)
{
- if (atomic_read(&global_irq_count)) {
- /* Stupid approach */
+ if (irqs_running()) {
cli();
sti();
}
@@ -301,32+251,37 @@ void synchronize_irq(void)
static inline void get_irqlock(int cpu)
{
- int count = MAXCOUNT;
+ int count;
- if (!spin_trylock(&global_irq_lock)) {
- /* do we already hold the lock? */
- if ((unsigned char) cpu == global_irq_holder)
- return;
- /* Uhhuh.. Somebody else got it. Wait.. */
- do {
- while (spin_is_locked(&global_irq_lock)) {
- if (!--count) {
- show("get_irqlock");
- count = ~0;
- }
- barrier();
+ if ((unsigned char)cpu == global_irq_holder)
+ return;
+
+ count = MAXCOUNT;
+again:
+ br_write_lock(BR_GLOBALIRQ_LOCK);
+ for (;;) {
+ spinlock_t *lock;
+
+ if (!irqs_running() &&
+ (local_bh_count(smp_processor_id()) || !spin_is_locked(&global_bh_lock)))
+ break;
+
+ br_write_unlock(BR_GLOBALIRQ_LOCK);
+ lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock;
+ while (irqs_running() ||
+ spin_is_locked(lock) ||
+ (!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) {
+ if (!--count) {
+ show("get_irqlock");
+ count = (~0 >> 1);
}
- } while (!spin_trylock(&global_irq_lock));
+ __sti();
+ SYNC_OTHER_CORES(cpu);
+ __cli();
+ }
+ goto again;
}
- /*
- * We also to make sure that nobody else is running
- * in an interrupt context.
- */
- wait_on_irq(cpu);
- /*
- * Ok, finally..
- */
global_irq_holder = cpu;
}
@@ -344,7+299,7 @@ static inline void get_irqlock(int cpu) */
void __global_cli(void)
{
- unsigned int flags;
+ unsigned long flags;
__save_flags(flags);
@@ -374,9+329,7 @@ void __global_sti(void) */
unsigned long __global_save_flags(void)
{
- int retval;
- int local_enabled = 0;
- unsigned long flags;
+ unsigned long flags, local_enabled, retval;
__save_flags(flags);
-/* $Id: sparc_ksyms.c,v 1.102 2000/08/05 10:48:40 davem Exp $
+/* $Id: sparc_ksyms.c,v 1.103 2000/08/26 02:42:28 anton Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -111,13+111,6 @@ EXPORT_SYMBOL_PRIVATE(_rw_read_enter); EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
#endif
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(__global_save_flags);
-EXPORT_SYMBOL(__global_restore_flags);
-EXPORT_SYMBOL(__global_sti);
-EXPORT_SYMBOL(__global_cli);
-#endif
-
/* rw semaphores */
EXPORT_SYMBOL_NOVERS(___down_read);
EXPORT_SYMBOL_NOVERS(___down_write);
@@ -137,14+130,17 @@ EXPORT_SYMBOL_PRIVATE(_change_bit); EXPORT_SYMBOL_PRIVATE(_set_le_bit);
EXPORT_SYMBOL_PRIVATE(_clear_le_bit);
-/* IRQ implementation. */
#ifdef CONFIG_SMP
+/* Kernel wide locking */
EXPORT_SYMBOL(kernel_flag);
+
+/* IRQ implementation. */
EXPORT_SYMBOL(global_irq_holder);
-EXPORT_SYMBOL(global_irq_lock);
-EXPORT_SYMBOL(global_bh_lock);
-EXPORT_SYMBOL(global_irq_count);
EXPORT_SYMBOL(synchronize_irq);
+EXPORT_SYMBOL(__global_cli);
+EXPORT_SYMBOL(__global_sti);
+EXPORT_SYMBOL(__global_save_flags);
+EXPORT_SYMBOL(__global_restore_flags);
#endif
EXPORT_SYMBOL(udelay);
-/* $Id: srmmu.c,v 1.221 2000/08/14 00:46:13 anton Exp $
+/* $Id: srmmu.c,v 1.222 2000/08/29 08:59:23 davem Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1323,8+1323,8 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma, mapping = file->f_dentry->d_inode->i_mapping;
offset = (address & PAGE_MASK) - vma->vm_start;
spin_lock(&mapping->i_shared_lock);
- vmaring = mapping->i_mmap;
- do {
+ vmaring = mapping->i_mmap_shared;
+ if (vmaring != NULL) do {
/* Do not mistake ourselves as another mapping. */
if(vmaring == vma)
continue;
-/* $Id: sun4c.c,v 1.198 2000/08/14 00:46:13 anton Exp $
+/* $Id: sun4c.c,v 1.199 2000/08/29 08:59:23 davem Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -2404,8+2404,8 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr
mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
spin_lock(&mapping->i_shared_lock);
- vmaring = mapping->i_mmap;
- do {
+ vmaring = mapping->i_mmap_shared;
+ if (vmaring != NULL) do {
unsigned long vaddr = vmaring->vm_start + offset;
unsigned long start;
-/* $Id: console.c,v 1.22 2000/02/08 20:24:23 davem Exp $
+/* $Id: console.c,v 1.23 2000/08/26 02:38:03 anton Exp $
* console.c: Routines that deal with sending and receiving IO
* to/from the current console device using the PROM.
*
@@ -30,7+30,7 @@ prom_nbgetchar(void) int i = -1;
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
case PROM_SUN4:
@@ -49,7+49,7 @@ prom_nbgetchar(void) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return i; /* Ugh, we could spin forever on unsupported proms ;( */
}
@@ -63,7+63,7 @@ prom_nbputchar(char c) unsigned long flags;
int i = -1;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
case PROM_SUN4:
@@ -82,7+82,7 @@ prom_nbputchar(char c) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return i; /* Ugh, we could spin forever on unsupported proms ;( */
}
@@ -125,10+125,10 @@ prom_query_input_device() return PROMDEV_I_UNK;
};
case PROM_V3:
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
if(prom_node_has_property(st_p, "keyboard"))
return PROMDEV_IKBD;
if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) {
@@ -174,10+174,10 @@ prom_query_output_device() break;
case PROM_V2:
case PROM_V3:
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
if (propl >= 0 && propl == sizeof("display") &&
strncmp("display", propb, sizeof("display")) == 0)
-/* $Id: devmap.c,v 1.6 1998/03/09 14:04:23 jj Exp $
+/* $Id: devmap.c,v 1.7 2000/08/26 02:38:03 anton Exp $
* promdevmap.c: Map device/IO areas to virtual addresses.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -29,13+29,13 @@ prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes) unsigned long flags;
char *ret;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0;
else
ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr,
num_bytes);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
@@ -46,9+46,9 @@ prom_unmapio(char *vaddr, unsigned int num_bytes) unsigned long flags;
if(num_bytes == 0x0) return;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
(*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return;
}
-/* $Id: devops.c,v 1.12 2000/01/29 01:09:12 anton Exp $
+/* $Id: devops.c,v 1.13 2000/08/26 02:38:03 anton Exp $
* devops.c: Device operations using the PROM.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -21,7+21,7 @@ prom_devopen(char *dstr) {
int handle;
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
handle = (*(romvec->pv_v0devops.v0_devopen))(dstr);
@@ -36,7+36,7 @@ prom_devopen(char *dstr) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return handle;
}
prom_devclose(int dhandle)
{
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
(*(romvec->pv_v0devops.v0_devclose))(dhandle);
@@ -59,7+59,7 @@ prom_devclose(int dhandle) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return 0;
}
prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
{
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
(*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo);
@@ -83,7+83,7 @@ prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return;
}
-/* $Id: misc.c,v 1.17 1998/07/21 10:36:22 jj Exp $
+/* $Id: misc.c,v 1.18 2000/08/26 02:38:03 anton Exp $
* misc.c: Miscellaneous prom functions that don't belong
* anywhere else.
*
extern void restore_current(void);
+spinlock_t prom_lock = SPIN_LOCK_UNLOCKED;
+
/* Reset and reboot the machine with the command 'bcommand'. */
void
prom_reboot(char *bcommand)
{
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
(*(romvec->pv_reboot))(bcommand);
/* Never get here. */
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
}
/* Forth evaluate the expression contained in 'fstring'. */
@@ -34,13+36,13 @@ prom_feval(char *fstring) unsigned long flags;
if(!fstring || fstring[0] == 0)
return;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
if(prom_vers == PROM_V0)
(*(romvec->pv_fortheval.v0_eval))(strlen(fstring), fstring);
else
(*(romvec->pv_fortheval.v2_eval))(fstring);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
}
/* We want to do this more nicely some day. */
@@ -66,10+68,10 @@ prom_cmdline(void) prom_palette (1);
#endif
install_obp_ticker();
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
(*(romvec->pv_abort))();
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
install_linux_ticker();
#ifdef CONFIG_SUN_AUXIO
TURN_ON_LED;
@@ -88,11+90,11 @@ prom_halt(void) {
unsigned long flags;
again:
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
(*(romvec->pv_halt))();
/* Never get here. */
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
goto again; /* PROM is out to get me -DaveM */
}
-/* $Id: mp.c,v 1.11 2000/01/29 01:09:12 anton Exp $
+/* $Id: mp.c,v 1.12 2000/08/26 02:38:03 anton Exp $
* mp.c: OpenBoot Prom Multiprocessor support routines. Don't call
* these on a UP or else you will halt and catch fire. ;)
*
@@ -25,7+25,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha int ret;
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
@@ -37,7+37,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
@@ -51,7+51,7 @@ prom_stopcpu(int cpunode) int ret;
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
@@ -63,7+63,7 @@ prom_stopcpu(int cpunode) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
@@ -77,7+77,7 @@ prom_idlecpu(int cpunode) int ret;
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
@@ -89,7+89,7 @@ prom_idlecpu(int cpunode) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
@@ -103,7+103,7 @@ prom_restartcpu(int cpunode) int ret;
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
@@ -115,7+115,7 @@ prom_restartcpu(int cpunode) break;
};
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
-/* $Id: segment.c,v 1.6 1998/03/09 14:04:27 jj Exp $
+/* $Id: segment.c,v 1.7 2000/08/26 02:38:03 anton Exp $
* segment.c: Prom routine to map segments in other contexts before
* a standalone is completely mapped. This is for sun4 and
* sun4c architectures only.
prom_putsegment(int ctx, unsigned long vaddr, int segment)
{
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
(*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return;
}
-/* $Id: tree.c,v 1.25 1998/09/17 11:04:58 jj Exp $
+/* $Id: tree.c,v 1.26 2000/08/26 02:38:03 anton Exp $
* tree.c: Basic device tree traversal/scanning for the Linux
* prom library.
*
@@ -26,10+26,10 @@ int __prom_getchild(int node) unsigned long flags;
int cnode;
- save_and_cli(flags);
+ spin_lock_irqsave(&prom_lock, flags);
cnode = prom_nodeops->no_child(node);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return cnode;
}
@@ -57,10+57,10 @@ int __prom_getsibling(int node) unsigned long flags;
int cnode;
- save_and_cli(flags);
+ spin_lock_irqsave(&prom_lock, flags);
cnode = prom_nodeops->no_nextnode(node);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return cnode;
}
@@ -93,10+93,10 @@ int prom_getproplen(int node, char *prop) if((!node) || (!prop))
return -1;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
ret = prom_nodeops->no_proplen(node, prop);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
@@ -113,10+113,10 @@ int prom_getproperty(int node, char *prop, char *buffer, int bufsize) if((plen > bufsize) || (plen == 0) || (plen == -1))
return -1;
/* Ok, things seem all right. */
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
ret = prom_nodeops->no_getprop(node, prop, buffer);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
@@ -226,10+226,10 @@ char * __prom_nextprop(int node, char * oprop) unsigned long flags;
char *prop;
- save_and_cli(flags);
+ spin_lock_irqsave(&prom_lock, flags);
prop = prom_nodeops->no_nextprop(node, oprop);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return prop;
}
@@ -325,10+325,10 @@ int prom_setprop(int node, char *pname, char *value, int size)
if(size == 0) return 0;
if((pname == 0) || (value == 0)) return 0;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
ret = prom_nodeops->no_setprop(node, pname, value, size);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
@@ -337,10+337,10 @@ int prom_inst2pkg(int inst) int node;
unsigned long flags;
- save_flags(flags); cli();
+ spin_lock_irqsave(&prom_lock, flags);
node = (*romvec->pv_v2devops.v2_inst2pkg)(inst);
restore_current();
- restore_flags(flags);
+ spin_unlock_irqrestore(&prom_lock, flags);
if (node == -1) return 0;
return node;
}
-/* $Id: irq.c,v 1.91 2000/08/05 10:48:40 davem Exp $
+/* $Id: irq.c,v 1.92 2000/08/26 02:42:28 anton Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -608,7+608,7 @@ again: spin_is_locked(lock) ||
(!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) {
if (!--count) {
- show("wait_on_irq");
+ show("get_irqlock");
count = (~0 >> 1);
}
__sti();
-/* $Id: sys_sparc.c,v 1.45 2000/07/30 23:12:24 davem Exp $
+/* $Id: sys_sparc.c,v 1.46 2000/08/29 07:01:54 davem Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -398,13+398,18 @@ asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, return -EINVAL;
if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) {
if (old_p) {
- if (!current->thread.utraps)
- put_user_ret(NULL, old_p, -EFAULT);
- else
- put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT);
+ if (!current->thread.utraps) {
+ if (put_user(NULL, old_p))
+ return -EFAULT;
+ } else {
+ if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p))
+ return -EFAULT;
+ }
+ }
+ if (old_d) {
+ if (put_user(NULL, old_d))
+ return -EFAULT;
}
- if (old_d)
- put_user_ret(NULL, old_d, -EFAULT);
return 0;
}
if (!current->thread.utraps) {
@@ -431,11+436,14 @@ asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, UT_TRAP_INSTRUCTION_31*sizeof(long));
}
}
- if (old_p)
- put_user_ret((utrap_handler_t)(current->thread.utraps[type]),
- old_p, -EFAULT);
- if (old_d)
- put_user_ret(NULL, old_d, -EFAULT);
+ if (old_p) {
+ if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p))
+ return -EFAULT;
+ }
+ if (old_d) {
+ if (put_user(NULL, old_d))
+ return -EFAULT;
+ }
current->thread.utraps[type] = (long)new_p;
return 0;
-/* $Id: fs.c,v 1.22 2000/07/28 12:15:02 davem Exp $
+/* $Id: fs.c,v 1.23 2000/08/29 07:01:54 davem Exp $
* fs.c: fs related syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -612,20+612,25 @@ asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg) case SOL_F_SETLKW: cmd = F_SETLKW; break;
}
- get_user_ret (f.l_type, &((struct sol_flock *)A(arg))->l_type, -EFAULT);
- __get_user_ret (f.l_whence, &((struct sol_flock *)A(arg))->l_whence, -EFAULT);
- __get_user_ret (f.l_start, &((struct sol_flock *)A(arg))->l_start, -EFAULT);
- __get_user_ret (f.l_len, &((struct sol_flock *)A(arg))->l_len, -EFAULT);
- __get_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT);
+ if (get_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) ||
+ __get_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) ||
+ __get_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) ||
+ __get_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) ||
+ __get_user (f.l_pid, &((struct sol_flock *)A(arg))->l_sysid))
+ return -EFAULT;
+
set_fs(KERNEL_DS);
ret = sys_fcntl(fd, cmd, (unsigned long)&f);
set_fs(old_fs);
- __put_user_ret (f.l_type, &((struct sol_flock *)A(arg))->l_type, -EFAULT);
- __put_user_ret (f.l_whence, &((struct sol_flock *)A(arg))->l_whence, -EFAULT);
- __put_user_ret (f.l_start, &((struct sol_flock *)A(arg))->l_start, -EFAULT);
- __put_user_ret (f.l_len, &((struct sol_flock *)A(arg))->l_len, -EFAULT);
- __put_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_pid, -EFAULT);
- __put_user_ret (0, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT);
+
+ if (__put_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) ||
+ __put_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) ||
+ __put_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) ||
+ __put_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) ||
+ __put_user (f.l_pid, &((struct sol_flock *)A(arg))->l_pid) ||
+ __put_user (0, &((struct sol_flock *)A(arg))->l_sysid))
+ return -EFAULT;
+
return ret;
}
case SOL_F_FREESP:
@@ -634,7+639,9 @@ asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg) int (*sys_newftruncate)(unsigned int, unsigned long)=
(int (*)(unsigned int, unsigned long))SYS(ftruncate);
- get_user_ret(length, &((struct sol_flock*)A(arg))->l_start, -EFAULT);
+ if (get_user(length, &((struct sol_flock*)A(arg))->l_start))
+ return -EFAULT;
+
return sys_newftruncate(fd, length);
}
};
-/* $Id: misc.c,v 1.29 2000/08/14 23:50:31 anton Exp $
+/* $Id: misc.c,v 1.30 2000/08/29 07:01:54 davem Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -139,12+139,14 @@ asmlinkage int solaris_brk(u32 brk) int i, len = (countfrom) ? \
((sizeof(to) > sizeof(from) ? \
sizeof(from) : sizeof(to))) : sizeof(to); \
- copy_to_user_ret(to, from, len, -EFAULT); \
+ if (copy_to_user(to, from, len)) \
+ return -EFAULT; \
if (dotchop) \
for (p=from,i=0; *p && *p != '.' && --len; p++,i++); \
else \
i = len - 1; \
- __put_user_ret('\0', (char *)(to+i), -EFAULT); \
+ if (__put_user('\0', (char *)(to+i))) \
+ return -EFAULT; \
}
struct sol_uname {
@@ -297,10+299,13 @@ asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count) }
len = strlen(r) + 1;
if (count < len) {
- copy_to_user_ret((char *)A(buf), r, count - 1, -EFAULT);
- __put_user_ret(0, (char *)A(buf) + count - 1, -EFAULT);
- } else
- copy_to_user_ret((char *)A(buf), r, len, -EFAULT);
+ if (copy_to_user((char *)A(buf), r, count - 1) ||
+ __put_user(0, (char *)A(buf) + count - 1))
+ return -EFAULT;
+ } else {
+ if (copy_to_user((char *)A(buf), r, len))
+ return -EFAULT;
+ }
return len;
}
-/* $Id: signal.c,v 1.5 1997/12/15 15:04:59 jj Exp $
+/* $Id: signal.c,v 1.6 2000/08/29 07:01:54 davem Exp $
* signal.c: Signal emulation for Solaris
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -368,9+368,13 @@ asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options) if (info) {
struct sol_siginfo *s = (struct sol_siginfo *)A(info);
- if (get_user (status, (unsigned int *)A(info))) return -EFAULT;
- __put_user_ret (SOLARIS_SIGCLD, &s->si_signo, -EFAULT);
- __put_user_ret (ret, &s->_data._proc._pid, -EFAULT);
+ if (get_user (status, (unsigned int *)A(info)))
+ return -EFAULT;
+
+ if (__put_user (SOLARIS_SIGCLD, &s->si_signo) ||
+ __put_user (ret, &s->_data._proc._pid))
+ return -EFAULT;
+
switch (status & 0xff) {
case 0: ret = SOLARIS_CLD_EXITED;
status = (status >> 8) & 0xff;
@@ -390,8+394,10 @@ asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options) status = linux_to_solaris_signals[status & 0x7f];
break;
}
- __put_user_ret (ret, &s->si_code, -EFAULT);
- __put_user_ret (status, &s->_data._proc._pdata._cld._status, -EFAULT);
+
+ if (__put_user (ret, &s->si_code) ||
+ __put_user (status, &s->_data._proc._pdata._cld._status))
+ return -EFAULT;
}
return 0;
}
* being used to store jiffies, which are unsigned longs).
*/
+/*
+ * 2000/08/28 -- Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * - get rid of check_region
+ * - s/suser/capable/
+ */
+
#define FLOPPY_SANITY_CHECK
#undef FLOPPY_SILENT_DCL_CLEAR
@@ -3497,7+3503,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
/* permission checks */
if (((cmd & 0x40) && !(filp->f_mode & 2)) ||
- ((cmd & 0x80) && !suser()))
+ ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
return -EPERM;
/* copyin */
@@ -4299,23+4305,14 @@ static int floppy_grab_irq_and_dma(void)
for (fdc=0; fdc< N_FDC; fdc++){
if (FDCS->address != -1){
- if (check_region(FDCS->address, 6) < 0 ||
- check_region(FDCS->address+7, 1) < 0) {
+ if (!request_region(FDCS->address, 6, "floppy")) {
DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address);
- fd_free_irq();
- fd_free_dma();
- while(--fdc >= 0) {
- release_region(FDCS->address, 6);
- release_region(FDCS->address+7, 1);
- }
- MOD_DEC_USE_COUNT;
- spin_lock_irqsave(&floppy_usage_lock, flags);
- usage_count--;
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
- return -1;
+ goto cleanup1;
+ }
+ if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
+ DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + 7);
+ goto cleanup2;
}
- request_region(FDCS->address, 6, "floppy");
- request_region(FDCS->address+7, 1, "floppy DIR");
/* address + 6 is reserved, and may be taken by IDE.
* Unfortunately, Adaptec doesn't know this :-(, */
}
@@ -4339,6+4336,20 @@ static int floppy_grab_irq_and_dma(void) fdc = 0;
irqdma_allocated = 1;
return 0;
+cleanup2:
+ release_region(FDCS->address, 6);
+cleanup1:
+ fd_free_irq();
+ fd_free_dma();
+ while(--fdc >= 0) {
+ release_region(FDCS->address, 6);
+ release_region(FDCS->address + 7, 1);
+ }
+ MOD_DEC_USE_COUNT;
+ spin_lock_irqsave(&floppy_usage_lock, flags);
+ usage_count--;
+ spin_unlock_irqrestore(&floppy_usage_lock, flags);
+ return -1;
}
static void floppy_release_irq_and_dma(void)
@@ -1406,6+1406,818 @@ XORBLOCK_TEMPLATE(SPARC) }
#endif /* __sparc_v[78]__ */
+#ifdef __alpha__
+/*
+ * High speed xor_block operation for RAID4/5 pipelined for Alpha EV5.
+ * There is a second version using EV6 prefetch instructions.
+ *
+ * Copyright (C) 2000 Richard Henderson (rth@redhat.com)
+ */
+
+XORBLOCK_TEMPLATE(alpha)
+{
+ long lines = bh_ptr[0]->b_size / sizeof (long) / 8;
+ long *d = (long *) bh_ptr[0]->b_data;
+ long *s1 = (long *) bh_ptr[1]->b_data;
+ long *s2, *s3, *s4;
+
+ if (count == 2) goto two_blocks;
+
+ s2 = (long *) bh_ptr[2]->b_data;
+ if (count == 3) goto three_blocks;
+
+ s3 = (long *) bh_ptr[3]->b_data;
+ if (count == 4) goto four_blocks;
+
+ s4 = (long *) bh_ptr[4]->b_data;
+ goto five_blocks;
+
+two_blocks:
+asm volatile ("
+ .align 4
+2:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,8(%0)
+ ldq $3,8(%1)
+
+ ldq $4,16(%0)
+ ldq $5,16(%1)
+ ldq $6,24(%0)
+ ldq $7,24(%1)
+
+ ldq $16,32(%0)
+ ldq $17,32(%1)
+ ldq $18,40(%0)
+ ldq $19,40(%1)
+
+ ldq $20,48(%0)
+ ldq $21,48(%1)
+ ldq $22,56(%0)
+ xor $0,$1,$0 # 7 cycles from $1 load
+
+ ldq $23,56(%1)
+ xor $2,$3,$2
+ stq $0,0(%0)
+ xor $4,$5,$4
+
+ stq $2,8(%0)
+ xor $6,$7,$6
+ stq $4,16(%0)
+ xor $16,$17,$16
+
+ stq $6,24(%0)
+ xor $18,$19,$18
+ stq $16,32(%0)
+ xor $20,$21,$20
+
+ stq $18,40(%0)
+ xor $22,$23,$22
+ stq $20,48(%0)
+ subq %2,1,%2
+
+ stq $22,56(%0)
+ addq %0,64,%0
+ addq %1,64,%1
+ bgt %2,2b"
+ : "=r"(d), "=r"(s1), "=r"(lines)
+ : "0"(d), "1"(s1), "2"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23");
+ return;
+
+three_blocks:
+asm volatile ("
+ .align 4
+3:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,0(%2)
+ ldq $3,8(%0)
+
+ ldq $4,8(%1)
+ ldq $6,16(%0)
+ ldq $7,16(%1)
+ ldq $17,24(%0)
+
+ ldq $18,24(%1)
+ ldq $20,32(%0)
+ ldq $21,32(%1)
+ ldq $5,8(%2)
+
+ ldq $16,16(%2)
+ ldq $19,24(%2)
+ ldq $22,32(%2)
+ nop
+
+ xor $0,$1,$1 # 8 cycles from $0 load
+ xor $3,$4,$4 # 6 cycles from $4 load
+ xor $6,$7,$7 # 6 cycles from $7 load
+ xor $17,$18,$18 # 5 cycles from $18 load
+
+ xor $1,$2,$2 # 9 cycles from $2 load
+ xor $20,$21,$21 # 5 cycles from $21 load
+ stq $2,0(%0)
+ xor $4,$5,$5 # 6 cycles from $5 load
+
+ stq $5,8(%0)
+ xor $7,$16,$16 # 7 cycles from $16 load
+ stq $16,16(%0)
+ xor $18,$19,$19 # 7 cycles from $19 load
+
+ stq $19,24(%0)
+ xor $21,$22,$22 # 7 cycles from $22 load
+ stq $22,32(%0)
+ nop
+
+ ldq $0,40(%0)
+ ldq $1,40(%1)
+ ldq $3,48(%0)
+ ldq $4,48(%1)
+
+ ldq $6,56(%0)
+ ldq $7,56(%1)
+ ldq $2,40(%2)
+ ldq $5,48(%2)
+
+ ldq $16,56(%2)
+ xor $0,$1,$1 # 4 cycles from $1 load
+ xor $3,$4,$4 # 5 cycles from $4 load
+ xor $6,$7,$7 # 5 cycles from $7 load
+
+ xor $1,$2,$2 # 4 cycles from $2 load
+ xor $4,$5,$5 # 5 cycles from $5 load
+ stq $2,40(%0)
+ xor $7,$16,$16 # 4 cycles from $16 load
+
+ stq $5,48(%0)
+ subq %3,1,%3
+ stq $16,56(%0)
+ addq %2,64,%2
+
+ addq %1,64,%1
+ addq %0,64,%0
+ bgt %3,3b"
+ : "=r"(d), "=r"(s1), "=r"(s2), "=r"(lines)
+ : "0"(d), "1"(s1), "2"(s2), "3"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22");
+ return;
+
+four_blocks:
+asm volatile ("
+ .align 4
+4:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,0(%2)
+ ldq $3,0(%3)
+
+ ldq $4,8(%0)
+ ldq $5,8(%1)
+ ldq $6,8(%2)
+ ldq $7,8(%3)
+
+ ldq $16,16(%0)
+ ldq $17,16(%1)
+ ldq $18,16(%2)
+ ldq $19,16(%3)
+
+ ldq $20,24(%0)
+ xor $0,$1,$1 # 6 cycles from $1 load
+ ldq $21,24(%1)
+ xor $2,$3,$3 # 6 cycles from $3 load
+
+ ldq $0,24(%2)
+ xor $1,$3,$3
+ ldq $1,24(%3)
+ xor $4,$5,$5 # 7 cycles from $5 load
+
+ stq $3,0(%0)
+ xor $6,$7,$7
+ xor $16,$17,$17 # 7 cycles from $17 load
+ xor $5,$7,$7
+
+ stq $7,8(%0)
+ xor $18,$19,$19 # 7 cycles from $19 load
+ ldq $2,32(%0)
+ xor $17,$19,$19
+
+ ldq $3,32(%1)
+ ldq $4,32(%2)
+ ldq $5,32(%3)
+ xor $20,$21,$21 # 8 cycles from $21 load
+
+ ldq $6,40(%0)
+ ldq $7,40(%1)
+ ldq $16,40(%2)
+ ldq $17,40(%3)
+
+ stq $19,16(%0)
+ xor $0,$1,$1 # 9 cycles from $1 load
+ xor $2,$3,$3 # 5 cycles from $3 load
+ xor $21,$1,$1
+
+ ldq $18,48(%0)
+ xor $4,$5,$5 # 5 cycles from $5 load
+ ldq $19,48(%1)
+ xor $3,$5,$5
+
+ ldq $20,48(%2)
+ ldq $21,48(%3)
+ ldq $0,56(%0)
+ ldq $1,56(%1)
+
+ ldq $2,56(%2)
+ xor $6,$7,$7 # 8 cycles from $6 load
+ ldq $3,56(%3)
+ xor $16,$17,$17 # 8 cycles from $17 load
+
+ xor $7,$17,$17
+ xor $18,$19,$19 # 5 cycles from $19 load
+ xor $20,$21,$21 # 5 cycles from $21 load
+ xor $19,$21,$21
+
+ stq $1,24(%0)
+ xor $0,$1,$1 # 5 cycles from $1 load
+ stq $5,32(%0)
+ xor $2,$3,$3 # 4 cycles from $3 load
+
+ stq $17,40(%0)
+ xor $1,$3,$3
+ stq $21,48(%0)
+ subq %4,1,%4
+
+ stq $3,56(%0)
+ addq %3,64,%3
+ addq %2,64,%2
+ addq %1,64,%1
+
+ addq %0,64,%0
+ bgt %4,4b"
+ : "=r"(d), "=r"(s1), "=r"(s2), "=r"(s3), "=r"(lines)
+ : "0"(d), "1"(s1), "2"(s2), "3"(s3), "4"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21");
+ return;
+
+five_blocks:
+asm volatile ("
+ ldq %0,0(%6)
+ ldq %1,8(%6)
+ ldq %2,16(%6)
+ ldq %3,24(%6)
+ ldq %4,32(%6)
+ ldq %0,%7(%0)
+ ldq %1,%7(%1)
+ ldq %2,%7(%2)
+ ldq %3,%7(%3)
+ ldq %4,%7(%4)
+ .align 4
+5:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,0(%2)
+ ldq $3,0(%3)
+
+ ldq $4,0(%4)
+ ldq $5,8(%0)
+ ldq $6,8(%1)
+ ldq $7,8(%2)
+
+ ldq $16,8(%3)
+ ldq $17,8(%4)
+ ldq $18,16(%0)
+ ldq $19,16(%1)
+
+ ldq $20,16(%2)
+ xor $0,$1,$1 # 6 cycles from $1 load
+ ldq $21,16(%3)
+ xor $2,$3,$3 # 6 cycles from $3 load
+
+ ldq $0,16(%4)
+ xor $1,$3,$3
+ ldq $1,24(%0)
+ xor $3,$4,$4 # 7 cycles from $4 load
+
+ stq $4,0(%0)
+ xor $5,$6,$6 # 7 cycles from $6 load
+ xor $7,$16,$16 # 7 cycles from $16 load
+ xor $6,$17,$17 # 7 cycles from $17 load
+
+ ldq $2,24(%1)
+ xor $16,$17,$17
+ ldq $3,24(%2)
+ xor $18,$19,$19 # 8 cycles from $19 load
+
+ stq $17,8(%0)
+ xor $19,$20,$20 # 8 cycles from $20 load
+ ldq $4,24(%3)
+ xor $21,$0,$0 # 7 cycles from $0 load
+
+ ldq $5,24(%4)
+ xor $20,$0,$0
+ ldq $6,32(%0)
+ ldq $7,32(%1)
+
+ stq $0,16(%0)
+ xor $1,$2,$2 # 6 cycles from $2 load
+ ldq $16,32(%2)
+ xor $3,$4,$4 # 4 cycles from $4 load
+
+ ldq $17,32(%3)
+ xor $2,$4,$4
+ ldq $18,32(%4)
+ ldq $19,40(%0)
+
+ ldq $20,40(%1)
+ ldq $21,40(%2)
+ ldq $0,40(%3)
+ xor $4,$5,$5 # 7 cycles from $5 load
+
+ stq $5,24(%0)
+ xor $6,$7,$7 # 7 cycles from $7 load
+ ldq $1,40(%4)
+ ldq $2,48(%0)
+
+ ldq $3,48(%1)
+ xor $7,$16,$16 # 7 cycles from $16 load
+ ldq $4,48(%2)
+ xor $17,$18,$18 # 6 cycles from $18 load
+
+ ldq $5,48(%3)
+ xor $16,$18,$18
+ ldq $6,48(%4)
+ xor $19,$20,$20 # 7 cycles from $20 load
+
+ stq $18,32(%0)
+ xor $20,$21,$21 # 8 cycles from $21 load
+ ldq $7,56(%0)
+ xor $0,$1,$1 # 6 cycles from $1 load
+
+ ldq $16,56(%1)
+ ldq $17,56(%2)
+ ldq $18,56(%3)
+ ldq $19,56(%4)
+
+ xor $21,$1,$1
+ xor $2,$3,$3 # 9 cycles from $3 load
+ xor $3,$4,$4 # 9 cycles from $4 load
+ xor $5,$6,$6 # 8 cycles from $6 load
+
+ unop
+ xor $4,$6,$6
+ xor $7,$16,$16 # 7 cycles from $16 load
+ xor $17,$18,$18 # 6 cycles from $18 load
+
+ stq $6,48(%0)
+ xor $16,$18,$18
+ subq %5,1,%5
+ xor $18,$19,$19 # 8 cycles from $19 load
+
+ stq $19,56(%0)
+ addq %4,64,%4
+ addq %3,64,%3
+ addq %2,64,%2
+
+ addq %1,64,%1
+ addq %0,64,%0
+ bgt %5,5b"
+ : "=&r"(d), "=&r"(s1), "=&r"(s2), "=&r"(s3), "=r"(s4), "=r"(lines)
+ /* ARG! We've run out of asm arguments! We've got to reload
+ all those pointers we just loaded. */
+ : "r"(bh_ptr), "i" (&((struct buffer_head *)0)->b_data), "5"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21");
+ return;
+}
+
+#define prefetch(base, ofs) \
+ asm("ldq $31,%2(%0)" : "=r"(base) : "0"(base), "i"(ofs))
+
+XORBLOCK_TEMPLATE(alpha_prefetch)
+{
+ long lines = bh_ptr[0]->b_size / sizeof (long) / 8;
+ long *d = (long *) bh_ptr[0]->b_data;
+ long *s1 = (long *) bh_ptr[1]->b_data;
+ long *s2, *s3, *s4;
+ long p;
+
+ p = count == 2;
+ prefetch(d, 0);
+ prefetch(s1, 0);
+ prefetch(d, 64);
+ prefetch(s1, 64);
+ prefetch(d, 128);
+ prefetch(s1, 128);
+ prefetch(d, 192);
+ prefetch(s1, 192);
+ if (p) goto two_blocks;
+
+ s2 = (long *) bh_ptr[2]->b_data;
+ p = count == 3;
+ prefetch(s2, 0);
+ prefetch(s2, 64);
+ prefetch(s2, 128);
+ prefetch(s2, 192);
+ if (p) goto three_blocks;
+
+ s3 = (long *) bh_ptr[3]->b_data;
+ p = count == 4;
+ prefetch(s3, 0);
+ prefetch(s3, 64);
+ prefetch(s3, 128);
+ prefetch(s3, 192);
+ if (p) goto four_blocks;
+
+ s4 = (long *) bh_ptr[4]->b_data;
+ prefetch(s4, 0);
+ prefetch(s4, 64);
+ prefetch(s4, 128);
+ prefetch(s4, 192);
+ goto five_blocks;
+
+two_blocks:
+asm volatile ("
+ .align 4
+2:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,8(%0)
+ ldq $3,8(%1)
+
+ ldq $4,16(%0)
+ ldq $5,16(%1)
+ ldq $6,24(%0)
+ ldq $7,24(%1)
+
+ ldq $16,32(%0)
+ ldq $17,32(%1)
+ ldq $18,40(%0)
+ ldq $19,40(%1)
+
+ ldq $20,48(%0)
+ ldq $21,48(%1)
+ ldq $22,56(%0)
+ ldq $23,56(%1)
+
+ ldq $31,256(%0)
+ xor $0,$1,$0 # 8 cycles from $1 load
+ ldq $31,256(%1)
+ xor $2,$3,$2
+
+ stq $0,0(%0)
+ xor $4,$5,$4
+ stq $2,8(%0)
+ xor $6,$7,$6
+
+ stq $4,16(%0)
+ xor $16,$17,$16
+ stq $6,24(%0)
+ xor $18,$19,$18
+
+ stq $16,32(%0)
+ xor $20,$21,$20
+ stq $18,40(%0)
+ xor $22,$23,$22
+
+ stq $20,48(%0)
+ subq %2,1,%2
+ stq $22,56(%0)
+ addq %0,64,%0
+
+ addq %1,64,%1
+ bgt %2,2b"
+ : "=r"(d), "=r"(s1), "=r"(lines)
+ : "0"(d), "1"(s1), "2"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23");
+ return;
+
+three_blocks:
+asm volatile ("
+ .align 4
+3:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,0(%2)
+ ldq $3,8(%0)
+
+ ldq $4,8(%1)
+ ldq $6,16(%0)
+ ldq $7,16(%1)
+ ldq $17,24(%0)
+
+ ldq $18,24(%1)
+ ldq $20,32(%0)
+ ldq $21,32(%1)
+ ldq $5,8(%2)
+
+ ldq $16,16(%2)
+ ldq $19,24(%2)
+ ldq $22,32(%2)
+ nop
+
+ xor $0,$1,$1 # 8 cycles from $0 load
+ xor $3,$4,$4 # 7 cycles from $4 load
+ xor $6,$7,$7 # 6 cycles from $7 load
+ xor $17,$18,$18 # 5 cycles from $18 load
+
+ xor $1,$2,$2 # 9 cycles from $2 load
+ xor $20,$21,$21 # 5 cycles from $21 load
+ stq $2,0(%0)
+ xor $4,$5,$5 # 6 cycles from $5 load
+
+ stq $5,8(%0)
+ xor $7,$16,$16 # 7 cycles from $16 load
+ stq $16,16(%0)
+ xor $18,$19,$19 # 7 cycles from $19 load
+
+ stq $19,24(%0)
+ xor $21,$22,$22 # 7 cycles from $22 load
+ stq $22,32(%0)
+ nop
+
+ ldq $0,40(%0)
+ ldq $1,40(%1)
+ ldq $3,48(%0)
+ ldq $4,48(%1)
+
+ ldq $6,56(%0)
+ ldq $7,56(%1)
+ ldq $2,40(%2)
+ ldq $5,48(%2)
+
+ ldq $16,56(%2)
+ ldq $31,256(%0)
+ ldq $31,256(%1)
+ ldq $31,256(%2)
+
+ xor $0,$1,$1 # 6 cycles from $1 load
+ xor $3,$4,$4 # 5 cycles from $4 load
+ xor $6,$7,$7 # 5 cycles from $7 load
+ xor $1,$2,$2 # 4 cycles from $2 load
+
+ xor $4,$5,$5 # 5 cycles from $5 load
+ xor $7,$16,$16 # 4 cycles from $16 load
+ stq $2,40(%0)
+ subq %3,1,%3
+
+ stq $5,48(%0)
+ addq %2,64,%2
+ stq $16,56(%0)
+ addq %1,64,%1
+
+ addq %0,64,%0
+ bgt %3,3b"
+ : "=r"(d), "=r"(s1), "=r"(s2), "=r"(lines)
+ : "0"(d), "1"(s1), "2"(s2), "3"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22");
+ return;
+
+four_blocks:
+asm volatile ("
+ .align 4
+4:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,0(%2)
+ ldq $3,0(%3)
+
+ ldq $4,8(%0)
+ ldq $5,8(%1)
+ ldq $6,8(%2)
+ ldq $7,8(%3)
+
+ ldq $16,16(%0)
+ ldq $17,16(%1)
+ ldq $18,16(%2)
+ ldq $19,16(%3)
+
+ ldq $20,24(%0)
+ xor $0,$1,$1 # 6 cycles from $1 load
+ ldq $21,24(%1)
+ xor $2,$3,$3 # 6 cycles from $3 load
+
+ ldq $0,24(%2)
+ xor $1,$3,$3
+ ldq $1,24(%3)
+ xor $4,$5,$5 # 7 cycles from $5 load
+
+ stq $3,0(%0)
+ xor $6,$7,$7
+ xor $16,$17,$17 # 7 cycles from $17 load
+ xor $5,$7,$7
+
+ stq $7,8(%0)
+ xor $18,$19,$19 # 7 cycles from $19 load
+ ldq $2,32(%0)
+ xor $17,$19,$19
+
+ ldq $3,32(%1)
+ ldq $4,32(%2)
+ ldq $5,32(%3)
+ xor $20,$21,$21 # 8 cycles from $21 load
+
+ ldq $6,40(%0)
+ ldq $7,40(%1)
+ ldq $16,40(%2)
+ ldq $17,40(%3)
+
+ stq $19,16(%0)
+ xor $0,$1,$1 # 9 cycles from $1 load
+ xor $2,$3,$3 # 5 cycles from $3 load
+ xor $21,$1,$1
+
+ ldq $18,48(%0)
+ xor $4,$5,$5 # 5 cycles from $5 load
+ ldq $19,48(%1)
+ xor $3,$5,$5
+
+ ldq $20,48(%2)
+ ldq $21,48(%3)
+ ldq $0,56(%0)
+ ldq $1,56(%1)
+
+ ldq $2,56(%2)
+ xor $6,$7,$7 # 8 cycles from $6 load
+ ldq $3,56(%3)
+ xor $16,$17,$17 # 8 cycles from $17 load
+
+ ldq $31,256(%0)
+ xor $7,$17,$17
+ ldq $31,256(%1)
+ xor $18,$19,$19 # 6 cycles from $19 load
+
+ ldq $31,256(%2)
+ xor $20,$21,$21 # 6 cycles from $21 load
+ ldq $31,256(%3)
+ xor $19,$21,$21
+
+ stq $1,24(%0)
+ xor $0,$1,$1 # 7 cycles from $1 load
+ stq $5,32(%0)
+ xor $2,$3,$3 # 6 cycles from $3 load
+
+ stq $17,40(%0)
+ xor $1,$3,$3
+ stq $21,48(%0)
+ subq %4,1,%4
+
+ stq $3,56(%0)
+ addq %3,64,%3
+ addq %2,64,%2
+ addq %1,64,%1
+
+ addq %0,64,%0
+ bgt %4,4b"
+ : "=r"(d), "=r"(s1), "=r"(s2), "=r"(s3), "=r"(lines)
+ : "0"(d), "1"(s1), "2"(s2), "3"(s3), "4"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21");
+ return;
+
+five_blocks:
+asm volatile ("
+ ldq %0,0(%6)
+ ldq %1,8(%6)
+ ldq %2,16(%6)
+ ldq %3,24(%6)
+ ldq %4,32(%6)
+ ldq %0,%7(%0)
+ ldq %1,%7(%1)
+ ldq %2,%7(%2)
+ ldq %3,%7(%3)
+ ldq %4,%7(%4)
+ .align 4
+5:
+ ldq $0,0(%0)
+ ldq $1,0(%1)
+ ldq $2,0(%2)
+ ldq $3,0(%3)
+
+ ldq $4,0(%4)
+ ldq $5,8(%0)
+ ldq $6,8(%1)
+ ldq $7,8(%2)
+
+ ldq $16,8(%3)
+ ldq $17,8(%4)
+ ldq $18,16(%0)
+ ldq $19,16(%1)
+
+ ldq $20,16(%2)
+ xor $0,$1,$1 # 6 cycles from $1 load
+ ldq $21,16(%3)
+ xor $2,$3,$3 # 6 cycles from $3 load
+
+ ldq $0,16(%4)
+ xor $1,$3,$3
+ ldq $1,24(%0)
+ xor $3,$4,$4 # 7 cycles from $4 load
+
+ stq $4,0(%0)
+ xor $5,$6,$6 # 7 cycles from $6 load
+ xor $7,$16,$16 # 7 cycles from $16 load
+ xor $6,$17,$17 # 7 cycles from $17 load
+
+ ldq $2,24(%1)
+ xor $16,$17,$17
+ ldq $3,24(%2)
+ xor $18,$19,$19 # 8 cycles from $19 load
+
+ stq $17,8(%0)
+ xor $19,$20,$20 # 8 cycles from $20 load
+ ldq $4,24(%3)
+ xor $21,$0,$0 # 7 cycles from $0 load
+
+ ldq $5,24(%4)
+ xor $20,$0,$0
+ ldq $6,32(%0)
+ ldq $7,32(%1)
+
+ stq $0,16(%0)
+ xor $1,$2,$2 # 6 cycles from $2 load
+ ldq $16,32(%2)
+ xor $3,$4,$4 # 4 cycles from $4 load
+
+ ldq $17,32(%3)
+ xor $2,$4,$4
+ ldq $18,32(%4)
+ ldq $19,40(%0)
+
+ ldq $20,40(%1)
+ ldq $21,40(%2)
+ ldq $0,40(%3)
+ xor $4,$5,$5 # 7 cycles from $5 load
+
+ stq $5,24(%0)
+ xor $6,$7,$7 # 7 cycles from $7 load
+ ldq $1,40(%4)
+ ldq $2,48(%0)
+
+ ldq $3,48(%1)
+ xor $7,$16,$16 # 7 cycles from $16 load
+ ldq $4,48(%2)
+ xor $17,$18,$18 # 6 cycles from $18 load
+
+ ldq $5,48(%3)
+ xor $16,$18,$18
+ ldq $6,48(%4)
+ xor $19,$20,$20 # 7 cycles from $20 load
+
+ stq $18,32(%0)
+ xor $20,$21,$21 # 8 cycles from $21 load
+ ldq $7,56(%0)
+ xor $0,$1,$1 # 6 cycles from $1 load
+
+ ldq $16,56(%1)
+ ldq $17,56(%2)
+ ldq $18,56(%3)
+ ldq $19,56(%4)
+
+ ldq $31,256(%0)
+ xor $21,$1,$1
+ ldq $31,256(%1)
+ xor $2,$3,$3 # 9 cycles from $3 load
+
+ ldq $31,256(%2)
+ xor $3,$4,$4 # 9 cycles from $4 load
+ ldq $31,256(%3)
+ xor $5,$6,$6 # 8 cycles from $6 load
+
+ ldq $31,256(%4)
+ xor $4,$6,$6
+ xor $7,$16,$16 # 7 cycles from $16 load
+ xor $17,$18,$18 # 6 cycles from $18 load
+
+ stq $6,48(%0)
+ xor $16,$18,$18
+ subq %5,1,%5
+ xor $18,$19,$19 # 8 cycles from $19 load
+
+ stq $19,56(%0)
+ addq %4,64,%4
+ addq %3,64,%3
+ addq %2,64,%2
+
+ addq %1,64,%1
+ addq %0,64,%0
+ bgt %5,5b"
+ : "=&r"(d), "=&r"(s1), "=&r"(s2), "=&r"(s3), "=r"(s4), "=r"(lines)
+ /* ARG! We've run out of asm arguments! We've got to reload
+ all those pointers we just loaded. */
+ : "r"(bh_ptr), "i" (&((struct buffer_head *)0)->b_data), "5"(lines)
+ : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$16", "$17", "$18", "$19", "$20", "$21");
+ return;
+}
+
+#undef prefetch
+
+#endif /* __alpha__ */
+
#ifndef __sparc_v9__
/*
@@ -1815,9+2627,22 @@ static inline void pick_fastest_function(void) }
#ifdef CONFIG_X86_XMM
if (cpu_has_xmm) {
+ /* we force the use of the KNI xor block because it
+ can write around l2. we may also be able
+ to load into the l1 only depending on how
+ the cpu deals with a load to a line that is
+ being prefetched.
+ */
fastest = &t_xor_block_pIII_kni;
}
#endif
+#ifdef __alpha__
+ if (implver() == IMPLVER_EV6) {
+ /* Force the use of alpha_prefetch if EV6, as it
+ is significantly faster in the cold cache case. */
+ fastest = &t_xor_block_alpha_prefetch;
+ }
+#endif
xor_block = fastest->xor_block;
printk( "using fastest function: %s (%d.%03d MB/sec)\n", fastest->name,
fastest->speed / 1000, fastest->speed % 1000);
@@ -1854,27+2679,23 @@ void calibrate_xor_block(void) if (cpu_has_xmm) {
printk(KERN_INFO
"raid5: KNI detected, trying cache-avoiding KNI checksum routine\n");
- /* we force the use of the KNI xor block because it
- can write around l2. we may also be able
- to load into the l1 only depending on how
- the cpu deals with a load to a line that is
- being prefetched.
- */
xor_speed(&t_xor_block_pIII_kni,&b1,&b2);
}
#endif /* CONFIG_X86_XMM */
#ifdef __i386__
-
if (md_cpu_has_mmx()) {
printk(KERN_INFO
"raid5: MMX detected, trying high-speed MMX checksum routines\n");
xor_speed(&t_xor_block_pII_mmx,&b1,&b2);
xor_speed(&t_xor_block_p5_mmx,&b1,&b2);
}
-
#endif /* __i386__ */
-
+
+#ifdef __alpha__
+ xor_speed(&t_xor_block_alpha,&b1,&b2);
+ xor_speed(&t_xor_block_alpha_prefetch,&b1,&b2);
+#endif
xor_speed(&t_xor_block_8regs,&b1,&b2);
xor_speed(&t_xor_block_32regs,&b1,&b2);
@@ -292,10+292,10 @@ MODULE_PARM(check_media_type, "i");
/* These are used to simplify getting data in from and back to user land */
#define IOCTL_IN(arg, type, in) \
- copy_from_user_ret(&in, (type *) arg, sizeof in, -EFAULT)
+ copy_from_user(&in, (type *) arg, sizeof in)
#define IOCTL_OUT(arg, type, out) \
- copy_to_user_ret((type *) arg, &out, sizeof out, -EFAULT)
+ copy_to_user((type *) arg, &out, sizeof out)
/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in
a lot of places. This macro makes the code more clear. */
@@ -1463,7+1463,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
if (!(cdo->capability & CDC_MULTI_SESSION))
return -ENOSYS;
- IOCTL_IN(arg, struct cdrom_multisession, ms_info);
+ if (IOCTL_IN(arg, struct cdrom_multisession, ms_info))
+ return -EFAULT;
requested_format = ms_info.addr_format;
if (!((requested_format == CDROM_MSF) ||
(requested_format == CDROM_LBA)))
@@ -1473,7+1474,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return ret;
sanitize_format(&ms_info.addr, &ms_info.addr_format,
requested_format);
- IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
+ if (IOCTL_OUT(arg, struct cdrom_multisession, ms_info))
+ return -EFAULT;
cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
return 0;
}
@@ -1632,7+1634,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return -ENOSYS;
if ((ret=cdo->get_mcn(cdi, &mcn)))
return ret;
- IOCTL_OUT(arg, struct cdrom_mcn, mcn);
+ if (IOCTL_OUT(arg, struct cdrom_mcn, mcn))
+ return -EFAULT;
cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
return 0;
}
@@ -1717,7+1720,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO))
return -ENOSYS;
/* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/
- IOCTL_IN(arg, struct cdrom_subchnl, q);
+ if (IOCTL_IN(arg, struct cdrom_subchnl, q))
+ return -EFAULT;
requested = q.cdsc_format;
if (!((requested == CDROM_MSF) ||
(requested == CDROM_LBA)))
@@ -1728,7+1732,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, back = q.cdsc_format; /* local copy */
sanitize_format(&q.cdsc_absaddr, &back, requested);
sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
- IOCTL_OUT(arg, struct cdrom_subchnl, q);
+ if (IOCTL_OUT(arg, struct cdrom_subchnl, q))
+ return -EFAULT;
/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
return 0;
}
@@ -1737,10+1742,12 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO))
return -ENOSYS;
/* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
- IOCTL_IN(arg, struct cdrom_tochdr, header);
+ if (IOCTL_IN(arg, struct cdrom_tochdr, header))
+ return -EFAULT;
if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
return ret;
- IOCTL_OUT(arg, struct cdrom_tochdr, header);
+ if (IOCTL_OUT(arg, struct cdrom_tochdr, header))
+ return -EFAULT;
/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
return 0;
}
@@ -1750,7+1757,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO))
return -ENOSYS;
/* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
- IOCTL_IN(arg, struct cdrom_tocentry, entry);
+ if (IOCTL_IN(arg, struct cdrom_tocentry, entry))
+ return -EFAULT;
requested_format = entry.cdte_format;
if (!((requested_format == CDROM_MSF) ||
(requested_format == CDROM_LBA)))
@@ -1761,7+1769,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return ret;
sanitize_format(&entry.cdte_addr,
&entry.cdte_format, requested_format);
- IOCTL_OUT(arg, struct cdrom_tocentry, entry);
+ if (IOCTL_OUT(arg, struct cdrom_tocentry, entry))
+ return -EFAULT;
/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
return 0;
}
@@ -1770,7+1779,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
- IOCTL_IN(arg, struct cdrom_msf, msf);
+ if (IOCTL_IN(arg, struct cdrom_msf, msf))
+ return -EFAULT;
return cdo->audio_ioctl(cdi, cmd, &msf);
}
case CDROMPLAYTRKIND: {
@@ -1778,7+1788,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
- IOCTL_IN(arg, struct cdrom_ti, ti);
+ if (IOCTL_IN(arg, struct cdrom_ti, ti))
+ return -EFAULT;
CHECKAUDIO;
return cdo->audio_ioctl(cdi, cmd, &ti);
}
@@ -1787,7+1798,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_PLAY_AUDIO))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n");
- IOCTL_IN(arg, struct cdrom_volctrl, volume);
+ if (IOCTL_IN(arg, struct cdrom_volctrl, volume))
+ return -EFAULT;
return cdo->audio_ioctl(cdi, cmd, &volume);
}
case CDROMVOLREAD: {
@@ -1797,7+1809,8 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n");
if ((ret=cdo->audio_ioctl(cdi, cmd, &volume)))
return ret;
- IOCTL_OUT(arg, struct cdrom_volctrl, volume);
+ if (IOCTL_OUT(arg, struct cdrom_volctrl, volume))
+ return -EFAULT;
return 0;
}
case CDROMSTART:
@@ -1894,7+1907,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, blocksize = CD_FRAMESIZE_RAW0;
break;
}
- IOCTL_IN(arg, struct cdrom_msf, msf);
+ if (IOCTL_IN(arg, struct cdrom_msf, msf))
+ return -EFAULT;
lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0);
/* FIXME: we need upper bound checking, too!! */
if (lba < 0)
@@ -1933,7+1947,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, struct cdrom_read_audio ra;
int lba, frames;
- IOCTL_IN(arg, struct cdrom_read_audio, ra);
+ if (IOCTL_IN(arg, struct cdrom_read_audio, ra))
+ return -EFAULT;
if (ra.addr_format == CDROM_MSF)
lba = msf_to_lba(ra.addr.msf.minute,
@@ -1975,7+1990,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMSUBCHNL: {
struct cdrom_subchnl q;
u_char requested, back;
- IOCTL_IN(arg, struct cdrom_subchnl, q);
+ if (IOCTL_IN(arg, struct cdrom_subchnl, q))
+ return -EFAULT;
requested = q.cdsc_format;
if (!((requested == CDROM_MSF) ||
(requested == CDROM_LBA)))
@@ -1986,7+2002,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, back = q.cdsc_format; /* local copy */
sanitize_format(&q.cdsc_absaddr, &back, requested);
sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
- IOCTL_OUT(arg, struct cdrom_subchnl, q);
+ if (IOCTL_OUT(arg, struct cdrom_subchnl, q))
+ return -EFAULT;
/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
return 0;
}
@@ -1994,7+2011,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, struct cdrom_ti ti;
cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
- IOCTL_IN(arg, struct cdrom_ti, ti);
+ if (IOCTL_IN(arg, struct cdrom_ti, ti))
+ return -EFAULT;
cgc.cmd[0] = GPCMD_PLAY_AUDIO_TI;
cgc.cmd[4] = ti.cdti_trk0;
@@ -2006,7+2024,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMPLAYMSF: {
struct cdrom_msf msf;
cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
- IOCTL_IN(arg, struct cdrom_msf, msf);
+ if (IOCTL_IN(arg, struct cdrom_msf, msf))
+ return -EFAULT;
cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
cgc.cmd[3] = msf.cdmsf_min0;
cgc.cmd[4] = msf.cdmsf_sec0;
@@ -2020,7+2039,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMPLAYBLK: {
struct cdrom_blk blk;
cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n");
- IOCTL_IN(arg, struct cdrom_blk, blk);
+ if (IOCTL_IN(arg, struct cdrom_blk, blk))
+ return -EFAULT;
cgc.cmd[0] = GPCMD_PLAY_AUDIO_10;
cgc.cmd[2] = (blk.from >> 24) & 0xff;
cgc.cmd[3] = (blk.from >> 16) & 0xff;
@@ -2038,7+2058,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned short offset;
cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n");
- IOCTL_IN(arg, struct cdrom_volctrl, volctrl);
+ if (IOCTL_IN(arg, struct cdrom_volctrl, volctrl))
+ return -EFAULT;
cgc.buffer = buffer;
cgc.buflen = 24;
@@ -2064,7+2085,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, volctrl.channel1 = buffer[offset+11];
volctrl.channel2 = buffer[offset+13];
volctrl.channel3 = buffer[offset+15];
- IOCTL_OUT(arg, struct cdrom_volctrl, volctrl);
+ if (IOCTL_OUT(arg, struct cdrom_volctrl, volctrl))
+ return -EFAULT;
return 0;
}
@@ -2130,10+2152,12 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, if (!CDROM_CAN(CDC_DVD))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n");
- IOCTL_IN(arg, dvd_authinfo, ai);
+ if (IOCTL_IN(arg, dvd_authinfo, ai))
+ return -EFAULT;
if ((ret = dvd_do_auth (cdi, &ai)))
return ret;
- IOCTL_OUT(arg, dvd_authinfo, ai);
+ if (IOCTL_OUT(arg, dvd_authinfo, ai))
+ return -EFAULT;
return 0;
}
@@ -2143,7+2167,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, if (!CDROM_CAN(CDC_GENERIC_PACKET))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n");
- IOCTL_IN(arg, struct cdrom_generic_command, cgc);
+ if (IOCTL_IN(arg, struct cdrom_generic_command, cgc))
+ return -EFAULT;
copy = !!cgc.buflen;
userbuf = cgc.buffer;
cgc.buffer = NULL;
@@ -2190,7+2215,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n");
if ((ret = cdrom_get_next_writable(dev, &next)))
return ret;
- IOCTL_OUT(arg, long, next);
+ if (IOCTL_OUT(arg, long, next))
+ return -EFAULT;
return 0;
}
case CDROM_LAST_WRITTEN: {
@@ -2198,7+2224,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n");
if ((ret = cdrom_get_last_written(dev, &last)))
return ret;
- IOCTL_OUT(arg, long, last);
+ if (IOCTL_OUT(arg, long, last))
+ return -EFAULT;
return 0;
}
} /* switch */
@@ -95,7+95,8 @@ int drm_agp_info(struct inode *inode, struct file *filp, unsigned int cmd, info.id_vendor = kern->device->vendor;
info.id_device = kern->device->device;
- copy_to_user_ret((drm_agp_info_t *)arg, &info, sizeof(info), -EFAULT);
+ if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info)))
+ return -EFAULT;
return 0;
}
@@ -134,8+135,8 @@ int drm_agp_enable(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dev->agp->acquired || !drm_agp.enable) return -EINVAL;
- copy_from_user_ret(&mode, (drm_agp_mode_t *)arg, sizeof(mode),
- -EFAULT);
+ if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
+ return -EFAULT;
dev->agp->mode = mode.mode;
(*drm_agp.enable)(mode.mode);
@@ -155,8+156,8 @@ int drm_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long pages;
u32 type;
if (!dev->agp->acquired) return -EINVAL;
- copy_from_user_ret(&request, (drm_agp_buffer_t *)arg, sizeof(request),
- -EFAULT);
+ if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
+ return -EFAULT;
if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
return -ENOMEM;
@@ -212,8+213,8 @@ int drm_agp_unbind(struct inode *inode, struct file *filp, unsigned int cmd, drm_agp_mem_t *entry;
if (!dev->agp->acquired) return -EINVAL;
- copy_from_user_ret(&request, (drm_agp_binding_t *)arg, sizeof(request),
- -EFAULT);
+ if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
+ return -EFAULT;
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
return -EINVAL;
if (!entry->bound) return -EINVAL;
@@ -231,8+232,8 @@ int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd, int page;
if (!dev->agp->acquired || !drm_agp.bind_memory) return -EINVAL;
- copy_from_user_ret(&request, (drm_agp_binding_t *)arg, sizeof(request),
- -EFAULT);
+ if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
+ return -EFAULT;
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
return -EINVAL;
if (entry->bound) return -EINVAL;
@@ -253,8+254,8 @@ int drm_agp_free(struct inode *inode, struct file *filp, unsigned int cmd, drm_agp_mem_t *entry;
if (!dev->agp->acquired) return -EINVAL;
- copy_from_user_ret(&request, (drm_agp_buffer_t *)arg, sizeof(request),
- -EFAULT);
+ if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
+ return -EFAULT;
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
return -EINVAL;
if (entry->bound) drm_unbind_agp(entry->memory);
@@ -137,7+137,8 @@ int drm_getmagic(struct inode *inode, struct file *filp, unsigned int cmd, }
DRM_DEBUG("%u\n", auth.magic);
- copy_to_user_ret((drm_auth_t *)arg, &auth, sizeof(auth), -EFAULT);
+ if (copy_to_user((drm_auth_t *)arg, &auth, sizeof(auth)))
+ return -EFAULT;
return 0;
}
@@ -149,7+150,8 @@ int drm_authmagic(struct inode *inode, struct file *filp, unsigned int cmd, drm_auth_t auth;
drm_file_t *file;
- copy_from_user_ret(&auth, (drm_auth_t *)arg, sizeof(auth), -EFAULT);
+ if (copy_from_user(&auth, (drm_auth_t *)arg, sizeof(auth)))
+ return -EFAULT;
DRM_DEBUG("%u\n", auth.magic);
if ((file = drm_find_file(dev, auth.magic))) {
file->authenticated = 1;
@@ -133,12+133,13 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd, dev->maplist[dev->map_count-1] = map;
up(&dev->struct_sem);
- copy_to_user_ret((drm_map_t *)arg, map, sizeof(*map), -EFAULT);
+ if (copy_to_user((drm_map_t *)arg, map, sizeof(*map)))
+ return -EFAULT;
if (map->type != _DRM_SHM) {
- copy_to_user_ret(&((drm_map_t *)arg)->handle,
+ if (copy_to_user(&((drm_map_t *)arg)->handle,
&map->offset,
- sizeof(map->offset),
- -EFAULT);
+ sizeof(map->offset)))
+ return -EFAULT;
}
return 0;
}
@@ -166,10+167,10 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
count = request.count;
order = drm_order(request.size);
@@ -295,10+296,10 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count;
request.size = size;
- copy_to_user_ret((drm_buf_desc_t *)arg,
+ if (copy_to_user((drm_buf_desc_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
atomic_dec(&dev->buf_alloc);
return 0;
@@ -324,10+325,10 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_info_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) ++count;
@@ -338,28+339,26 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, if (request.count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) {
- copy_to_user_ret(&request.list[count].count,
+ if (copy_to_user(&request.list[count].count,
&dma->bufs[i].buf_count,
sizeof(dma->bufs[0]
- .buf_count),
- -EFAULT);
- copy_to_user_ret(&request.list[count].size,
+ .buf_count)) ||
+ copy_to_user(&request.list[count].size,
&dma->bufs[i].buf_size,
- sizeof(dma->bufs[0].buf_size),
- -EFAULT);
- copy_to_user_ret(&request.list[count].low_mark,
+ sizeof(dma->bufs[0].buf_size)) ||
+ copy_to_user(&request.list[count].low_mark,
&dma->bufs[i]
.freelist.low_mark,
sizeof(dma->bufs[0]
- .freelist.low_mark),
- -EFAULT);
- copy_to_user_ret(&request.list[count]
+ .freelist.low_mark)) ||
+ copy_to_user(&request.list[count]
.high_mark,
&dma->bufs[i]
.freelist.high_mark,
sizeof(dma->bufs[0]
- .freelist.high_mark),
- -EFAULT);
+ .freelist.high_mark)))
+ return -EFAULT;
+
DRM_DEBUG("%d %d %d %d %d\n",
i,
dma->bufs[i].buf_count,
@@ -372,10+371,10 @@ int drm_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, }
request.count = count;
- copy_to_user_ret((drm_buf_info_t *)arg,
+ if (copy_to_user((drm_buf_info_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
return 0;
}
@@ -392,10+391,10 @@ int drm_markbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("%d, %d, %d\n",
request.size, request.low_mark, request.high_mark);
@@ -427,17+426,17 @@ int drm_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_free_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("%d\n", request.count);
for (i = 0; i < request.count; i++) {
- copy_from_user_ret(&idx,
+ if (copy_from_user(&idx,
&request.list[i],
- sizeof(idx),
- -EFAULT);
+ sizeof(idx)))
+ return -EFAULT;
if (idx < 0 || idx >= dma->buf_count) {
DRM_ERROR("Index %d (of %d max)\n",
idx, dma->buf_count - 1);
@@ -480,10+479,10 @@ int drm_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_map_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
if (request.count >= dma->buf_count) {
down(¤t->mm->mmap_sem);
request.count = dma->buf_count;
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
- copy_to_user_ret((drm_buf_map_t *)arg,
+ if (copy_to_user((drm_buf_map_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
return retcode;
}
@@ -129,19+129,21 @@ int drm_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
+ if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+ return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- copy_to_user_ret(&res.contexts[i],
+ if (copy_to_user(&res.contexts[i],
&i,
- sizeof(i),
- -EFAULT);
+ sizeof(i)))
+ return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
+ if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+ return -EFAULT;
return 0;
}
@@ -153,7+155,8 @@ int drm_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
if ((ctx.handle = drm_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
/* Init kernel's context and get a new one. */
drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx);
@@ -161,7+164,8 @@ int drm_addctx(struct inode *inode, struct file *filp, unsigned int cmd, }
drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx);
DRM_DEBUG("%d\n", ctx.handle);
- copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -173,7+177,8 @@ int drm_modctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx;
drm_queue_t *q;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -206,7+211,8 @@ int drm_getctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx;
drm_queue_t *q;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
@@ -223,7+229,8 @@ int drm_getctx(struct inode *inode, struct file *filp, unsigned int cmd, ctx.flags = q->flags;
atomic_dec(&q->use_count);
- copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -235,7+242,8 @@ int drm_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return drm_context_switch(dev, dev->last_context, ctx.handle);
}
@@ -247,7+255,8 @@ int drm_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
drm_context_switch_complete(dev, ctx.handle);
@@ -263,7+272,8 @@ int drm_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_queue_t *q;
drm_buf_t *buf;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
if (ctx.handle >= dev->queue_count) return -EINVAL;
@@ -486,14+486,16 @@ static int drm_dma_get_buffers_of_order(drm_device_t *dev, drm_dma_t *d, buf->pending);
}
buf->pid = current->pid;
- copy_to_user_ret(&d->request_indices[i],
+ if (copy_to_user(&d->request_indices[i],
&buf->idx,
- sizeof(buf->idx),
- -EFAULT);
- copy_to_user_ret(&d->request_sizes[i],
+ sizeof(buf->idx)))
+ return -EFAULT;
+
+ if (copy_to_user(&d->request_sizes[i],
&buf->total,
- sizeof(buf->total),
- -EFAULT);
+ sizeof(buf->total)))
+ return -EFAULT;
+
++d->granted_count;
}
return 0;
@@ -39,7+39,8 @@ int drm_adddraw(struct inode *inode, struct file *filp, unsigned int cmd,
draw.handle = 0; /* NOOP */
DRM_DEBUG("%d\n", draw.handle);
- copy_to_user_ret((drm_draw_t *)arg, &draw, sizeof(draw), -EFAULT);
+ if (copy_to_user((drm_draw_t *)arg, &draw, sizeof(draw)))
+ return -EFAULT;
return 0;
}
#include <linux/types.h>
#include <linux/agp_backend.h>
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#if LINUX_VERSION_CODE >= 0x020100 /* KERNEL_VERSION(2,1,0) */
#include <linux/tqueue.h>
#include <linux/poll.h>
#endif
+#if LINUX_VERSION_CODE < 0x020400
+#include "compat-pre24.h"
+#endif
#include "drm.h"
#define DRM_DEBUG_CODE 2 /* Include debugging code (if > 1, then
@@ -140,11+143,6 @@ typedef struct wait_queue *wait_queue_head_t; #define module_exit(x) void cleanup_module(void) { x(); }
#endif
- /* virt_to_page added in 2.4.0-test6 */
-#if LINUX_VERSION_CODE < 0x020400
-#define virt_to_page(kaddr) (mem_map + MAP_NR(kaddr))
-#endif
-
/* Generic cmpxchg added in 2.3.x */
#ifndef __HAVE_ARCH_CMPXCHG
/* Include this here so that driver can be
-/* $Id: ffb_context.c,v 1.3 2000/06/09 03:46:53 davem Exp $
+/* $Id: ffb_context.c,v 1.4 2000/08/29 07:01:55 davem Exp $
* ffb_context.c: Creator/Creator3D DRI/DRM context switching.
*
* Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -389,19+389,21 @@ int ffb_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
+ if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+ return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- copy_to_user_ret(&res.contexts[i],
+ if (copy_to_user(&res.contexts[i],
&i,
- sizeof(i),
- -EFAULT);
+ sizeof(i)))
+ return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
+ if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+ return -EFAULT;
return 0;
}
@@ -414,14+416,16 @@ int ffb_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx;
int idx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
idx = ffb_alloc_queue(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
if (idx < 0)
return -ENFILE;
DRM_DEBUG("%d\n", ctx.handle);
ctx.handle = idx;
- copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -435,7+439,8 @@ int ffb_modctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx;
int idx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
idx = ctx.handle;
if (idx <= 0 || idx >= FFB_MAX_CTXS)
@@ -463,7+468,8 @@ int ffb_getctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_ctx_t ctx;
int idx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
idx = ctx.handle;
if (idx <= 0 || idx >= FFB_MAX_CTXS)
@@ -478,7+484,8 @@ int ffb_getctx(struct inode *inode, struct file *filp, unsigned int cmd, else
ctx.flags = 0;
- copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -490,7+497,8 @@ int ffb_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return ffb_context_switch(dev, dev->last_context, ctx.handle);
}
@@ -500,7+508,8 @@ int ffb_newctx(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return 0;
@@ -515,7+524,8 @@ int ffb_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1);
int idx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
idx = ctx.handle - 1;
@@ -176,7+176,8 @@ ssize_t drm_read(struct file *filp, char *buf, size_t count, loff_t *off) } else {
cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
}
- copy_to_user_ret(buf, dev->buf_rp, cur, -EINVAL);
+ if (copy_to_user(buf, dev->buf_rp, cur))
+ return -EFAULT;
dev->buf_rp += cur;
if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
send -= cur;
@@ -586,7+586,8 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd, int retcode = 0;
drm_dma_t d;
- copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
+ if (copy_from_user(&d, (drm_dma_t *)arg, sizeof(d)))
+ return -EFAULT;
DRM_DEBUG("%d %d: %d send, %d req\n",
current->pid, d.context, d.send_count, d.request_count);
@@ -621,7+622,8 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("%d returning, granted = %d\n",
current->pid, d.granted_count);
- copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
+ if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
+ return -EFAULT;
return retcode;
}
@@ -710,7+712,8 @@ int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_control_t ctl;
int retcode;
- copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
+ if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
+ return -EFAULT;
switch (ctl.func) {
case DRM_INST_HANDLER:
@@ -742,7+745,8 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, dev->lck_start = start = get_cycles();
#endif
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -804,6+808,15 @@ int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */
if (!ret) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (lock.flags & _DRM_LOCK_READY)
gamma_dma_ready(dev);
if (lock.flags & _DRM_LOCK_QUIESCENT) {
@@ -405,17+405,18 @@ int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version;
int len;
- copy_from_user_ret(&version,
+ if (copy_from_user(&version,
(drm_version_t *)arg,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
#define DRM_COPY(name,value) \
len = strlen(value); \
if (len > name##_len) len = name##_len; \
name##_len = strlen(value); \
if (len && name) { \
- copy_to_user_ret(name, value, len, -EFAULT); \
+ if (copy_to_user(name, value, len)) \
+ return -EFAULT; \
}
version.version_major = GAMMA_MAJOR;
@@ -426,10+427,10 @@ int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, GAMMA_DATE);
DRM_COPY(version.desc, GAMMA_DESC);
- copy_to_user_ret((drm_version_t *)arg,
+ if (copy_to_user((drm_version_t *)arg,
&version,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
return 0;
}
@@ -537,7+538,8 @@ int gamma_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_lock_t lock;
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -564,5+566,6 @@ int gamma_unlock(struct inode *inode, struct file *filp, unsigned int cmd, - dev->lck_start)]);
#endif
+ unblock_all_signals();
return 0;
}
@@ -56,10+56,10 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
count = request.count;
order = drm_order(request.size);
@@ -155,10+155,10 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count;
request.size = size;
- copy_to_user_ret((drm_buf_desc_t *)arg,
+ if (copy_to_user((drm_buf_desc_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
atomic_dec(&dev->buf_alloc);
dma->flags = _DRM_DMA_USE_AGP;
@@ -170,10+170,10 @@ int i810_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_buf_desc_t request;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
if(request.flags & _DRM_AGP_BUFFER)
return i810_addbufs_agp(inode, filp, cmd, arg);
@@ -201,10+201,10 @@ int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_info_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) ++count;
@@ -215,28+215,26 @@ int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, if (request.count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) {
- copy_to_user_ret(&request.list[count].count,
+ if (copy_to_user(&request.list[count].count,
&dma->bufs[i].buf_count,
sizeof(dma->bufs[0]
- .buf_count),
- -EFAULT);
- copy_to_user_ret(&request.list[count].size,
+ .buf_count)) ||
+ copy_to_user(&request.list[count].size,
&dma->bufs[i].buf_size,
- sizeof(dma->bufs[0].buf_size),
- -EFAULT);
- copy_to_user_ret(&request.list[count].low_mark,
+ sizeof(dma->bufs[0].buf_size)) ||
+ copy_to_user(&request.list[count].low_mark,
&dma->bufs[i]
.freelist.low_mark,
sizeof(dma->bufs[0]
- .freelist.low_mark),
- -EFAULT);
- copy_to_user_ret(&request.list[count]
+ .freelist.low_mark)) ||
+ copy_to_user(&request.list[count]
.high_mark,
&dma->bufs[i]
.freelist.high_mark,
sizeof(dma->bufs[0]
- .freelist.high_mark),
- -EFAULT);
+ .freelist.high_mark)))
+ return -EFAULT;
+
DRM_DEBUG("%d %d %d %d %d\n",
i,
dma->bufs[i].buf_count,
@@ -249,10+247,10 @@ int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, }
request.count = count;
- copy_to_user_ret((drm_buf_info_t *)arg,
+ if (copy_to_user((drm_buf_info_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
return 0;
}
@@ -269,10+267,10 @@ int i810_markbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("%d, %d, %d\n",
request.size, request.low_mark, request.high_mark);
@@ -304,17+302,17 @@ int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_free_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("%d\n", request.count);
for (i = 0; i < request.count; i++) {
- copy_from_user_ret(&idx,
+ if (copy_from_user(&idx,
&request.list[i],
- sizeof(idx),
- -EFAULT);
+ sizeof(idx)))
+ return -EFAULT;
if (idx < 0 || idx >= dma->buf_count) {
DRM_ERROR("Index %d (of %d max)\n",
idx, dma->buf_count - 1);
@@ -103,19+103,21 @@ int i810_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
+ if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+ return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- copy_to_user_ret(&res.contexts[i],
+ if (copy_to_user(&res.contexts[i],
&i,
- sizeof(i),
- -EFAULT);
+ sizeof(i)))
+ return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
+ if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+ return -EFAULT;
return 0;
}
@@ -126,7+128,8 @@ int i810_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
if ((ctx.handle = i810_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
ctx.handle = i810_alloc_queue(dev);
@@ -137,7+140,8 @@ int i810_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM;
}
DRM_DEBUG("%d\n", ctx.handle);
- copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -153,10+157,12 @@ int i810_getctx(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
/* This is 0, because we don't hanlde any context flags */
ctx.flags = 0;
- copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -167,7+173,8 @@ int i810_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return i810_context_switch(dev, dev->last_context, ctx.handle);
}
@@ -179,7+186,8 @@ int i810_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
i810_context_switch_complete(dev, ctx.handle);
@@ -193,7+201,8 @@ int i810_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
if(ctx.handle != DRM_KERNEL_CONTEXT) {
drm_ctxbitmap_free(dev, ctx.handle);
@@ -490,8+490,8 @@ int i810_dma_init(struct inode *inode, struct file *filp, drm_i810_init_t init;
int retcode = 0;
- copy_from_user_ret(&init, (drm_i810_init_t *)arg,
- sizeof(init), -EFAULT);
+ if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
+ return -EFAULT;
switch(init.func) {
case I810_INIT_DMA:
@@ -1005,7+1005,8 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG( "i810_control\n");
- copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
+ if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
+ return -EFAULT;
switch (ctl.func) {
case DRM_INST_HANDLER:
@@ -1178,7+1179,8 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, int ret = 0;
drm_lock_t lock;
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -1227,6+1229,15 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd, }
if (!ret) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (lock.flags & _DRM_LOCK_QUIESCENT) {
DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
DRM_DEBUG("fred\n");
@@ -1266,8+1277,8 @@ int i810_dma_vertex(struct inode *inode, struct file *filp, dev_priv->sarea_priv;
drm_i810_vertex_t vertex;
- copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex),
- -EFAULT);
+ if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex)))
+ return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("i810_dma_vertex called without lock held\n");
@@ -1298,8+1309,8 @@ int i810_clear_bufs(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev;
drm_i810_clear_t clear;
- copy_from_user_ret(&clear, (drm_i810_clear_t *)arg, sizeof(clear),
- -EFAULT);
+ if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear)))
+ return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("i810_clear_bufs called without lock held\n");
@@ -1356,7+1367,8 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, dev_priv->sarea_priv;
DRM_DEBUG("getbuf\n");
- copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT);
+ if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
+ return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("i810_dma called without lock held\n");
@@ -1370,7+1382,8 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
current->pid, retcode, d.granted);
- copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
+ if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
+ return -EFAULT;
sarea_priv->last_dispatch = (int) hw_status[5];
return retcode;
@@ -1395,14+1408,16 @@ int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, return -EINVAL;
}
- copy_from_user_ret(&d, (drm_i810_copy_t *)arg, sizeof(d), -EFAULT);
+ if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d)))
+ return -EFAULT;
if(d.idx > dma->buf_count) return -EINVAL;
buf = dma->buflist[ d.idx ];
buf_priv = buf->dev_private;
if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM;
- copy_from_user_ret(buf_priv->virtual, d.address, d.used, -EFAULT);
+ if (copy_from_user(buf_priv->virtual, d.address, d.used))
+ return -EFAULT;
sarea_priv->last_dispatch = (int) hw_status[5];
@@ -428,17+428,18 @@ int i810_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version;
int len;
- copy_from_user_ret(&version,
+ if (copy_from_user(&version,
(drm_version_t *)arg,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
#define DRM_COPY(name,value) \
len = strlen(value); \
if (len > name##_len) len = name##_len; \
name##_len = strlen(value); \
if (len && name) { \
- copy_to_user_ret(name, value, len, -EFAULT); \
+ if (copy_to_user(name, value, len, -EFAULT)) \
+ return -EFAULT; \
}
version.version_major = I810_MAJOR;
@@ -449,10+450,10 @@ int i810_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, I810_DATE);
DRM_COPY(version.desc, I810_DESC);
- copy_to_user_ret((drm_version_t *)arg,
+ if (copy_to_user((drm_version_t *)arg,
&version,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
return 0;
}
@@ -616,7+617,8 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_lock_t lock;
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -642,5+644,6 @@ int i810_unlock(struct inode *inode, struct file *filp, unsigned int cmd, - dev->lck_start)]);
#endif
+ unblock_all_signals();
return 0;
}
@@ -38,13+38,15 @@ int drm_irq_busid(struct inode *inode, struct file *filp, unsigned int cmd, drm_irq_busid_t p;
struct pci_dev *dev;
- copy_from_user_ret(&p, (drm_irq_busid_t *)arg, sizeof(p), -EFAULT);
+ if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
+ return -EFAULT;
dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
if (dev) p.irq = dev->irq;
else p.irq = 0;
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
p.busnum, p.devnum, p.funcnum, p.irq);
- copy_to_user_ret((drm_irq_busid_t *)arg, &p, sizeof(p), -EFAULT);
+ if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
+ return -EFAULT;
return 0;
}
@@ -55,13+57,15 @@ int drm_getunique(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_unique_t u;
- copy_from_user_ret(&u, (drm_unique_t *)arg, sizeof(u), -EFAULT);
+ if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
+ return -EFAULT;
if (u.unique_len >= dev->unique_len) {
- copy_to_user_ret(u.unique, dev->unique, dev->unique_len,
- -EFAULT);
+ if (copy_to_user(u.unique, dev->unique, dev->unique_len))
+ return -EFAULT;
}
u.unique_len = dev->unique_len;
- copy_to_user_ret((drm_unique_t *)arg, &u, sizeof(u), -EFAULT);
+ if (copy_to_user((drm_unique_t *)arg, &u, sizeof(u)))
+ return -EFAULT;
return 0;
}
@@ -72,15+76,19 @@ int drm_setunique(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_unique_t u;
- if (dev->unique_len || dev->unique) return -EBUSY;
+ if (dev->unique_len || dev->unique)
+ return -EBUSY;
- copy_from_user_ret(&u, (drm_unique_t *)arg, sizeof(u), -EFAULT);
- if (!u.unique_len) return -EINVAL;
+ if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
+ return -EFAULT;
+
+ if (!u.unique_len)
+ return -EINVAL;
dev->unique_len = u.unique_len;
dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
- copy_from_user_ret(dev->unique, u.unique, dev->unique_len,
- -EFAULT);
+ if (copy_from_user(dev->unique, u.unique, dev->unique_len))
+ return -EFAULT;
dev->unique[dev->unique_len] = '\0';
dev->devname = drm_alloc(strlen(dev->name) + strlen(dev->unique) + 2,
@@ -218,7+218,8 @@ int drm_finish(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("\n");
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
ret = drm_flush_block_and_flush(dev, lock.context, lock.flags);
drm_flush_unblock(dev, lock.context, lock.flags);
return ret;
@@ -57,10+57,10 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
count = request.count;
order = drm_order(request.size);
@@ -173,10+173,10 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count;
request.size = size;
- copy_to_user_ret((drm_buf_desc_t *)arg,
+ if (copy_to_user((drm_buf_desc_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
atomic_dec(&dev->buf_alloc);
@@ -219,10+219,10 @@ int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
count = request.count;
order = drm_order(request.size);
@@ -348,10+348,10 @@ int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count;
request.size = size;
- copy_to_user_ret((drm_buf_desc_t *)arg,
+ if (copy_to_user((drm_buf_desc_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
atomic_dec(&dev->buf_alloc);
return 0;
@@ -362,10+362,10 @@ int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_buf_desc_t request;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
if(request.flags & _DRM_AGP_BUFFER)
return mga_addbufs_agp(inode, filp, cmd, arg);
@@ -393,10+393,10 @@ int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_info_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) ++count;
@@ -407,28+407,26 @@ int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, if (request.count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) {
- copy_to_user_ret(&request.list[count].count,
+ if (copy_to_user(&request.list[count].count,
&dma->bufs[i].buf_count,
sizeof(dma->bufs[0]
- .buf_count),
- -EFAULT);
- copy_to_user_ret(&request.list[count].size,
+ .buf_count)) ||
+ copy_to_user(&request.list[count].size,
&dma->bufs[i].buf_size,
- sizeof(dma->bufs[0].buf_size),
- -EFAULT);
- copy_to_user_ret(&request.list[count].low_mark,
+ sizeof(dma->bufs[0].buf_size)) ||
+ copy_to_user(&request.list[count].low_mark,
&dma->bufs[i]
.freelist.low_mark,
sizeof(dma->bufs[0]
- .freelist.low_mark),
- -EFAULT);
- copy_to_user_ret(&request.list[count]
+ .freelist.low_mark)) ||
+ copy_to_user(&request.list[count]
.high_mark,
&dma->bufs[i]
.freelist.high_mark,
sizeof(dma->bufs[0]
- .freelist.high_mark),
- -EFAULT);
+ .freelist.high_mark)))
+ return -EFAULT;
+
DRM_DEBUG("%d %d %d %d %d\n",
i,
dma->bufs[i].buf_count,
@@ -441,10+439,10 @@ int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd, }
request.count = count;
- copy_to_user_ret((drm_buf_info_t *)arg,
+ if (copy_to_user((drm_buf_info_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
return 0;
}
@@ -461,10+459,10 @@ int mga_markbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("%d, %d, %d\n",
request.size, request.low_mark, request.high_mark);
@@ -496,17+494,17 @@ int mga_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_free_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("%d\n", request.count);
for (i = 0; i < request.count; i++) {
- copy_from_user_ret(&idx,
+ if (copy_from_user(&idx,
&request.list[i],
- sizeof(idx),
- -EFAULT);
+ sizeof(idx)))
+ return -EFAULT;
if (idx < 0 || idx >= dma->buf_count) {
DRM_ERROR("Index %d (of %d max)\n",
idx, dma->buf_count - 1);
@@ -550,10+548,10 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_map_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("mga_mapbufs\n");
DRM_DEBUG("dma->flags : %x\n", dma->flags);
@@ -628,10+626,10 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, request.count = dma->buf_count;
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
- copy_to_user_ret((drm_buf_map_t *)arg,
+ if (copy_to_user((drm_buf_map_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
DRM_DEBUG("retcode : %d\n", retcode);
@@ -103,19+103,21 @@ int mga_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
+ if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+ return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- copy_to_user_ret(&res.contexts[i],
+ if (copy_to_user(&res.contexts[i],
&i,
- sizeof(i),
- -EFAULT);
+ sizeof(i)))
+ return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
+ if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+ return -EFAULT;
return 0;
}
@@ -126,7+128,8 @@ int mga_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
if ((ctx.handle = mga_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
ctx.handle = mga_alloc_queue(dev);
@@ -137,7+140,8 @@ int mga_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM;
}
DRM_DEBUG("%d\n", ctx.handle);
- copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -153,10+157,12 @@ int mga_getctx(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
/* This is 0, because we don't hanlde any context flags */
ctx.flags = 0;
- copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -167,7+173,8 @@ int mga_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return mga_context_switch(dev, dev->last_context, ctx.handle);
}
@@ -179,7+186,8 @@ int mga_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
mga_context_switch_complete(dev, ctx.handle);
@@ -193,7+201,8 @@ int mga_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
if(ctx.handle != DRM_KERNEL_CONTEXT) {
drm_ctxbitmap_free(dev, ctx.handle);
@@ -82,6+82,7 @@ static void mga_delay(void) return;
}
+#ifdef __i386__
void mga_flush_write_combine(void)
{
int xchangeDummy;
@@ -92,6+93,11 @@ void mga_flush_write_combine(void) " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;"
" pop %%eax" : /* no outputs */ : /* no inputs */ );
}
+#else
+void mga_flush_write_combine(void)
+{
+}
+#endif
/* These are two age tags that will never be sent to
* the hardware */
@@ -850,7+856,8 @@ int mga_dma_init(struct inode *inode, struct file *filp,
DRM_DEBUG("%s\n", __FUNCTION__);
- copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT);
+ if (copy_from_user(&init, (drm_mga_init_t *)arg, sizeof(init)))
+ return -EFAULT;
switch(init.func) {
case MGA_INIT_DMA:
@@ -932,7+939,8 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_control_t ctl;
- copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
+ if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
+ return -EFAULT;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1019,7+1027,8 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, drm_lock_t lock;
DRM_DEBUG("%s\n", __FUNCTION__);
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -1068,6+1077,15 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, }
if (!ret) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (lock.flags & _DRM_LOCK_QUIESCENT) {
DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
mga_flush_queue(dev);
@@ -1088,7+1106,8 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp, drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("mga_flush_ioctl called without lock held\n");
@@ -444,17+444,18 @@ int mga_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version;
int len;
- copy_from_user_ret(&version,
+ if (copy_from_user(&version,
(drm_version_t *)arg,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
#define DRM_COPY(name,value) \
len = strlen(value); \
if (len > name##_len) len = name##_len; \
name##_len = strlen(value); \
if (len && name) { \
- copy_to_user_ret(name, value, len, -EFAULT); \
+ if (copy_to_user(name, value, len)) \
+ return -EFAULT; \
}
version.version_major = MGA_MAJOR;
@@ -465,10+466,10 @@ int mga_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, MGA_DATE);
DRM_COPY(version.desc, MGA_DESC);
- copy_to_user_ret((drm_version_t *)arg,
+ if (copy_to_user((drm_version_t *)arg,
&version,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
return 0;
}
@@ -633,7+634,8 @@ int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_lock_t lock;
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -655,5+657,6 @@ int mga_unlock(struct inode *inode, struct file *filp, unsigned int cmd, DRM_ERROR("\n");
}
+ unblock_all_signals();
return 0;
}
typedef struct {
u32 buffer_status;
- unsigned int num_dwords;
- unsigned int max_dwords;
+ int num_dwords;
+ int max_dwords;
u32 *current_dma_ptr;
u32 *head;
u32 phys_head;
@@ -209,19+209,27 @@ typedef struct { #define PRIMLOCALS u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
int outcount, num_dwords
-#define PRIM_OVERFLOW(dev, dev_priv, length) do { \
- drm_mga_prim_buf_t *tmp_buf = \
- dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
- if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \
- &tmp_buf->buffer_status)) { \
- mga_advance_primary(dev); \
- mga_dma_schedule(dev, 1); \
- } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||\
- tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \
- set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \
- mga_advance_primary(dev); \
- mga_dma_schedule(dev, 1); \
- } \
+#define PRIM_OVERFLOW(dev, dev_priv, length) do { \
+ drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ if( test_bit(MGA_BUF_NEEDS_OVERFLOW, \
+ &tmp_buf->buffer_status)) { \
+ mga_advance_primary(dev); \
+ mga_dma_schedule(dev, 1); \
+ tmp_buf = dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length || \
+ tmp_buf->sec_used > MGA_DMA_BUF_NR/2) { \
+ set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status); \
+ mga_advance_primary(dev); \
+ mga_dma_schedule(dev, 1); \
+ tmp_buf = dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ } \
+ if(MGA_VERBOSE) \
+ DRM_DEBUG("PRIMGETPTR in %s\n", __FUNCTION__); \
+ dma_ptr = tmp_buf->current_dma_ptr; \
+ num_dwords = tmp_buf->num_dwords; \
+ phys_head = tmp_buf->phys_head; \
+ outcount = 0; \
} while(0)
#define PRIMGETPTR(dev_priv) do { \
#include "mga_drv.h"
#include "drm.h"
+/* If you change the functions to set state, PLEASE
+ * change these values
+ */
+
+#define MGAEMITCLIP_SIZE 10
+#define MGAEMITCTX_SIZE 15
+#define MGAG200EMITTEX_SIZE 20
+#define MGAG400EMITTEX0_SIZE 30
+#define MGAG400EMITTEX1_SIZE 25
+#define MGAG400EMITPIPE_SIZE 50
+#define MGAG200EMITPIPE_SIZE 15
+
+#define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \
+ MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + \
+ MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE)
+
static void mgaEmitClipRect(drm_mga_private_t * dev_priv,
drm_clip_rect_t * box)
{
@@ -60,8+76,8 @@ static void mgaEmitClipRect(drm_mga_private_t * dev_priv,
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1));
- PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / 2);
- PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / 2);
+ PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp);
+ PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / dev_priv->cpp);
PRIMADVANCE(dev_priv);
}
@@ -224,7+240,6 @@ static void mgaG400EmitTex1(drm_mga_private_t * dev_priv) PRIMADVANCE(dev_priv);
}
-#define EMIT_PIPE 50
static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -492,7+507,6 @@ static void mga_dma_dispatch_tex_blit(drm_device_t * dev, y2 = length / 64;
PRIM_OVERFLOW(dev, dev_priv, 30);
- PRIMGETPTR(dev_priv);
PRIMOUTREG(MGAREG_DSTORG, destOrg);
PRIMOUTREG(MGAREG_MACCESS, 0x00000000);
@@ -526,7+540,6 @@ static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf) int length = buf->used;
int use_agp = PDEA_pagpxfer_enable;
int i = 0;
- int primary_needed;
PRIMLOCALS;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -542,9+555,8 @@ static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf) * these numbers (Overestimating this doesn't hurt).
*/
buf_priv->dispatched = 1;
- primary_needed = (50 + 15 + 15 + 30 + 25 +
- 10 + 15 * MGA_NR_SAREA_CLIPRECTS);
- PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+ PRIM_OVERFLOW(dev, dev_priv,
+ (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
mgaEmitState(dev_priv);
do {
if (i < sarea_priv->nbox) {
@@ -592,7+604,6 @@ static void mga_dma_dispatch_indices(drm_device_t * dev, unsigned int address = (unsigned int) buf->bus_address;
int use_agp = PDEA_pagpxfer_enable;
int i = 0;
- int primary_needed;
PRIMLOCALS;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -606,9+617,8 @@ static void mga_dma_dispatch_indices(drm_device_t * dev, * these numbers (Overestimating this doesn't hurt).
*/
buf_priv->dispatched = 1;
- primary_needed = (50 + 15 + 15 + 30 + 25 +
- 10 + 15 * MGA_NR_SAREA_CLIPRECTS);
- PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+ PRIM_OVERFLOW(dev, dev_priv,
+ (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
mgaEmitState(dev_priv);
do {
@@ -657,7+667,6 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, int flags, drm_clip_rect_t *pbox = sarea_priv->boxes;
unsigned int cmd;
int i;
- int primary_needed;
PRIMLOCALS;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -666,11+675,7 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, int flags, else
cmd = MGA_CLEAR_CMD | DC_atype_rstr;
- primary_needed = nbox * 70;
- if (primary_needed == 0)
- primary_needed = 70;
- PRIM_OVERFLOW(dev, dev_priv, primary_needed);
- PRIMGETPTR(dev_priv);
+ PRIM_OVERFLOW(dev, dev_priv, 35 * MGA_NR_SAREA_CLIPRECTS);
for (i = 0; i < nbox; i++) {
unsigned int height = pbox[i].y2 - pbox[i].y1;
@@ -741,14+746,12 @@ static void mga_dma_dispatch_swap(drm_device_t * dev) int nbox = sarea_priv->nbox;
drm_clip_rect_t *pbox = sarea_priv->boxes;
int i;
- int primary_needed;
+ int pixel_stride = dev_priv->stride / dev_priv->cpp;
+
PRIMLOCALS;
DRM_DEBUG("%s\n", __FUNCTION__);
- primary_needed = nbox * 5;
- primary_needed += 65;
- PRIM_OVERFLOW(dev, dev_priv, primary_needed);
- PRIMGETPTR(dev_priv);
+ PRIM_OVERFLOW(dev, dev_priv, (MGA_NR_SAREA_CLIPRECTS * 5) + 20);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
@@ -758,7+761,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev) PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
- PRIMOUTREG(MGAREG_AR5, dev_priv->stride / 2);
+ PRIMOUTREG(MGAREG_AR5, pixel_stride);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
@@ -767,7+770,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev)
for (i = 0; i < nbox; i++) {
unsigned int h = pbox[i].y2 - pbox[i].y1;
- unsigned int start = pbox[i].y1 * dev_priv->stride / 2;
+ unsigned int start = pbox[i].y1 * pixel_stride;
DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2);
@@ -799,8+802,8 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_clear_t clear;
- copy_from_user_ret(&clear, (drm_mga_clear_t *) arg, sizeof(clear),
- -EFAULT);
+ if (copy_from_user(&clear, (drm_mga_clear_t *) arg, sizeof(clear)))
+ return -EFAULT;
DRM_DEBUG("%s\n", __FUNCTION__);
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
@@ -868,8+871,8 @@ int mga_iload(struct inode *inode, struct file *filp, DRM_DEBUG("%s\n", __FUNCTION__);
DRM_DEBUG("Starting Iload\n");
- copy_from_user_ret(&iload, (drm_mga_iload_t *) arg, sizeof(iload),
- -EFAULT);
+ if (copy_from_user(&iload, (drm_mga_iload_t *) arg, sizeof(iload)))
+ return -EFAULT;
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("mga_iload called without lock held\n");
@@ -913,8+916,8 @@ int mga_vertex(struct inode *inode, struct file *filp, drm_mga_vertex_t vertex;
DRM_DEBUG("%s\n", __FUNCTION__);
- copy_from_user_ret(&vertex, (drm_mga_vertex_t *) arg,
- sizeof(vertex), -EFAULT);
+ if (copy_from_user(&vertex, (drm_mga_vertex_t *) arg, sizeof(vertex)))
+ return -EFAULT;
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("mga_vertex called without lock held\n");
@@ -962,8+965,8 @@ int mga_indices(struct inode *inode, struct file *filp, drm_mga_indices_t indices;
DRM_DEBUG("%s\n", __FUNCTION__);
- copy_from_user_ret(&indices, (drm_mga_indices_t *) arg,
- sizeof(indices), -EFAULT);
+ if (copy_from_user(&indices, (drm_mga_indices_t *) arg, sizeof(indices)))
+ return -EFAULT;
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("mga_indices called without lock held\n");
@@ -1008,10+1011,11 @@ static int mga_dma_get_buffers(drm_device_t * dev, drm_dma_t * d) if (!buf)
break;
buf->pid = current->pid;
- copy_to_user_ret(&d->request_indices[i],
- &buf->idx, sizeof(buf->idx), -EFAULT);
- copy_to_user_ret(&d->request_sizes[i],
- &buf->total, sizeof(buf->total), -EFAULT);
+ if (copy_to_user(&d->request_indices[i],
+ &buf->idx, sizeof(buf->idx)) ||
+ copy_to_user(&d->request_sizes[i],
+ &buf->total, sizeof(buf->total)))
+ return -EFAULT;
++d->granted_count;
}
return 0;
@@ -1027,7+1031,8 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd, drm_dma_t d;
DRM_DEBUG("%s\n", __FUNCTION__);
- copy_from_user_ret(&d, (drm_dma_t *) arg, sizeof(d), -EFAULT);
+ if (copy_from_user(&d, (drm_dma_t *) arg, sizeof(d)))
+ return -EFAULT;
DRM_DEBUG("%d %d: %d send, %d req\n",
current->pid, d.context, d.send_count, d.request_count);
@@ -1062,6+1067,7 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("%d returning, granted = %d\n",
current->pid, d.granted_count);
- copy_to_user_ret((drm_dma_t *) arg, &d, sizeof(d), -EFAULT);
+ if (copy_to_user((drm_dma_t *) arg, &d, sizeof(d)))
+ return -EFAULT;
return retcode;
}
@@ -60,10+60,10 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
count = request.count;
order = drm_order(request.size);
@@ -173,10+173,10 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd, request.count = entry->buf_count;
request.size = size;
- copy_to_user_ret((drm_buf_desc_t *)arg,
+ if (copy_to_user((drm_buf_desc_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
dma->flags = _DRM_DMA_USE_AGP;
@@ -195,10+195,10 @@ int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dev_priv || dev_priv->is_pci) return -EINVAL;
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_desc_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
if (request.flags & _DRM_AGP_BUFFER)
@@ -234,10+234,10 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, ++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
- copy_from_user_ret(&request,
+ if (copy_from_user(&request,
(drm_buf_map_t *)arg,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
if (request.count >= dma->buf_count) {
if (dma->flags & _DRM_DMA_USE_AGP) {
@@ -300,10+300,10 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, request.count = dma->buf_count;
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
- copy_to_user_ret((drm_buf_map_t *)arg,
+ if (copy_to_user((drm_buf_map_t *)arg,
&request,
- sizeof(request),
- -EFAULT);
+ sizeof(request)))
+ return -EFAULT;
return retcode;
}
@@ -103,19+103,21 @@ int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
+ if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+ return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- copy_to_user_ret(&res.contexts[i],
+ if (copy_to_user(&res.contexts[i],
&i,
- sizeof(i),
- -EFAULT);
+ sizeof(i)))
+ return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
+ if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+ return -EFAULT;
return 0;
}
@@ -127,7+129,8 @@ int r128_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
if ((ctx.handle = r128_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
ctx.handle = r128_alloc_queue(dev);
@@ -139,7+142,8 @@ int r128_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM;
}
- copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -148,7+152,8 @@ int r128_modctx(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
if (ctx.flags==_DRM_CONTEXT_PRESERVED)
r128_res_ctx.handle=ctx.handle;
return 0;
@@ -159,10+164,12 @@ int r128_getctx(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
/* This is 0, because we don't hanlde any context flags */
ctx.flags = 0;
- copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -173,7+180,8 @@ int r128_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return r128_context_switch(dev, dev->last_context, ctx.handle);
}
@@ -185,7+193,8 @@ int r128_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
r128_context_switch_complete(dev, ctx.handle);
@@ -199,7+208,8 @@ int r128_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
drm_ctxbitmap_free(dev, ctx.handle);
@@ -68,6+68,7 @@ int R128_READ_PLL(drm_device_t *dev, int addr) return R128_READ(R128_CLOCK_CNTL_DATA);
}
+#ifdef __i386__
static void r128_flush_write_combine(void)
{
int xchangeDummy;
@@ -86,6+87,11 @@ static void r128_flush_write_combine(void) "pop %%ebx ;"
"pop %%eax" : /* no outputs */ : /* no inputs */ );
}
+#else
+static void r128_flush_write_combine(void)
+{
+}
+#endif
static void r128_status(drm_device_t *dev)
{
@@ -211,8+217,8 @@ int r128_init_cce(struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev;
drm_r128_init_t init;
- copy_from_user_ret(&init, (drm_r128_init_t *)arg, sizeof(init),
- -EFAULT);
+ if (copy_from_user(&init, (drm_r128_init_t *)arg, sizeof(init)))
+ return -EFAULT;
switch (init.func) {
case R128_INIT_CCE:
@@ -680,8+686,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, return -EINVAL;
}
- copy_from_user_ret(&packet, (drm_r128_packet_t *)arg, sizeof(packet),
- -EFAULT);
+ if (copy_from_user(&packet, (drm_r128_packet_t *)arg, sizeof(packet)))
+ return -EFAULT;
c = packet.count;
size = c * sizeof(*buffer);
@@ -696,7+702,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, }
if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM;
- copy_from_user_ret(buffer, packet.buffer, size, -EFAULT);
+ if (copy_from_user(buffer, packet.buffer, size))
+ return -EFAULT;
if (dev_priv->cce_secure)
ret = r128_submit_packets_ring_secure(dev, buffer, &c);
@@ -706,7+713,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, c += left;
} else {
if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM;
- copy_from_user_ret(buffer, packet.buffer, size, -EFAULT);
+ if (copy_from_user(buffer, packet.buffer, size))
+ return -EFAULT;
if (dev_priv->cce_secure)
ret = r128_submit_packets_pio_secure(dev, buffer, &c);
@@ -717,8+725,8 @@ int r128_submit_pkt(struct inode *inode, struct file *filp, kfree(buffer);
packet.count = c;
- copy_to_user_ret((drm_r128_packet_t *)arg, &packet, sizeof(packet),
- -EFAULT);
+ if (copy_to_user((drm_r128_packet_t *)arg, &packet, sizeof(packet)))
+ return -EFAULT;
if (ret) return ret;
else if (c > 0) return -EAGAIN;
@@ -855,14+863,13 @@ static int r128_get_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) buf = r128_freelist_get(dev);
if (!buf) break;
buf->pid = current->pid;
- copy_to_user_ret(&v->request_indices[i],
+ if (copy_to_user(&v->request_indices[i],
&buf->idx,
- sizeof(buf->idx),
- -EFAULT);
- copy_to_user_ret(&v->request_sizes[i],
+ sizeof(buf->idx)) ||
+ copy_to_user(&v->request_sizes[i],
&buf->total,
- sizeof(buf->total),
- -EFAULT);
+ sizeof(buf->total)))
+ return -EFAULT;
++v->granted_count;
}
return 0;
@@ -889,7+896,8 @@ int r128_vertex_buf(struct inode *inode, struct file *filp, unsigned int cmd, return -EINVAL;
}
- copy_from_user_ret(&v, (drm_r128_vertex_t *)arg, sizeof(v), -EFAULT);
+ if (copy_from_user(&v, (drm_r128_vertex_t *)arg, sizeof(v)))
+ return -EFAULT;
DRM_DEBUG("%d: %d send, %d req\n",
current->pid, v.send_count, v.request_count);
@@ -916,7+924,8 @@ int r128_vertex_buf(struct inode *inode, struct file *filp, unsigned int cmd,
DRM_DEBUG("%d returning, granted = %d\n",
current->pid, v.granted_count);
- copy_to_user_ret((drm_r128_vertex_t *)arg, &v, sizeof(v), -EFAULT);
+ if (copy_to_user((drm_r128_vertex_t *)arg, &v, sizeof(v)))
+ return -EFAULT;
return retcode;
}
@@ -420,17+420,18 @@ int r128_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version;
int len;
- copy_from_user_ret(&version,
+ if (copy_from_user(&version,
(drm_version_t *)arg,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
#define DRM_COPY(name,value) \
len = strlen(value); \
if (len > name##_len) len = name##_len; \
name##_len = strlen(value); \
if (len && name) { \
- copy_to_user_ret(name, value, len, -EFAULT); \
+ if (copy_to_user(name, value, len)) \
+ return -EFAULT; \
}
version.version_major = R128_MAJOR;
@@ -441,10+442,10 @@ int r128_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, R128_DATE);
DRM_COPY(version.desc, R128_DESC);
- copy_to_user_ret((drm_version_t *)arg,
+ if (copy_to_user((drm_version_t *)arg,
&version,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
return 0;
}
@@ -559,7+560,8 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, dev->lck_start = start = get_cycles();
#endif
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -698,7+700,8 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_lock_t lock;
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -105,19+105,21 @@ int tdfx_resctx(struct inode *inode, struct file *filp, unsigned int cmd, int i;
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
- copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT);
+ if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+ return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- copy_to_user_ret(&res.contexts[i],
+ if (copy_to_user(&res.contexts[i],
&i,
- sizeof(i),
- -EFAULT);
+ sizeof(i)))
+ return -EFAULT;
}
}
res.count = DRM_RESERVED_CONTEXTS;
- copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT);
+ if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+ return -EFAULT;
return 0;
}
@@ -129,7+131,8 @@ int tdfx_addctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
if ((ctx.handle = tdfx_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
ctx.handle = tdfx_alloc_queue(dev);
@@ -141,7+144,8 @@ int tdfx_addctx(struct inode *inode, struct file *filp, unsigned int cmd, return -ENOMEM;
}
- copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -150,7+154,8 @@ int tdfx_modctx(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
if (ctx.flags==_DRM_CONTEXT_PRESERVED)
tdfx_res_ctx.handle=ctx.handle;
return 0;
@@ -161,10+166,12 @@ int tdfx_getctx(struct inode *inode, struct file *filp, unsigned int cmd, {
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT);
- /* This is 0, because we don't hanlde any context flags */
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
+ /* This is 0, because we don't handle any context flags */
ctx.flags = 0;
- copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT);
+ if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
return 0;
}
@@ -175,7+182,8 @@ int tdfx_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
return tdfx_context_switch(dev, dev->last_context, ctx.handle);
}
@@ -187,7+195,8 @@ int tdfx_newctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
tdfx_context_switch_complete(dev, ctx.handle);
@@ -201,7+210,8 @@ int tdfx_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
drm_ctxbitmap_free(dev, ctx.handle);
@@ -379,17+379,18 @@ int tdfx_version(struct inode *inode, struct file *filp, unsigned int cmd, drm_version_t version;
int len;
- copy_from_user_ret(&version,
+ if (copy_from_user(&version,
(drm_version_t *)arg,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
#define DRM_COPY(name,value) \
len = strlen(value); \
if (len > name##_len) len = name##_len; \
name##_len = strlen(value); \
if (len && name) { \
- copy_to_user_ret(name, value, len, -EFAULT); \
+ if (copy_to_user(name, value, len)) \
+ return -EFAULT; \
}
version.version_major = TDFX_MAJOR;
@@ -400,10+401,10 @@ int tdfx_version(struct inode *inode, struct file *filp, unsigned int cmd, DRM_COPY(version.date, TDFX_DATE);
DRM_COPY(version.desc, TDFX_DESC);
- copy_to_user_ret((drm_version_t *)arg,
+ if (copy_to_user((drm_version_t *)arg,
&version,
- sizeof(version),
- -EFAULT);
+ sizeof(version)))
+ return -EFAULT;
return 0;
}
@@ -518,7+519,8 @@ int tdfx_lock(struct inode *inode, struct file *filp, unsigned int cmd, dev->lck_start = start = get_cycles();
#endif
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -615,6+617,15 @@ int tdfx_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif
if (!ret) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (lock.flags & _DRM_LOCK_READY) {
/* Wait for space in DMA/FIFO */
}
@@ -649,7+660,8 @@ int tdfx_unlock(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev;
drm_lock_t lock;
- copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
@@ -679,5+691,6 @@ int tdfx_unlock(struct inode *inode, struct file *filp, unsigned int cmd, }
#endif
+ unblock_all_signals();
return 0;
}
A driver for CardBus serial devices
- serial_cb.c 1.15 1999/11/24 02:52:06
+ serial_cb.c 1.20 2000/08/07 19:02:03
Copyright 1998, 1999 by Donald Becker and David Hinds
Donald Becker may be reached as becker@CESDIS.edu, or C/O
USRA Center of Excellence in Space Data and Information Sciences
Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771
- David Hinds may be reached at dhinds@pcmcia.sourceforge.org
+ David Hinds may be reached at dahinds@users.sourceforge.net
======================================================================*/
@@ -39,7+39,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"serial_cb.c 1.15 1999/11/24 02:52:06 (David Hinds)";
+"serial_cb.c 1.20 2000/08/07 19:02:03 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -134,7+134,7 @@ err_out:
static void serial_detach(dev_node_t *node)
{
- DEBUG(0, "serial_detach(tty%02d)\n", node->minor - 0x40);
+ DEBUG(0, "serial_detach(ttyS%02d)\n", node->minor - 0x40);
unregister_serial(node->minor - 0x40);
kfree(node);
MOD_DEC_USE_COUNT;
A driver for PCMCIA serial devices
- serial_cs.c 1.118 2000/05/04 01:29:47
+ serial_cs.c 1.123 2000/08/24 18:46:38
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -58,7+58,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"serial_cs.c 1.118 2000/05/04 01:29:47 (David Hinds)";
+"serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -242,12+242,11 @@ static int setup_serial(serial_info_t *info, ioaddr_t port, int irq) memset(&serial, 0, sizeof(serial));
serial.port = port;
serial.irq = irq;
- serial.flags = ASYNC_SKIP_TEST;
- serial.flags |= (info->multi || info->slave) ? ASYNC_SHARE_IRQ : 0;
+ serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ;
line = register_serial(&serial);
if (line < 0) {
- printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04x, "
- "irq %d failed\n", serial.port, serial.irq);
+ printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx,"
+ " irq %d failed\n", (u_long)serial.port, serial.irq);
return -1;
}
@@ -290,7+289,7 @@ static int simple_config(dev_link_t *link) cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
config_info_t config;
- int i, j;
+ int i, j, try;
/* If the card is already configured, look up the port and irq */
i = CardServices(GetConfigurationInfo, handle, &config);
@@ -315,22+314,26 @@ static int simple_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if (i != CS_SUCCESS) goto next_entry;
- if (cf->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
- cf->vpp1.param[CISTPL_POWER_VNOM]/10000;
- if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
- (cf->io.win[0].base != 0)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = CardServices(RequestIO, link->handle, &link->io);
- if (i == CS_SUCCESS) goto found_port;
+ /* Two tries: without IO aliases, then with aliases */
+ for (try = 0; try < 2; try++) {
+ i = first_tuple(handle, &tuple, &parse);
+ while (i != CS_NO_MORE_ITEMS) {
+ if (i != CS_SUCCESS) goto next_entry;
+ if (cf->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ cf->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
+ (cf->io.win[0].base != 0)) {
+ link->conf.ConfigIndex = cf->index;
+ link->io.BasePort1 = cf->io.win[0].base;
+ link->io.IOAddrLines = (try == 0) ?
+ 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+ i = CardServices(RequestIO, link->handle, &link->io);
+ if (i == CS_SUCCESS) goto found_port;
+ }
+ next_entry:
+ i = next_tuple(handle, &tuple, &parse);
}
- next_entry:
- i = next_tuple(handle, &tuple, &parse);
}
/* Second pass: try to find an entry that isn't picky about
@@ -448,6+451,9 @@ static int multi_config(dev_link_t *link) }
setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
+ /* The Nokia cards are not really multiport cards */
+ if (info->manfid == MANFID_NOKIA)
+ return 0;
for (i = 0; i < info->multi-1; i++)
setup_serial(info, base2+(8*i), link->irq.AssignedIRQ);
@@ -518,11+524,13 @@ void serial_config(dev_link_t *link) (parse.funcid.func == CISTPL_FUNCID_MULTI) ||
(parse.funcid.func == CISTPL_FUNCID_SERIAL))) {
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- if ((first_tuple(handle, &tuple, &parse) == CS_SUCCESS) &&
- (((cf->io.nwin == 1) && (cf->io.win[0].len == 16)) ||
- ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
- (cf->io.win[1].len == 8))))
- info->multi = 2;
+ if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+ if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
+ info->multi = cf->io.win[0].len >> 3;
+ if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
+ (cf->io.win[1].len == 8))
+ info->multi = 2;
+ }
}
if (info->multi > 1)
*
* This Driver is currently maintained by Christoph Lameter (christoph@lameter.com)
*
- * Please contact digi for support issues at digilnux@dgii.com. Some
- * information (mostly of historical interest) can be found at
+ * Please contact digi for support issues at digilnux@dgii.com.
+ * Some more information can be found at
* http://lameter.com/digi.
*
* 1.5.2 Fall 1995 Bug fixes by David Nugent
* and Xeve also.
* 1.6.2 August, 7, 2000: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* get rid of panics, release previously allocated resources
+ * 1.6.3 August, 23, 2000: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * cleaned up wrt verify_area.
+ * Christoph Lameter: Update documentation, email addresses
+ * and URLs. Remove some obsolete code.
*
*/
-#undef SPEED_HACK
-/* If you define SPEED_HACK then you get the following Baudrate translation
- 19200 = 57600
- 38400 = 115K
- The driver supports the native 57.6K and 115K Baudrates under Linux, but
- some distributions like Slackware 3.0 don't like these high baudrates.
-*/
-
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <asm/bitops.h>
#include <asm/semaphore.h>
-#define VERSION "1.6.2"
+#define VERSION "1.6.3"
#include "digi.h"
#include "fep.h"
@@ -713,11+709,10 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha tail &= (size - 1);
stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
count = MIN(stlen, count);
- if (count) {
- if (verify_area(VERIFY_READ, (char*)buf, count))
- count=0;
- else copy_from_user(ch->tmp_buf, buf, count);
- }
+ if (count)
+ if (copy_from_user(ch->tmp_buf, buf, count))
+ count = 0;
+
buf = ch->tmp_buf;
memoff(ch);
restore_flags(flags);
@@ -1896,11+1891,6 @@ fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds, static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
{
unsigned res = 0;
-#ifdef SPEED_HACK
- /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */
- if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200;
- if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600;
-#endif
if (cflag & CBAUDEX)
{
ch->digiext.digi_flags |= DIGI_FAST;
@@ -2124,7+2114,6 @@ static void receive_data(struct channel *ch) static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- int error;
struct channel *ch = (struct channel *) tty->driver_data;
volatile struct board_chan *bc;
int retval;
@@ -2163,15+2152,13 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, return 0;
case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0,
- (unsigned int *) arg);
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned int *)arg);
case TIOCSSOFTCAR:
{
unsigned int value;
- error = get_user( value, (unsigned int *) arg);
- if (error)
- return error;
+ if (get_user(value, (unsigned int *) arg))
+ return -EFAULT;
tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (value ? CLOCAL : 0));
}
return 0;
@@ -2199,18+2186,16 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, if(mstat & ch->dcd)
mflag |= TIOCM_CD;
- error = put_user(mflag, (unsigned int *) arg);
- if(error)
- return error;
+ if (put_user(mflag, (unsigned int *) arg))
+ return -EFAULT;
break;
case TIOCMBIS:
case TIOCMBIC:
case TIOCMODS:
case TIOCMSET:
- error = get_user(mstat, (unsigned int *) arg);
- if(error)
- return error;
+ if (get_user(mstat, (unsigned int *) arg))
+ return -EFAULT;
mflag = 0;
if(mstat & TIOCM_DTR)
@@ -2262,10+2247,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, break;
case DIGI_GETA:
- if((error=verify_area(VERIFY_WRITE, (char*)arg, sizeof(digi_t))))
- return(error);
-
- copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t));
+ if (copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t)))
+ return -EFAULT;
break;
case DIGI_SETAW:
@@ -2282,10+2265,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, /* Fall Thru */
case DIGI_SETA:
- if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(digi_t))))
- return(error);
-
- copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t));
+ if (copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t)))
+ return -EFAULT;
#ifdef DEBUG_IOCTL
printk("ioctl(DIGI_SETA): flags = %x\n", ch->digiext.digi_flags);
#endif
@@ -2319,10+2300,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, memoff(ch);
restore_flags(flags);
- if((error=verify_area(VERIFY_WRITE, (char*)arg,sizeof(dflow))))
- return(error);
-
- copy_to_user((char*)arg, &dflow, sizeof(dflow));
+ if (copy_to_user((char*)arg, &dflow, sizeof(dflow)))
+ return -EFAULT;
break;
case DIGI_SETAFLOW:
@@ -2335,10+2314,8 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, stopc = ch->stopca;
}
- if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(dflow))))
- return(error);
-
- copy_from_user(&dflow, (char*)arg, sizeof(dflow));
+ if (copy_from_user(&dflow, (char*)arg, sizeof(dflow)))
+ return -EFAULT;
if(dflow.startc != startc || dflow.stopc != stopc) {
cli();
@@ -220,10+220,10 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, sizeof(unsigned long)))?-EFAULT:0;
case I2C_RDWR:
- copy_from_user_ret(&rdwr_arg,
- (struct i2c_rdwr_ioctl_data *)arg,
- sizeof(rdwr_arg),
- -EFAULT);
+ if (copy_from_user(&rdwr_arg,
+ (struct i2c_rdwr_ioctl_data *)arg,
+ sizeof(rdwr_arg)))
+ return -EFAULT;
rdwr_pa = (struct i2c_msg *)
kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
@@ -280,10+280,10 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, return res;
case I2C_SMBUS:
- copy_from_user_ret(&data_arg,
+ if (copy_from_user(&data_arg,
(struct i2c_smbus_ioctl_data *) arg,
- sizeof(struct i2c_smbus_ioctl_data),
- -EFAULT);
+ sizeof(struct i2c_smbus_ioctl_data)))
+ return -EFAULT;
if ((data_arg.size != I2C_SMBUS_BYTE) &&
(data_arg.size != I2C_SMBUS_QUICK) &&
(data_arg.size != I2C_SMBUS_BYTE_DATA) &&
@@ -336,15+336,18 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, datasize = sizeof(data_arg.data->block);
if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_WRITE))
- copy_from_user_ret(&temp,data_arg.data,datasize,
- -EFAULT);
+ (data_arg.read_write == I2C_SMBUS_WRITE)) {
+ if (copy_from_user(&temp, data_arg.data, datasize))
+ return -EFAULT;
+ }
res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
data_arg.read_write,
data_arg.command,data_arg.size,&temp);
if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_READ)))
- copy_to_user_ret(data_arg.data,&temp,datasize,-EFAULT);
+ (data_arg.read_write == I2C_SMBUS_READ))) {
+ if (copy_to_user(data_arg.data, &temp, datasize))
+ return -EFAULT;
+ }
return res;
default:
@@ -1242,7+1242,8 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) case VIDIOCCAPTURE:
{
int v;
- get_user_ret(v,(int*)arg, -EFAULT);
+ if (get_user(v, (int *)arg))
+ return -EFAULT;
DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v));
if (v==0) {
@@ -1314,7+1315,8 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) case VIDIOCSYNC:
{
int i;
- get_user_ret(i,(int*)arg, -EFAULT);
+ if (get_user(i, (int *) arg))
+ return -EFAULT;
DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i));
if (i<0 || i>ZORAN_MAX_FBUFFERS)
return -EINVAL;
Written 1993-1998 by
Donald Becker, becker@cesdis.gsfc.nasa.gov, (driver core) and
- David Hinds, dhinds@pcmcia.sourceforge.org (from his PC card code).
+ David Hinds, dahinds@users.sourceforge.net (from his PC card code).
This software may be used and distributed according to the terms of
the GNU Public License, incorporated herein by reference.
@@ -327,7+327,7 @@ static dev_link_t *tc574_attach(void) dev->stop = &el3_close;
dev->tx_timeout = el3_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
-
+
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
A PCMCIA ethernet driver for the 3com 3c589 card.
- Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
+ Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
- 3c589_cs.c 1.151 2000/05/08 22:03:18
+ 3c589_cs.c 1.153 2000/06/12 21:27:25
The network driver code is based on Donald Becker's 3c589 code:
@@ -117,7+117,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"3c589_cs.c 1.151 2000/05/08 22:03:18 (David Hinds)";
+"3c589_cs.c 1.153 2000/06/12 21:27:25 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
* Status: Experimental.
* Authors: John Markus Bjørndalen <johnm@cs.uit.no>
* Dag Brattli <dagb@cs.uit.no>
- * David Hinds <dhinds@pcmcia.sourceforge.org>
+ * David Hinds <dahinds@users.sourceforge.net>
* Created at: A long time ago!
* Modified at: Mon Nov 10 11:54:37 1997
* Modified by: Dag Brattli <dagb@cs.uit.no>
#ifdef CONFIG_NET_PCMCIA_RADIO
#include <linux/wireless.h>
-#endif /* CONFIG_NET_PCMCIA_RADIO */
+#endif
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#define NETWAVE_ASR_RXRDY 0x80
#define NETWAVE_ASR_TXBA 0x01
-#define TX_TIMEOUT 20
-#define WATCHDOG_JIFFIES 32
+#define TX_TIMEOUT ((32*HZ)/100)
static const unsigned int imrConfRFU1 = 0x10; /* RFU interrupt mask, keep high */
static const unsigned int imrConfIENA = 0x02; /* Interrupt enable */
@@ -151,8+150,6 @@ static const unsigned int txConfEUD = 0x10; /* Enable Uni-Data packets */ static const unsigned int txConfKey = 0x02; /* Scramble data packets */
static const unsigned int txConfLoop = 0x01; /* Loopback mode */
-static int netwave_debug = 0;
-
/*
All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
you do not define PCMCIA_DEBUG at all, all the debug code will be
@@ -223,7+220,6 @@ static void netwave_reset(struct net_device *dev); static int netwave_open(struct net_device *dev); /* Open the device */
static int netwave_close(struct net_device *dev); /* Close the device */
static int netwave_config(struct net_device *dev, struct ifmap *map);
-static void netwave_tx_timeout (struct net_device *dev);
/* Packet transmission and Packet reception */
static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev);
@@ -231,7+227,7 @@ static int netwave_rx( struct net_device *dev);
/* Interrupt routines */
static void netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void netwave_watchdog(u_long); /* Transmission watchdog */
+static void netwave_watchdog(struct net_device *);
/* Statistics */
static void update_stats(struct net_device *dev);
@@ -309,7+305,6 @@ typedef struct netwave_private { u_char *ramBase;
int timeoutCounter;
int lastExec;
- spinlock_t lock;
struct timer_list watchdog; /* To avoid blocking state */
struct site_survey nss;
struct net_device_stats stats;
@@ -417,18+412,6 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) #endif
/*
- * Function netwave_init (dev)
- *
- * We never need to do anything when a device is "initialized"
- * by the net software, because we only register already-found cards.
- */
-int netwave_init(struct net_device *dev)
-{
- /* We do all the initialization of this in netwave_attach instead */
- return 0;
-}
-
-/*
* Function netwave_attach (void)
*
* Creates an "instance" of the driver, allocating local data
@@ -456,7+439,6 @@ static dev_link_t *netwave_attach(void) priv = kmalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) return NULL;
memset(priv, 0, sizeof(*priv));
- priv->lock = SPIN_LOCK_UNLOCKED;
link = &priv->link; dev = &priv->dev;
link->priv = dev->priv = priv;
link->release.function = &netwave_release;
@@ -486,10+468,6 @@ static dev_link_t *netwave_attach(void) link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
- /* Set the watchdog timer */
- priv->watchdog.function = &netwave_watchdog;
- priv->watchdog.data = (unsigned long) dev;
-
/* Netwave specific entries in the device structure */
dev->hard_start_xmit = &netwave_start_xmit;
dev->set_config = &netwave_config;
@@ -501,14+479,12 @@ static dev_link_t *netwave_attach(void) #endif
dev->do_ioctl = &netwave_ioctl;
+ dev->tx_timeout = &netwave_watchdog;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
ether_setup(dev);
- strcpy(dev->name, priv->node.dev_name);
- dev->init = &netwave_init;
dev->open = &netwave_open;
dev->stop = &netwave_close;
- dev->tx_timeout = netwave_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
- netif_start_queue (dev);
link->irq.Instance = dev;
/* Register with Card Services */
@@ -545,30+521,21 @@ static void netwave_detach(dev_link_t *link) {
netwave_private *priv = link->priv;
dev_link_t **linkp;
- long flags;
DEBUG(0, "netwave_detach(0x%p)\n", link);
- save_flags(flags);
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- cli();
- restore_flags(flags);
-
/*
If the device is currently configured and active, we won't
actually delete it yet. Instead, it is marked so that when
the release() function is called, that will trigger a proper
detach().
*/
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
netwave_release((u_long) link);
if (link->state & DEV_STALE_CONFIG) {
DEBUG(1, "netwave_cs: detach postponed, '%s' still "
"locked\n", link->dev->dev_name);
-
link->state |= DEV_STALE_LINK;
return;
}
@@ -641,7+608,7 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */ struct iwreq *wrq = (struct iwreq *) rq;
#endif
- DEBUG( 0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
+ DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
@@ -840,7+807,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { struct net_device *dev = &priv->dev;
tuple_t tuple;
cisparse_t parse;
- int i=0, j, last_ret, last_fn;
+ int i, j, last_ret, last_fn;
u_char buf[64];
win_req_t req;
memreq_t mem;
@@ -862,16+829,16 @@ static void netwave_pcmcia_config(dev_link_t *link) { CS_CHECK(ParseTuple, handle, &tuple, &parse);
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
+
/* Configure card */
link->state |= DEV_CONFIG;
-
+
/*
* Try allocating IO ports. This tries a few fixed addresses.
* If you want, you can also read the card's config table to
* pick addresses -- see the serial driver for an example.
*/
- for (j = 0x0; j < 0x400; j += 0x20) {
+ for (i = j = 0x0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
i = CardServices(RequestIO, link->handle, &link->io);
if (i == CS_SUCCESS) break;
@@ -880,19+847,19 @@ static void netwave_pcmcia_config(dev_link_t *link) { cs_error(link->handle, RequestIO, i);
goto failed;
}
-
+
/*
* Now allocate an interrupt line. Note that this does not
* actually assign a handler to the interrupt.
*/
CS_CHECK(RequestIRQ, handle, &link->irq);
-
+
/*
* This actually configures the PCMCIA socket -- setting up
* the I/O windows and the interrupt mapping.
*/
CS_CHECK(RequestConfiguration, handle, &link->conf);
-
+
/*
* Allocate a 32K memory window. Note that the dev_link_t
* structure provides space for one window handle -- if your
@@ -900,7+867,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { * the handles in your private data structure, link->priv.
*/
DEBUG(1, "Setting mem speed of %d\n", mem_speed);
-
+
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
req.Base = 0; req.Size = 0x8000;
req.AccessSpeed = mem_speed;
@@ -908,26+875,25 @@ static void netwave_pcmcia_config(dev_link_t *link) { CS_CHECK(RequestWindow, &link->win, &req);
mem.CardOffset = 0x20000; mem.Page = 0;
CS_CHECK(MapMemPage, link->win, &mem);
-
+
/* Store base address of the common window frame */
ramBase = ioremap(req.Base, 0x8000);
((netwave_private*)dev->priv)->ramBase = ramBase;
-
+
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
goto failed;
}
-
+
+ strcpy(priv->node.dev_name, dev->name);
+ link->dev = &priv->node;
link->state &= ~DEV_CONFIG_PENDING;
-
- link->dev = &((netwave_private *)dev->priv)->node;
/* Reset card before reading physical address */
netwave_doreset(dev->base_addr, ramBase);
-
+
/* Read the ethernet address and fill in the Netwave registers. */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i);
@@ -949,7+915,6 @@ cs_failed: cs_error(link->handle, last_fn, last_ret);
failed:
netwave_release((u_long)link);
- return;
} /* netwave_pcmcia_config */
/*
@@ -975,7+940,7 @@ static void netwave_release(u_long arg) { link->state |= DEV_STALE_CONFIG;
return;
}
-
+
/* Don't bother checking to see if these succeed or not */
if (link->win) {
iounmap(priv->ramBase);
@@ -984,9+949,9 @@ static void netwave_release(u_long arg) { CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
-
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING | DEV_STALE_CONFIG);
-
+
+ link->state &= ~(DEV_CONFIG | DEV_STALE_CONFIG);
+
} /* netwave_release */
/*
@@ -1020,8+985,7 @@ static int netwave_event(event_t event, int priority, link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
- link->release.expires = jiffies + 5;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
@@ -1035,7+999,6 @@ static int netwave_event(event_t event, int priority, if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
-
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -1082,10+1045,7 @@ static void netwave_reset(struct net_device *dev) { DEBUG(0, "netwave_reset: Done with hardware reset\n");
priv->timeoutCounter = 0;
-
- /* If watchdog was activated, kill it ! */
- del_timer(&priv->watchdog);
-
+
/* Reset card */
netwave_doreset(iobase, ramBase);
printk(KERN_DEBUG "netwave_reset: Done with hardware reset\n");
@@ -1172,7+1132,7 @@ static int netwave_hw_xmit(unsigned char* data, int len, netwave_private *priv = (netwave_private *) dev->priv;
u_char* ramBase = priv->ramBase;
ioaddr_t iobase = dev->base_addr;
-
+
/* Disable interrupts & save flags */
save_flags(flags);
cli();
@@ -1183,9+1143,10 @@ static int netwave_hw_xmit(unsigned char* data, int len, /* No buffers available */
printk(KERN_DEBUG "netwave_hw_xmit: %s - no xmit buffers available.\n",
dev->name);
+ restore_flags(flags);
return 1;
}
-
+
priv->stats.tx_bytes += len;
DEBUG(3, "Transmitting with SPCQ %x SPU %x LIF %x ISPLQ %x\n",
@@ -1222,29+1183,11 @@ static int netwave_hw_xmit(unsigned char* data, int len, writeb(len & 0xff, ramBase + NETWAVE_EREG_CB + 1);
writeb((len>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2);
writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
-
- /* If watchdog not already active, activate it... */
- if (!timer_pending(&priv->watchdog)) {
- /* set timer to expire in WATCHDOG_JIFFIES */
- priv->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
- add_timer(&priv->watchdog);
- }
+
restore_flags( flags);
return 0;
}
-
-static void netwave_tx_timeout (struct net_device *dev)
-{
- if (netwave_debug > 0)
- printk (KERN_DEBUG "%s timed out.\n", dev->name);
- netwave_reset (dev);
- dev->trans_start = jiffies;
- netif_start_queue (dev);
-}
-
-
-
static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
/* This flag indicate that the hardware can't perform a transmission.
* Theoritically, NET3 check it before sending a packet to the driver,
@@ -1252,23+1195,15 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) { * As the watchdog will abort too long transmissions, we are quite safe...
*/
- /* Sending a NULL skb means some higher layer thinks we've missed an
- * tx-done interrupt. Caution: dev_tint() handles the cli()/sti()
- * itself.
- */
+ netif_stop_queue(dev);
- /* Block a timer-based transmit from overlapping. This could
- * better be done with atomic_swap(1, dev->tbusy, but set_bit()
- * works as well
- */
- netif_stop_queue (dev);
- if (1) {
+ {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char* buf = skb->data;
if (netwave_hw_xmit( buf, length, dev) == 1) {
/* Some error, let's make them call us another time? */
- netif_start_queue (dev);
+ netif_start_queue(dev);
}
dev->trans_start = jiffies;
}
@@ -1295,11+1230,9 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { dev_link_t *link = &priv->link;
int i;
- if ((dev == NULL) || !netif_device_present(dev))
+ if (!netif_device_present(dev))
return;
- spin_lock (&priv->lock);
-
iobase = dev->base_addr;
ramBase = priv->ramBase;
@@ -1313,9+1246,9 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
status = inb(iobase + NETWAVE_REG_ASR);
- if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) {
- DEBUG( 1, "netwave_interupt: Interrupt with status 0x%x "
- "from removed or suspended card!\n", status);
+ if (!DEV_OK(link)) {
+ DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x "
+ "from removed or suspended card!\n", status);
break;
}
@@ -1393,21+1326,15 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { DEBUG(3, "New status is TSER %x ASR %x\n",
readb(ramBase + NETWAVE_EREG_TSER),
inb(iobase + NETWAVE_REG_ASR));
-
- /* If watchdog was activated, kill it ! */
- del_timer(&priv->watchdog);
- netif_wake_queue (dev);
+ netif_wake_queue(dev);
}
/* TxBA, this would trigger on all error packets received */
/* if (status & 0x01) {
- if (netwave_debug > 3)
- printk(KERN_DEBUG "Transmit buffers available, %x\n", status);
- }
+ DEBUG(4, "Transmit buffers available, %x\n", status);
+ }
*/
}
- /* done.. */
- spin_unlock (&priv->lock);
} /* netwave_interrupt */
/*
@@ -1418,20+1345,12 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { * it expire, we reset the card.
*
*/
-static void netwave_watchdog(u_long a) {
- struct net_device *dev;
- ioaddr_t iobase;
-
- dev = (struct net_device *) a;
- iobase = dev->base_addr;
-
- DEBUG( 1, "%s: netwave_watchdog: watchdog timer expired\n", dev->name);
-
- netwave_reset(dev);
-
- /* We are not waiting anymore... */
- netif_start_queue (dev);
-
+static void netwave_watchdog(struct net_device *dev) {
+
+ DEBUG(1, "%s: netwave_watchdog: watchdog timer expired\n", dev->name);
+ netwave_reset(dev);
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
} /* netwave_watchdog */
static struct net_device_stats *netwave_get_stats(struct net_device *dev) {
@@ -1569,8+1488,8 @@ static int netwave_open(struct net_device *dev) {
link->open++;
MOD_INC_USE_COUNT;
-
- netif_start_queue (dev);
+
+ netif_start_queue(dev);
netwave_reset(dev);
return 0;
@@ -1582,17+1501,10 @@ static int netwave_close(struct net_device *dev) {
DEBUG(1, "netwave_close: finishing.\n");
- netif_stop_queue (dev);
-
- /* If watchdog was activated, kill it ! */
- del_timer(&priv->watchdog);
-
link->open--;
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + 5;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ netif_stop_queue(dev);
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
return 0;
@@ -28,7+28,7 @@ References Dean Siasoyco, New Media Corporation
Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com>
Donald Becker <becker@cesdis1.gsfc.nasa.gov>
- David Hinds <dhinds@pcmcia.sourceforge.org>
+ David Hinds <dahinds@users.sourceforge.net>
The Linux client driver is based on the 3c589_cs.c client driver by
David Hinds.
Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
mode. It will also handle the Socket EA card in either mode.
- Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
+ Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
- pcnet_cs.c 1.117 2000/05/04 01:29:47
+ pcnet_cs.c 1.124 2000/07/21 19:47:31
The network driver code is based on Donald Becker's NE2000 code:
@@ -72,7+72,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"pcnet_cs.c 1.117 2000/05/04 01:29:47 (David Hinds)";
+"pcnet_cs.c 1.124 2000/07/21 19:47:31 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -153,7+153,8 @@ typedef struct hw_info_t { #define USE_BIG_BUF 0x04
#define HAS_IBM_MISC 0x08
#define IS_DL10019 0x10
-#define IS_AX88190 0x20
+#define IS_DL10022 0x20
+#define IS_AX88190 0x40
#define USE_SHMEM 0x80 /* autodetected */
static hw_info_t hw_info[] = {
@@ -219,10+220,9 @@ static hw_info_t hw_info[] = {
#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t))
-static hw_info_t default_info =
-{ /* Unknown NE2000 Clone */ 0x00, 0x00, 0x00, 0x00, 0 };
-static hw_info_t dl10019_info =
-{ /* D-Link DL10019 chipset */ 0x00, 0x00, 0x00, 0x00, IS_DL10019 };
+static hw_info_t default_info = { 0, 0, 0, 0, 0 };
+static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019 };
+static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10019|IS_DL10022 };
typedef struct pcnet_dev_t {
struct net_device dev; /* so &dev == &pcnet_dev_t */
@@ -232,7+232,7 @@ typedef struct pcnet_dev_t { caddr_t base;
struct timer_list watchdog;
int stale, fast_poll;
- u_char link_status;
+ u_short link_status;
} pcnet_dev_t;
/*======================================================================
@@ -504,7+504,8 @@ static hw_info_t *get_dl10019(dev_link_t *link) return NULL;
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
- return &dl10019_info;
+ i = inb(dev->base_addr + 0x1f);
+ return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info;
}
/*======================================================================
@@ -723,14+724,18 @@ static void pcnet_config(dev_link_t *link) hw_info = get_hwired(link);
if (hw_info == NULL) {
- printk(KERN_NOTICE "pcnet_cs: unable to read hardware net address\n");
- goto config_undo;
+ printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
+ " address for io base %#3lx\n", dev->base_addr);
+ unregister_netdev(dev);
+ goto failed;
}
info->flags = hw_info->flags;
/* Check for user overrides */
info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
- if ((manfid == MANFID_SOCKET) && (prodid == PRODID_SOCKET_LPE))
+ if ((manfid == MANFID_SOCKET) &&
+ ((prodid == PRODID_SOCKET_LPE) ||
+ (prodid == PRODID_SOCKET_EIO)))
info->flags &= ~USE_BIG_BUF;
if (!use_big_buf)
info->flags &= ~USE_BIG_BUF;
@@ -760,8+765,9 @@ static void pcnet_config(dev_link_t *link)
if (info->flags & IS_DL10019) {
dev->do_ioctl = &do_ioctl;
- printk(KERN_INFO "%s: NE2000 (DL10019 rev %02x): ",
- dev->name, inb(dev->base_addr + 0x1a));
+ printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ",
+ dev->name, ((info->flags & IS_DL10022) ? 22 : 19),
+ inb(dev->base_addr + 0x1a));
} else if (info->flags & IS_AX88190) {
printk(KERN_INFO "%s: NE2000 (AX88190): ", dev->name);
} else
@@ -776,9+782,6 @@ static void pcnet_config(dev_link_t *link) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
return;
-config_undo:
- unregister_netdev(dev);
- goto failed;
cs_failed:
cs_error(link->handle, last_fn, last_ret);
failed:
@@ -876,6+879,79 @@ static int pcnet_event(event_t event, int priority, return 0;
} /* pcnet_event */
+/*======================================================================
+
+ MII interface support for DL10019 and DL10022 based cards
+
+ On the DL10019, the MII IO direction bit is 0x10; on the DL10022
+ it is 0x20. Setting both bits seems to work on both card types.
+
+======================================================================*/
+
+#define DLINK_GPIO 0x1c
+#define DLINK_DIAG 0x1d
+#define MDIO_SHIFT_CLK 0x80
+#define MDIO_DATA_OUT 0x40
+#define MDIO_DIR_WRITE 0x30
+#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
+#define MDIO_DATA_READ 0x10
+#define MDIO_MASK 0x0f
+
+static void mdio_sync(ioaddr_t addr)
+{
+ int bits, mask = inb(addr) & MDIO_MASK;
+ for (bits = 0; bits < 32; bits++) {
+ outb(mask | MDIO_DATA_WRITE1, addr);
+ outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+ }
+}
+
+static int mdio_read(ioaddr_t addr, int phy_id, int loc)
+{
+ u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+ int i, retval = 0, mask = inb(addr) & MDIO_MASK;
+
+ mdio_sync(addr);
+ for (i = 13; i >= 0; i--) {
+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+ outb(mask | dat, addr);
+ outb(mask | dat | MDIO_SHIFT_CLK, addr);
+ }
+ for (i = 19; i > 0; i--) {
+ outb(mask, addr);
+ retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
+ outb(mask | MDIO_SHIFT_CLK, addr);
+ }
+ return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value)
+{
+ u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+ int i, mask = inb(addr) & MDIO_MASK;
+
+ mdio_sync(addr);
+ for (i = 31; i >= 0; i--) {
+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+ outb(mask | dat, addr);
+ outb(mask | dat | MDIO_SHIFT_CLK, addr);
+ }
+ for (i = 1; i >= 0; i--) {
+ outb(mask, addr);
+ outb(mask | MDIO_SHIFT_CLK, addr);
+ }
+}
+
+static void mdio_reset(ioaddr_t addr, int phy_id)
+{
+ outb_p(0x08, addr);
+ outb_p(0x0c, addr);
+ outb_p(0x08, addr);
+ outb_p(0x0c, addr);
+ outb_p(0x00, addr);
+}
+
/*====================================================================*/
static void set_misc_reg(struct net_device *dev)
@@ -894,6+970,12 @@ static void set_misc_reg(struct net_device *dev) tmp |= 8;
outb_p(tmp, nic_base + PCNET_MISC);
}
+ if (info->flags & IS_DL10022) {
+ mdio_reset(nic_base + DLINK_GPIO, 0);
+ /* Restart MII autonegotiation */
+ mdio_write(nic_base + DLINK_GPIO, 0, 0, 0x0000);
+ mdio_write(nic_base + DLINK_GPIO, 0, 0, 0x1200);
+ }
}
/*====================================================================*/
@@ -914,8+996,7 @@ static int pcnet_open(struct net_device *dev) set_misc_reg(dev);
request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
- /* Start by assuming the link is bad */
- info->link_status = 1;
+ info->link_status = 0x00;
info->watchdog.function = &ei_watchdog;
info->watchdog.data = (u_long)info;
info->watchdog.expires = jiffies + HZ;
@@ -1008,13+1089,14 @@ static void ei_watchdog(u_long arg) pcnet_dev_t *info = (pcnet_dev_t *)(arg);
struct net_device *dev = &info->dev;
ioaddr_t nic_base = dev->base_addr;
+ u_short link;
if (!netif_device_present(dev)) goto reschedule;
/* Check for pending interrupt with expired latency timer: with
this, we can limp along even if the interrupt is blocked */
outb_p(E8390_NODMA+E8390_PAGE0, nic_base + E8390_CMD);
- if (info->stale++ && inb_p(nic_base + EN0_ISR)) {
+ if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
if (!info->fast_poll)
printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
ei_irq_wrapper(dev->irq, dev, NULL);
@@ -1027,15+1109,30 @@ static void ei_watchdog(u_long arg) return;
}
- if (info->flags & IS_DL10019) {
- u_char link = inb(dev->base_addr+0x1c) & 0x01;
- if (link != info->link_status) {
- printk(KERN_INFO "%s: %s link beat\n", dev->name,
- (link) ? "lost" : "found");
- if (!link)
- NS8390_init(dev, 1);
- info->link_status = link;
+ if (!(info->flags & IS_DL10019))
+ goto reschedule;
+
+ link = mdio_read(dev->base_addr + DLINK_GPIO, 0, 1) & 0x0004;
+ if (link != info->link_status) {
+ u_short p = mdio_read(dev->base_addr + DLINK_GPIO, 0, 5);
+ printk(KERN_INFO "%s: %s link beat\n", dev->name,
+ (link) ? "found" : "lost");
+ if (link && (info->flags & IS_DL10022)) {
+ /* Disable collision detection on full duplex links */
+ outb((p & 0x0140) ? 4 : 0, dev->base_addr + DLINK_DIAG);
+ }
+ if (link) {
+ if (p)
+ printk(KERN_INFO "%s: autonegotiation complete: "
+ "%sbaseT-%cD selected\n", dev->name,
+ ((p & 0x0180) ? "100" : "10"),
+ ((p & 0x0140) ? 'F' : 'H'));
+ else
+ printk(KERN_INFO "%s: link partner did not autonegotiate\n",
+ dev->name);
+ NS8390_init(dev, 1);
}
+ info->link_status = link;
}
reschedule:
@@ -1043,83+1140,22 @@ reschedule: add_timer(&info->watchdog);
}
-/*======================================================================
-
- MII interface support for DL10019 based cards
-
- There are two types of DL10019 based cards. Some have the MII IO
- direction bit as 0x10, others as 0x20; setting both bits seems to
- work on all cards.
-
-======================================================================*/
-
-#define MDIO_SHIFT_CLK 0x80
-#define MDIO_DATA_OUT 0x40
-#define MDIO_DIR_WRITE 0x30
-#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
-#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
-#define MDIO_DATA_READ 0x10
-#define MDIO_MASK 0x0f
-
-static void mdio_sync(ioaddr_t addr)
-{
- int bits, mask = inb(addr) & MDIO_MASK;
- for (bits = 0; bits < 32; bits++) {
- outb(mask | MDIO_DATA_WRITE1, addr);
- outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
- }
-}
-
-static int mdio_read(ioaddr_t addr, int phy_id, int loc)
-{
- u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
- int i, retval = 0, mask = inb(addr) & MDIO_MASK;
-
- mdio_sync(addr);
- for (i = 13; i >= 0; i--) {
- int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outb(mask | dat, addr);
- outb(mask | dat | MDIO_SHIFT_CLK, addr);
- }
- for (i = 19; i > 0; i--) {
- outb(mask, addr);
- retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
- outb(mask | MDIO_SHIFT_CLK, addr);
- }
- return (retval>>1) & 0xffff;
-}
-
-static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value)
-{
- u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
- int i, mask = inb(addr) & MDIO_MASK;
-
- mdio_sync(addr);
- for (i = 31; i >= 0; i--) {
- int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outb(mask | dat, addr);
- outb(mask | dat | MDIO_SHIFT_CLK, addr);
- }
- for (i = 1; i >= 0; i--) {
- outb(mask, addr);
- outb(mask | MDIO_SHIFT_CLK, addr);
- }
-}
+/*====================================================================*/
static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
u16 *data = (u16 *)&rq->ifr_data;
- ioaddr_t addr = dev->base_addr + 0x1c;
+ ioaddr_t addr = dev->base_addr + DLINK_GPIO;
switch (cmd) {
case SIOCDEVPRIVATE:
data[0] = 0;
case SIOCDEVPRIVATE+1:
- data[3] = mdio_read(addr, 0, data[1] & 0x1f);
+ data[3] = mdio_read(addr, data[0], data[1] & 0x1f);
return 0;
case SIOCDEVPRIVATE+2:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- mdio_write(addr, 0, data[1] & 0x1f, data[2]);
+ mdio_write(addr, data[0], data[1] & 0x1f, data[2]);
return 0;
}
return -EOPNOTSUPP;
@@ -318,6+318,23 @@ static void cs_error(client_handle_t handle, int func, int ret) error_info_t err = { func, ret };
pcmcia_report_error(handle, &err);
}
+/*======================================================================
+
+ This bit of code is used to avoid unregistering network devices
+ at inappropriate times. 2.2 and later kernels are fairly picky
+ about when this can happen.
+
+======================================================================*/
+
+static void flush_stale_links(void)
+{
+ dev_link_t *link, *next;
+ for (link = dev_list; link; link = next) {
+ next = link->next;
+ if (link->state & DEV_STALE_LINK)
+ ray_detach(link);
+ }
+}
/*=============================================================================
ray_attach() creates an "instance" of the driver, allocating
@@ -336,6+353,7 @@ static dev_link_t *ray_attach(void) struct net_device *dev;
DEBUG(1, "ray_attach()\n");
+ flush_stale_links();
/* Initialize the dev_link_t structure */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
@@ -384,7+402,6 @@ static dev_link_t *ray_attach(void)
dev->priv = local;
local->finder = link;
- link->dev = &local->node;
local->card_status = CARD_INSERTED;
local->authentication_state = UNAUTHENTICATED;
local->num_multi = 0;
@@ -451,8+468,6 @@ fail_alloc_dev: static void ray_detach(dev_link_t *link)
{
dev_link_t **linkp;
- struct net_device *dev;
- long flags;
DEBUG(1, "ray_detach(0x%p)\n", link);
@@ -462,19+477,12 @@ static void ray_detach(dev_link_t *link) if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
/* If the device is currently configured and active, we won't
actually delete it yet. Instead, it is marked so that when
the release() function is called, that will trigger a proper
detach().
*/
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
ray_release((u_long)link);
if(link->state & DEV_STALE_CONFIG) {
@@ -490,10+498,10 @@ static void ray_detach(dev_link_t *link) /* Unlink device structure, free pieces */
*linkp = link->next;
if (link->priv) {
- dev = link->priv;
+ struct net_device *dev = link->priv;
+ if (link->dev) unregister_netdev(dev);
if (dev->priv)
kfree(dev->priv);
-
kfree(link->priv);
}
kfree(link);
@@ -606,6+614,7 @@ static void ray_config(dev_link_t *link) }
strcpy(local->node.dev_name, dev->name);
+ link->dev = &local->node;
link->state &= ~DEV_CONFIG_PENDING;
printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
@@ -907,9+916,7 @@ static void ray_release(u_long arg) return;
}
del_timer(&local->timer);
- if (link->dev != '\0') unregister_netdev(dev);
- /* Unlink the device chain */
- link->dev = NULL;
+ link->state &= ~DEV_CONFIG;
iounmap(local->sram);
iounmap(local->rmem);
@@ -926,8+933,6 @@ static void ray_release(u_long arg) i = pcmcia_release_irq(link->handle, &link->irq);
if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
- link->state &= ~DEV_CONFIG;
- if (link->state & DEV_STALE_LINK) ray_detach(link);
DEBUG(2,"ray_release ending\n");
} /* ray_release */
/*=============================================================================
@@ -954,8+959,7 @@ static int ray_event(event_t event, int priority, link->state &= ~DEV_PRESENT;
netif_device_detach(dev);
if (link->state & DEV_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
del_timer(&local->timer);
}
break;
@@ -1006,7+1010,7 @@ int ray_dev_init(struct net_device *dev) if ( (i = dl_startup_params(dev)) < 0)
{
printk(KERN_INFO "ray_dev_init dl_startup_params failed - "
- "returns 0x%x/n",i);
+ "returns 0x%x\n",i);
return -1;
}
@@ -1554,11+1558,8 @@ static int ray_dev_close(struct net_device *dev)
link->open--;
netif_stop_queue(dev);
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
@@ -2773,10+2774,9 @@ static void __exit exit_ray_cs(void) #endif
unregister_pcmcia_driver(&dev_info);
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG) ray_release((u_long)dev_list);
+ while (dev_list != NULL)
ray_detach(dev_list);
- }
+
#ifdef CONFIG_PROC_FS
remove_proc_entry("driver/ray_cs/ray_cs", NULL);
remove_proc_entry("driver/ray_cs/essid", NULL);
Megahertz, Motorola, Ositech, and Psion Dacom ethernet/modem
multifunction cards.
- Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
+ Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
- smc91c92_cs.c 1.96 2000/05/09 02:35:58
+ smc91c92_cs.c 1.104 2000/08/31 21:25:13
This driver contains code written by Donald Becker
(becker@cesdis.gsfc.nasa.gov), Rowan Hughes (x-csrdh@jcu.edu.au),
- David Hinds (dhinds@pcmcia.sourceforge.org), and Erik Stahlman
+ David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman
(erik@vt.edu). Donald wrote the SMC 91c92 code using parts of
Erik's SMC 91c94 driver. Rowan wrote a similar driver, and I've
incorporated some parts of his driver here. I (Dave) wrote most
@@ -635,11+635,12 @@ static void mot_config(dev_link_t *link) mdelay(100);
}
-static int mot_setup(dev_link_t *link) {
+static int mot_setup(dev_link_t *link)
+{
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
ioaddr_t ioaddr = dev->base_addr;
- int i, wait=0, loop;
+ int i, wait, loop;
u_int addr;
/* Read Ethernet address from Serial EEPROM */
@@ -650,7+651,7 @@ static int mot_setup(dev_link_t *link) { SMC_SELECT_BANK(1);
outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL);
- for (loop = 0; loop < 200; loop++) {
+ for (loop = wait = 0; loop < 200; loop++) {
udelay(10);
wait = ((CTL_RELOAD | CTL_STORE) & inw(ioaddr + CONTROL));
if (wait == 0) break;
@@ -751,7+752,7 @@ static int osi_config(dev_link_t *link) struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
- int i=0, j;
+ int i, j;
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
@@ -765,7+766,7 @@ static int osi_config(dev_link_t *link) /* Enable Hard Decode, LAN, Modem */
link->conf.ConfigIndex = 0x23;
- for (j = 0; j < 4; j++) {
+ for (i = j = 0; j < 4; j++) {
link->io.BasePort2 = com[j];
i = CardServices(RequestIO, link->handle, &link->io);
if (i == CS_SUCCESS) break;
@@ -808,15+809,16 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) for (i = 0; i < 6; i++)
dev->dev_addr[i] = buf[i+2];
- if (manfid != MANFID_OSITECH) return 0;
-
- if (cardid == PRODID_OSITECH_SEVEN) {
+ if (((manfid == MANFID_OSITECH) &&
+ (cardid == PRODID_OSITECH_SEVEN)) ||
+ ((manfid == MANFID_PSION) &&
+ (cardid == PRODID_PSION_NET100))) {
/* Download the Seven of Diamonds firmware */
for (i = 0; i < sizeof(__Xilinx7OD); i++) {
outb(__Xilinx7OD[i], link->io.BasePort1+2);
udelay(50);
}
- } else {
+ } else if (manfid == MANFID_OSITECH) {
/* Make sure both functions are powered up */
set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR);
/* Now, turn on the interrupt for both card functions */
@@ -927,7+929,8 @@ static void smc91c92_config(dev_link_t *link) /* Configure card */
link->state |= DEV_CONFIG;
- if (smc->manfid == MANFID_OSITECH) {
+ if ((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid != PRODID_OSITECH_SEVEN)) {
i = osi_config(link);
} else if ((smc->manfid == MANFID_MOTOROLA) ||
((smc->manfid == MANFID_MEGAHERTZ) &&
@@ -1001,7+1004,7 @@ static void smc91c92_config(dev_link_t *link) for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
if (rev > 0) {
- u_long mir, mcr, mii;
+ u_long mir, mcr;
ioaddr_t ioaddr = dev->base_addr;
SMC_SELECT_BANK(0);
mir = inw(ioaddr + MEMINFO) & 0xff;
@@ -1014,8+1017,14 @@ static void smc91c92_config(dev_link_t *link) else
printk(KERN_INFO " %lu kb", mir>>10);
SMC_SELECT_BANK(1);
- mii = inw(ioaddr + CONFIG) & CFG_MII_SELECT;
- printk(" buffer, %s xcvr\n", mii ? "MII" : if_names[dev->if_port]);
+ smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
+ smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC;
+ if (smc->manfid == MANFID_OSITECH)
+ smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0;
+ if ((rev >> 4) >= 7)
+ smc->cfg |= CFG_MII_SELECT;
+ printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
+ "MII" : if_names[dev->if_port]);
}
return;
@@ -1321,7+1330,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called,"
" status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
-
+
if (smc->saved_skb) {
/* THIS SHOULD NEVER HAPPEN. */
smc->stats.tx_aborted_errors++;
@@ -1808,9+1817,6 @@ static void smc_reset(struct net_device *dev) Accept link errors, counter and Tx error interrupts. */
outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE,
ioaddr + CONTROL);
- smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
- smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC |
- (smc->manfid == MANFID_OSITECH ? (CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0) : 0);
smc_set_xcvr(dev, dev->if_port);
if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN))
* Xircom CreditCard Ethernet Adapter IIps driver
* Xircom Realport 10/100 (RE-100) driver
*
- * This driver originally was made by Werner Koch. Since the driver was left
- * unmaintained for some time, there have been some improvements and changes
- * since. These include supporting some of the "Realport" cards and develop-
- * ing enhancements to support the new ones.
- * It is made for CE2, CEM28, CEM33, CE33 and
- * CEM56 cards. The CEM56 cards work both with their modem and ethernet
- * interface. The RealPort 10/100 Modem and similar cards are supported but
- * with some bugs which are being corrected as they are detected.
+ * This driver supports various Xircom CreditCard Ethernet adapters
+ * including the CE2, CE IIps, RE-10, CEM28, CEM33, CE33, CEM56,
+ * CE3-100, CE3B, RE-100, REM10BT, and REM56G-100.
*
- * Code revised and maintained by Allan Baker Ortegon
- * al527261@prodigy.net.mx
* Written originally by Werner Koch based on David Hinds' skeleton of the
- * PCMCIA driver. The code has been modified as to make the newer cards
- * available.
+ * PCMCIA driver.
*
- * The latest code for the driver, information on the development project
- * for the Xircom RealPort and CE cards for the PCMCIA driver, and other
- * related material, can be found at the following URL, which is underway:
- *
- * "http://xirc2ps.linuxbox.com/index.html"
- *
- * Any bugs regarding this driver, please send them to:
- * alanyuu@linuxbox.com
- *
- * The driver is still evolving and there are many cards which will benefit
- * from having alpha testers. If you have a particular card and would like
- * to be involved in this ongoing effort, please send mail to the maintainer.
- *
- * Special thanks to David Hinds, to Xircom for the specifications and their
- * software development kit, and all others who may have colaborated in the
- * development of the driver: Koen Van Herck (Koen.Van.Herck@xircom.com),
- * 4PC GmbH Duesseldorf, David Luger, et al.
- *
- *
- ************************************************************************
* Copyright (c) 1997,1998 Werner Koch (dd9jn)
- * Copyright (c) 1999 Allan Baker Ortegon
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* Enable the bug fix for CEM56 to use modem and ethernet simultaneously */
-#define CEM56_FIX
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
-#ifndef MANFID_XIRCOM
- #define MANFID_XIRCOM 0x0105
-#endif
#ifndef MANFID_COMPAQ
#define MANFID_COMPAQ 0x0138
#define MANFID_COMPAQ2 0x0183 /* is this correct? */
#endif
-#ifndef MANFID_INTEL
- #define MANFID_INTEL 0x0089
-#endif
#include <pcmcia/ds.h>
@@ -936,26+898,26 @@ xirc2ps_config(dev_link_t * link) switch(parse.manfid.manf) {
case MANFID_XIRCOM:
local->manf_str = "Xircom";
- DEBUG(0, "found xircom card\n");
break;
case MANFID_ACCTON:
local->manf_str = "Accton";
- DEBUG(0, "found Accton card\n");
break;
case MANFID_COMPAQ:
case MANFID_COMPAQ2:
local->manf_str = "Compaq";
- DEBUG(0, "found Compaq card\n");
break;
case MANFID_INTEL:
local->manf_str = "Intel";
- DEBUG(0, "found Intel card\n");
+ break;
+ case MANFID_TOSHIBA:
+ local->manf_str = "Toshiba";
break;
default:
printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n",
(unsigned)parse.manfid.manf);
goto failure;
}
+ DEBUG(0, "found %s card\n", local->manf_str);
if (!set_card_type(link, buf)) {
printk(KNOT_XIRC "this card is not supported\n");
@@ -1120,13+1082,10 @@ xirc2ps_config(dev_link_t * link) }
if (local->dingo) {
- #ifdef CEM56_FIX
conf_reg_t reg;
- #endif
win_req_t req;
memreq_t mem;
- #ifdef CEM56_FIX
/* Reset the modem's BAR to the correct value
* This is necessary because in the RequestConfiguration call,
* the base address of the ethernet port (BasePort1) is written
@@ -1148,7+1107,6 @@ xirc2ps_config(dev_link_t * link) cs_error(link->handle, AccessConfigurationRegister, err);
goto config_error;
}
- #endif
/* There is no config entry for the Ethernet part which
* is at 0x0800. So we allocate a window into the attribute
@@ -1227,9+1185,9 @@ xirc2ps_config(dev_link_t * link) goto config_error;
}
- link->state &= ~DEV_CONFIG_PENDING;
strcpy(local->node.dev_name, dev->name);
link->dev = &local->node;
+ link->state &= ~DEV_CONFIG_PENDING;
if (local->dingo)
do_reset(dev, 1); /* a kludge to make the cem56 work */
@@ -1043,9+1043,10 @@ static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d) return -EPERM;
}
- get_user_ret(addr, &(d->addr), -EFAULT);
- get_user_ret(len, &(d->len), -EFAULT);
- get_user_ret(code, &(d->code), -EFAULT);
+ if (get_user(addr, &(d->addr)) ||
+ __get_user(len, &(d->len)) ||
+ __get_user(code, &(d->code)))
+ return -EFAULT;
if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE)
return -EINVAL;
@@ -1083,9+1084,10 @@ static inline int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d) return -EPERM;
}
- get_user_ret(addr, &(d->addr), -EFAULT);
- get_user_ret(len, &(d->len), -EFAULT);
- get_user_ret(code, &(d->code), -EFAULT);
+ if (get_user(addr, &(d->addr)) ||
+ __get_user(len, &(d->len)) ||
+ __get_user(code, &(d->code)))
+ return -EFAULT;
/* If something fails, force the user to reset the card */
cosa->firmware_status &= ~COSA_FW_RESET;
@@ -1133,7+1135,8 @@ static inline int cosa_start(struct cosa_data *cosa, int address) static inline int cosa_getidstr(struct cosa_data *cosa, char *string)
{
int l = strlen(cosa->id_string)+1;
- copy_to_user_ret(string, cosa->id_string, l, -EFAULT);
+ if (copy_to_user(string, cosa->id_string, l))
+ return -EFAULT;
return l;
}
@@ -1141,7+1144,8 @@ static inline int cosa_getidstr(struct cosa_data *cosa, char *string) static inline int cosa_gettype(struct cosa_data *cosa, char *string)
{
int l = strlen(cosa->type)+1;
- copy_to_user_ret(string, cosa->type, l, -EFAULT);
+ if (copy_to_user(string, cosa->type, l))
+ return -EFAULT;
return l;
}
@@ -1429,7+1433,8 @@ static int download(struct cosa_data *cosa, char *microcode, int length, int add while (length--) {
char c;
#ifndef SRP_DOWNLOAD_AT_BOOT
- get_user_ret(c,microcode, -23);
+ if (get_user(c, microcode))
+ return -23; /* ??? */
#else
c = *microcode;
#endif
@@ -1507,7+1512,8 @@ static int readmem(struct cosa_data *cosa, char *microcode, int length, int addr }
c=i;
#if 1
- put_user_ret(c,microcode, -23);
+ if (put_user(c, microcode))
+ return -23; /* ??? */
#else
*microcode = c;
#endif
PCMCIA Bulk Memory Services
- bulkmem.c 1.34 1999/11/17 01:37:55
+ bulkmem.c 1.37 2000/06/12 21:29:35
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
static int do_mtd_request(memory_handle_t handle, mtd_request_t *req,
caddr_t buf)
{
- int ret=0, tries;
+ int ret, tries;
client_t *mtd;
socket_info_t *s;
@@ -70,7+70,7 @@ static int do_mtd_request(memory_handle_t handle, mtd_request_t *req, if (mtd == NULL)
return CS_GENERAL_FAILURE;
s = SOCKET(mtd);
- for (tries = 0; tries < 100; tries++) {
+ for (ret = tries = 0; tries < 100; tries++) {
mtd->event_callback_args.mtdrequest = req;
mtd->event_callback_args.buffer = buf;
ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW);
=====================================================================*/
-static int cb_assign_irq(u32 mask)
-{
- int irq, try;
-
- for (try = 0; try < 2; try++) {
- for (irq = 1; irq < 32; irq++) {
- if ((mask >> irq) & 1) {
- if (try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0)
- return irq;
- }
- }
- }
- return 0;
-}
-
int cb_alloc(socket_info_t * s)
{
struct pci_bus *bus;
@@ -310,8+295,6 @@ int cb_alloc(socket_info_t * s) /* Does this function have an interrupt at all? */
pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
if (irq_pin) {
- if (!irq)
- irq = cb_assign_irq(s->cap.irq_mask);
dev->irq = irq;
pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
}
@@ -369,14+352,7 @@ int cb_config(socket_info_t * s)
void cb_release(socket_info_t * s)
{
- cb_config_t *c = s->cb_config;
-
DEBUG(0, "cs: cb_release(bus %d)\n", s->cap.cb_dev->subordinate->number);
-
-#ifdef CONFIG_ISA
- if ((c[0].dev.irq != 0) && (c[0].dev.irq != s->cap.pci_irq))
- undo_irq(IRQ_TYPE_EXCLUSIVE, c[0].dev.irq);
-#endif
}
/*=====================================================================
CardBus device enabler
- cb_enabler.c 1.28 1999/12/09 20:57:37
+ cb_enabler.c 1.31 2000/06/12 21:29:36
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -58,12+58,12 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"cb_enabler.c 1.28 1999/12/09 20:57:37 (David Hinds)";
+"cb_enabler.c 1.31 2000/06/12 21:29:36 (David Hinds)";
#else
#define DEBUG(n, args...) do { } while (0)
#endif
-MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("CardBus stub enabler module");
/*====================================================================*/
@@ -168,9+168,9 @@ static void cb_detach(dev_link_t *link) driver_info_t *dev = link->priv;
dev_link_t **linkp;
bus_info_t *b = (void *)link->win;
-
+
DEBUG(0, "cb_detach(0x%p)\n", link);
-
+
/* Locate device structure */
for (linkp = &dev->dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
@@ -179,16+179,16 @@ static void cb_detach(dev_link_t *link)
if (link->state & DEV_CONFIG)
cb_release((u_long)link);
-
+
/* Don't drop Card Services connection if we are the bus owner */
- if ((b->flags != 0) && (link == b->owner)) {
+ if (b && (b->flags != 0) && (link == b->owner)) {
link->state |= DEV_STALE_LINK;
return;
}
-
+
if (link->handle)
pcmcia_deregister_client(link->handle);
-
+
*linkp = link->next;
kfree(link);
MOD_DEC_USE_COUNT;
PCMCIA Card Information Structure parser
- cistpl.c 1.77 2000/01/16 19:19:01
+ cistpl.c 1.90 2000/08/30 20:23:47
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -77,6+77,14 @@ static const u_int exponent[] = { /* Upper limit on reasonable # of tuples */
#define MAX_TUPLES 200
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+
+INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
+
/*======================================================================
Low-level functions to read and write CIS memory. I think the
@@ -88,6+96,17 @@ static const u_int exponent[] = { #define IS_ATTR 1
#define IS_INDIRECT 8
+static void set_cis_map(socket_info_t *s, pccard_mem_map *mem)
+{
+ s->ss_entry->set_mem_map(s->sock, mem);
+ if (s->cap.features & SS_CAP_STATIC_MAP) {
+ if (s->cis_virt)
+ bus_iounmap(s->cap.bus, s->cis_virt);
+ s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start,
+ s->cap.map_size);
+ }
+}
+
void read_cis_mem(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr)
{
@@ -99,16+118,17 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr, memset(ptr, 0xff, len);
return;
}
- mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
- sys = s->cis_virt;
+ mem->flags = MAP_ACTIVE;
+ if (cis_width) mem->flags |= MAP_16BIT;
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
locations in common memory */
u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
- mem->card_start = 0;
- s->ss_entry->set_mem_map(s->sock, mem);
+ mem->card_start = 0; mem->flags = MAP_ACTIVE;
+ set_cis_map(s, mem);
+ sys = s->cis_virt;
bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
@@ -121,14+141,15 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr, if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
sys += (addr & (s->cap.map_size-1));
mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
- s->ss_entry->set_mem_map(s->sock, mem);
+ while (len) {
+ set_cis_map(s, mem);
+ sys = s->cis_virt + (addr & (s->cap.map_size-1));
for ( ; len > 0; len--, buf++, sys += inc) {
if (sys == s->cis_virt+s->cap.map_size) break;
*buf = bus_readb(s->cap.bus, sys);
}
mem->card_start += s->cap.map_size;
+ addr = 0;
}
}
DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
@@ -144,16+165,17 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr,
DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (setup_cis_mem(s) != 0) return;
- mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
- sys = s->cis_virt;
+ mem->flags = MAP_ACTIVE;
+ if (cis_width) mem->flags |= MAP_16BIT;
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
locations in common memory */
u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
- mem->card_start = 0;
- s->ss_entry->set_mem_map(s->sock, mem);
+ mem->card_start = 0; mem->flags = MAP_ACTIVE;
+ set_cis_map(s, mem);
+ sys = s->cis_virt;
bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
@@ -164,16+186,16 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr, } else {
int inc = 1;
if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
- sys += (addr & (s->cap.map_size-1));
mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
- s->ss_entry->set_mem_map(s->sock, mem);
+ while (len) {
+ set_cis_map(s, mem);
+ sys = s->cis_virt + (addr & (s->cap.map_size-1));
for ( ; len > 0; len--, buf++, sys += inc) {
if (sys == s->cis_virt+s->cap.map_size) break;
bus_writeb(s->cap.bus, *buf, sys);
}
mem->card_start += s->cap.map_size;
+ addr = 0;
}
}
}
@@ -238,7+260,8 @@ static int checksum_match(u_long base)
int setup_cis_mem(socket_info_t *s)
{
- if (s->cis_mem.sys_start == 0) {
+ if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
+ (s->cis_mem.sys_start == 0)) {
int low = !(s->cap.features & SS_CAP_PAGE_REGS);
vs = s;
validate_mem(cis_readable, checksum_match, low);
@@ -262,9+285,11 @@ void release_cis_mem(socket_info_t *s) if (s->cis_mem.sys_start != 0) {
s->cis_mem.flags &= ~MAP_ACTIVE;
s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
- release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
+ if (!(s->cap.features & SS_CAP_STATIC_MAP))
+ release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
bus_iounmap(s->cap.bus, s->cis_virt);
s->cis_mem.sys_start = 0;
+ s->cis_virt = NULL;
}
}
@@ -1278,6+1303,25 @@ static int parse_org(tuple_t *tuple, cistpl_org_t *org)
/*====================================================================*/
+static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
+{
+ u_char *p;
+
+ if (tuple->TupleDataLen < 10)
+ return CS_BAD_TUPLE;
+
+ p = tuple->TupleData;
+
+ fmt->type = p[0];
+ fmt->edc = p[1];
+ fmt->offset = le32_to_cpu(*(u_int *)(p+2));
+ fmt->length = le32_to_cpu(*(u_int *)(p+6));
+
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
{
int ret = CS_SUCCESS;
@@ -1345,6+1389,10 @@ int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse case CISTPL_ORG:
ret = parse_org(tuple, &parse->org);
break;
+ case CISTPL_FORMAT:
+ case CISTPL_FORMAT_A:
+ ret = parse_format(tuple, &parse->format);
+ break;
case CISTPL_NO_LINK:
case CISTPL_LINKTARGET:
ret = CS_SUCCESS;
@@ -1395,34+1443,36 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) {
tuple_t tuple;
cisparse_t p;
- int ret, reserved, errors;
-
+ int ret, reserved, dev_ok = 0, ident_ok = 0;
+
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
-
- info->Chains = reserved = errors = 0;
+
+ info->Chains = reserved = 0;
tuple.DesiredTuple = RETURN_FIRST_TUPLE;
tuple.Attributes = TUPLE_RETURN_COMMON;
ret = pcmcia_get_first_tuple(handle, &tuple);
if (ret != CS_SUCCESS)
return CS_SUCCESS;
- /* First tuple should be DEVICE */
- if (tuple.TupleCode != CISTPL_DEVICE)
- errors++;
- /* All cards should have a MANFID tuple */
- if (read_tuple(handle, CISTPL_MANFID, &p) != CS_SUCCESS)
- errors++;
- /* All cards should have either a VERS_1 or a VERS_2 tuple. But
- at worst, we'll accept a CFTABLE_ENTRY that parses. */
- if ((read_tuple(handle, CISTPL_VERS_1, &p) != CS_SUCCESS) &&
- (read_tuple(handle, CISTPL_VERS_2, &p) != CS_SUCCESS) &&
- (read_tuple(handle, CISTPL_CFTABLE_ENTRY, &p) != CS_SUCCESS) &&
- (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, &p) != CS_SUCCESS))
- errors++;
- if (errors > 1)
+ /* First tuple should be DEVICE; we should really have either that
+ or a CFTABLE_ENTRY of some sort */
+ if ((tuple.TupleCode == CISTPL_DEVICE) ||
+ (read_tuple(handle, CISTPL_CFTABLE_ENTRY, &p) == CS_SUCCESS) ||
+ (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, &p) == CS_SUCCESS))
+ dev_ok++;
+
+ /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
+ tuple, for card identification. Certain old D-Link and Linksys
+ cards have only a broken VERS_2 tuple; hence the bogus test. */
+ if ((read_tuple(handle, CISTPL_MANFID, &p) == CS_SUCCESS) ||
+ (read_tuple(handle, CISTPL_VERS_1, &p) == CS_SUCCESS) ||
+ (read_tuple(handle, CISTPL_VERS_2, &p) != CS_NO_MORE_ITEMS))
+ ident_ok++;
+
+ if (!dev_ok && !ident_ok)
return CS_SUCCESS;
-
+
for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) {
ret = pcmcia_get_next_tuple(handle, &tuple);
if (ret != CS_SUCCESS) break;
@@ -1431,9+1481,10 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) ((tuple.TupleCode > 0x90) && (tuple.TupleCode < 0xff)))
reserved++;
}
- if ((info->Chains == MAX_TUPLES) || (reserved > 5))
+ if ((info->Chains == MAX_TUPLES) || (reserved > 5) ||
+ ((!dev_ok || !ident_ok) && (info->Chains > 10)))
info->Chains = 0;
-
+
return CS_SUCCESS;
}
PCMCIA Card Services -- core services
- cs.c 1.249 2000/02/10 23:26:11
+ cs.c 1.267 2000/08/30 22:07:31
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
static const char *version =
-"cs.c 1.249 2000/02/10 23:26:11 (David Hinds)";
+"cs.c 1.267 2000/08/30 22:07:31 (David Hinds)";
#endif
#ifdef CONFIG_PCI
@@ -93,7+93,7 @@ static const char *version = static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
static const char *options = "options: " OPTIONS;
-MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE
"\n options:" OPTIONS);
@@ -773,6+773,13 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base, *base, align);
align = 0;
}
+ /* Check for an already-allocated window that must conflict with
+ what was asked for. It is a hack because it does not catch all
+ potential conflicts, just the most obvious ones. */
+ for (i = 0; i < MAX_IO_WIN; i++)
+ if ((s->io[i].NumPorts != 0) &&
+ ((s->io[i].BasePort & (align-1)) == *base))
+ return 1;
for (i = 0; i < MAX_IO_WIN; i++) {
if (s->io[i].NumPorts == 0) {
if (find_io_region(base, num, align, name) == 0) {
@@ -1676,11+1683,13 @@ int pcmcia_request_configuration(client_handle_t handle, write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
}
if (req->Present & PRESENT_OPTION) {
- if (s->functions == 1)
+ if (s->functions == 1) {
c->Option = req->ConfigIndex & COR_CONFIG_MASK;
- else {
+ } else {
c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
- c->Option |= COR_FUNC_ENA|COR_ADDR_DECODE|COR_IREQ_ENA;
+ c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
+ if (req->Present & PRESENT_IOBASE_0)
+ c->Option |= COR_ADDR_DECODE;
}
if (c->state & CONFIG_IRQ_REQ)
if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
@@ -1829,8+1838,8 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) if (c->state & CONFIG_IRQ_REQ)
return CS_IN_USE;
- /* Short cut: if the interrupt is PCI, there are no options */
- if (s->cap.irq_mask == (1 << s->cap.pci_irq))
+ /* Short cut: if there are no ISA interrupts, then it is PCI */
+ if (!s->cap.irq_mask)
irq = s->cap.pci_irq;
#ifdef CONFIG_ISA
else if (s->irq.AssignedIRQ != 0) {
@@ -1845,7+1854,6 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) ret = CS_IN_USE;
if (req->IRQInfo1 & IRQ_INFO2_VALID) {
mask = req->IRQInfo2 & s->cap.irq_mask;
- mask &= ~(1 << s->cap.pci_irq);
for (try = 0; try < 2; try++) {
for (irq = 0; irq < 32; irq++)
if ((mask >> irq) & 1) {
@@ -1910,11+1918,12 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle req->Size : s->cap.map_size);
if (req->Size & (s->cap.map_size-1))
return CS_BAD_SIZE;
- if (req->Base & (align-1))
+ if ((req->Base && (s->cap.features & SS_CAP_STATIC_MAP)) ||
+ (req->Base & (align-1)))
return CS_BAD_BASE;
if (req->Base)
align = 0;
-
+
/* Allocate system memory window */
for (w = 0; w < MAX_WIN; w++)
if (!(s->state & SOCKET_WIN_REQ(w))) break;
@@ -1928,13+1937,13 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle win->sock = s;
win->base = req->Base;
win->size = req->Size;
-
- if (find_mem_region(&win->base, win->size, align,
+
+ if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
+ find_mem_region(&win->base, win->size, align,
(req->Attributes & WIN_MAP_BELOW_1MB) ||
!(s->cap.features & SS_CAP_PAGE_REGS),
(*handle)->dev_info))
return CS_IN_USE;
- req->Base = win->base;
(*handle)->state |= CLIENT_WIN_REQ(w);
/* Configure the socket controller */
@@ -1949,14+1958,15 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle win->ctl.flags |= MAP_16BIT;
if (req->Attributes & WIN_USE_WAIT)
win->ctl.flags |= MAP_USE_WAIT;
- win->ctl.sys_start = req->Base;
- win->ctl.sys_stop = req->Base + req->Size-1;
+ win->ctl.sys_start = win->base;
+ win->ctl.sys_stop = win->base + win->size-1;
win->ctl.card_start = 0;
if (set_mem_map(s, &win->ctl) != 0)
return CS_BAD_ARGS;
s->state |= SOCKET_WIN_REQ(w);
/* Return window handle */
+ req->Base = win->ctl.sys_start;
*wh = win;
return CS_SUCCESS;
@@ -2168,7+2178,7 @@ int CardServices(int func, void *a1, void *a2, void *a3) {
#ifdef PCMCIA_DEBUG
- if (pc_debug > 1) {
+ if (pc_debug > 2) {
int i;
for (i = 0; i < SERVICE_COUNT; i++)
if (service_table[i].key == func) break;
/*
- * cs_internal.h 1.46 1999/11/08 20:46:49
+ * cs_internal.h 1.52 2000/06/12 21:29:37
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*/
PC Card Driver Services
- ds.c 1.104 2000/01/11 01:18:02
+ ds.c 1.108 2000/08/07 19:06:15
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -61,12+61,12 @@ int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static const char *version =
-"ds.c 1.104 2000/01/11 01:18:02 (David Hinds)";
+"ds.c 1.108 2000/08/07 19:06:15 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
-MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
/*====================================================================*/
@@ -81,6+81,7 @@ typedef struct driver_info_t {
typedef struct socket_bind_t {
driver_info_t *driver;
+ u_char function;
dev_link_t *instance;
struct socket_bind_t *next;
} socket_bind_t;
@@ -391,7+392,8 @@ static int bind_request(int i, bind_info_t *bind_info) }
for (b = s->bind; b; b = b->next)
- if (driver == b->driver)
+ if ((driver == b->driver) &&
+ (bind_info->function == b->function))
break;
if (b != NULL) {
bind_info->instance = b->instance;
@@ -413,6+415,7 @@ static int bind_request(int i, bind_info_t *bind_info) driver->use_count++;
b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
b->driver = driver;
+ b->function = bind_info->function;
b->instance = NULL;
b->next = s->bind;
s->bind = b;
@@ -475,16+478,14 @@ static int get_device_info(int i, bind_info_t *bind_info, int first) #endif
for (b = s->bind; b; b = b->next)
- if (strcmp((char *)b->driver->dev_info,
- (char *)bind_info->dev_info) == 0)
+ if ((strcmp((char *)b->driver->dev_info,
+ (char *)bind_info->dev_info) == 0) &&
+ (b->function == bind_info->function))
break;
if (b == NULL) return -ENODEV;
-
- if (b->instance == NULL)
- return -EAGAIN;
- if (b->instance->state & DEV_CONFIG_PENDING)
+ if ((b->instance == NULL) ||
+ (b->instance->state & DEV_CONFIG_PENDING))
return -EAGAIN;
-
if (first)
node = b->instance->dev;
else
@@ -511,8+512,9 @@ static int unbind_request(int i, bind_info_t *bind_info) DEBUG(2, "unbind_request(%d, '%s')\n", i,
(char *)bind_info->dev_info);
for (b = &s->bind; *b; b = &(*b)->next)
- if (strcmp((char *)(*b)->driver->dev_info,
- (char *)bind_info->dev_info) == 0)
+ if ((strcmp((char *)(*b)->driver->dev_info,
+ (char *)bind_info->dev_info) == 0) &&
+ ((*b)->function == bind_info->function))
break;
if (*b == NULL)
return -ENODEV;
Resource management routines
- rsrc_mgr.c 1.77 1999/11/16 03:32:59
+ rsrc_mgr.c 1.79 2000/08/30 20:23:58
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
/* Parameters that can be set with 'insmod' */
-/* Should we probe resources for conflicts? */
-static int probe_mem = 1;
-MODULE_PARM(probe_mem, "i");
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+
+INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
#ifdef CONFIG_ISA
-static int probe_io = 1;
-static int mem_limit = 0x10000;
-MODULE_PARM(probe_io, "i");
-MODULE_PARM(mem_limit, "i");
+INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
+INT_MODULE_PARM(mem_limit, 0x10000);
#endif
/*======================================================================
/*
- * rsrc_mgr.h 1.19 1999/10/25 20:03:34
+ * rsrc_mgr.h 1.20 2000/06/12 21:29:37
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
@@ -529,7+529,7 @@ static void __init isapnp_add_irq_resource(struct pci_dev *dev, (*res)->irq = irq;
#ifdef CONFIG_PCI
for (i=0; i<16; i++)
- if (irq->map & i)
+ if (irq->map & (1<<i))
pcibios_penalize_isa_irq(i);
#endif
}
@@ -507,7+507,8 @@ static long read_nibble(unsigned minor, char *c, unsigned long cnt) if (pins & BPP_GP_PError) byte |= 0x40;
if (pins & BPP_GP_Busy) byte |= 0x80;
- put_user_ret(byte, c, -EFAULT);
+ if (put_user(byte, c))
+ return -EFAULT;
c += 1;
remaining -= 1;
@@ -559,7+560,8 @@ static long read_ecp(unsigned minor, char *c, unsigned long cnt) for (idx = 0 ; idx < repeat ; idx += 1)
buffer[idx] = instances[minor].repeat_byte;
- copy_to_user_ret(c, buffer, repeat, -EFAULT);
+ if (copy_to_user(c, buffer, repeat))
+ return -EFAULT;
remaining -= repeat;
c += repeat;
instances[minor].run_length -= repeat;
@@ -575,7+577,8 @@ static long read_ecp(unsigned minor, char *c, unsigned long cnt) if (rc & BPP_GP_Busy) {
/* OK, this is data. read it in. */
unsigned char byte = bpp_inb(base_addrs[minor]);
- put_user_ret(byte, c, -EFAULT);
+ if (put_user(byte, c))
+ return -EFAULT;
c += 1;
remaining -= 1;
@@ -685,7+688,8 @@ static long write_compat(unsigned minor, const char *c, unsigned long cnt) while (remaining > 0) {
unsigned char byte;
- get_user_ret(byte, c, -EFAULT);
+ if (get_user(byte, c))
+ return -EFAULT;
c += 1;
rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor);
@@ -735,7+739,8 @@ static long write_ecp(unsigned minor, const char *c, unsigned long cnt) unsigned char byte;
int rc;
- get_user_ret(byte, c, -EFAULT);
+ if (get_user(byte, c))
+ return -EFAULT;
rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor);
if (rc == -1) return -ETIMEDOUT;
-/* $Id: display7seg.c,v 1.2 2000/08/02 06:22:35 davem Exp $
+/* $Id: display7seg.c,v 1.3 2000/08/29 07:01:55 davem Exp $
*
* display7seg - Driver implementation for the 7-segment display
* present on Sun Microsystems CP1400 and CP1500
#include <linux/ioport.h> /* request_region, check_region */
#include <asm/ebus.h> /* EBus device */
#include <asm/oplib.h> /* OpenProm Library */
-#include <asm/uaccess.h> /* put_/get_user_ret */
+#include <asm/uaccess.h> /* put_/get_user */
#include <asm/display7seg.h>
@@ -132,7+132,8 @@ static int d7s_ioctl(struct inode *inode, struct file *f, /* assign device register values
* we mask-out D7S_FLIP if in sol_compat mode
*/
- get_user_ret(ireg, (int *) arg, -EFAULT);
+ if (get_user(ireg, (int *) arg))
+ return -EFAULT;
if (0 != sol_compat) {
(regs & D7S_FLIP) ?
(ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP);
@@ -147,7+148,8 @@ static int d7s_ioctl(struct inode *inode, struct file *f, * This driver will not misinform you about the state
* of your hardware while in sol_compat mode
*/
- put_user_ret(regs, (int *) arg, -EFAULT);
+ if (put_user(regs, (int *) arg))
+ return -EFAULT;
break;
case D7SIOCTM:
@@ -73,7+73,8 @@ static int copyin(struct openpromio *info, struct openpromio **opp_p) if (!info || !opp_p)
return -EFAULT;
- get_user_ret(bufsize, &info->oprom_size, -EFAULT);
+ if (get_user(bufsize, &info->oprom_size))
+ return -EFAULT;
if (bufsize == 0)
return -EINVAL;
@@ -132,7+133,8 @@ static int getstrings(struct openpromio *info, struct openpromio **opp_p) */
static int copyout(void *info, struct openpromio *opp, int len)
{
- copy_to_user_ret(info, opp, len, -EFAULT);
+ if (copy_to_user(info, opp, len))
+ return -EFAULT;
return 0;
}
@@ -364,7+366,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
switch (cmd) {
case OPIOCGET:
- copy_from_user_ret(&op, (void *)arg, sizeof(op), -EFAULT);
+ if (copy_from_user(&op, (void *)arg, sizeof(op)))
+ return -EFAULT;
if (!goodnode(op.op_nodeid,data))
return -EINVAL;
@@ -386,9+389,10 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
if (len <= 0) {
kfree(str);
- /* Verified by the above copy_from_user_ret */
- __copy_to_user_ret((void *)arg, &op,
- sizeof(op), -EFAULT);
+ /* Verified by the above copy_from_user */
+ if (__copy_to_user((void *)arg, &op,
+ sizeof(op)))
+ return -EFAULT;
return 0;
}
@@ -414,7+418,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, return error;
case OPIOCNEXTPROP:
- copy_from_user_ret(&op, (void *)arg, sizeof(op), -EFAULT);
+ if (copy_from_user(&op, (void *)arg, sizeof(op)))
+ return -EFAULT;
if (!goodnode(op.op_nodeid,data))
return -EINVAL;
@@ -457,7+462,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, return error;
case OPIOCSET:
- copy_from_user_ret(&op, (void *)arg, sizeof(op), -EFAULT);
+ if (copy_from_user(&op, (void *)arg, sizeof(op)))
+ return -EFAULT;
if (!goodnode(op.op_nodeid,data))
return -EINVAL;
@@ -485,13+491,14 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, return 0;
case OPIOCGETOPTNODE:
- copy_to_user_ret((void *)arg, &options_node,
- sizeof(int), -EFAULT);
+ if (copy_to_user((void *)arg, &options_node, sizeof(int)))
+ return -EFAULT;
return 0;
case OPIOCGETNEXT:
case OPIOCGETCHILD:
- copy_from_user_ret(&node, (void *)arg, sizeof(int), -EFAULT);
+ if (copy_from_user(&node, (void *)arg, sizeof(int)))
+ return -EFAULT;
save_and_cli(flags);
if (cmd == OPIOCGETNEXT)
@@ -500,7+507,8 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, node = __prom_getchild(node);
restore_flags(flags);
- __copy_to_user_ret((void *)arg, &node, sizeof(int), -EFAULT);
+ if (__copy_to_user((void *)arg, &node, sizeof(int)))
+ return -EFAULT;
return 0;
-/* $Id: rtc.c,v 1.22 2000/08/22 06:56:33 davem Exp $
+/* $Id: rtc.c,v 1.23 2000/08/29 07:01:55 davem Exp $
*
* Linux/SPARC Real Time Clock Driver
* Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -97,7+97,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case RTCGET:
get_rtc_time(&rtc_tm);
- copy_to_user_ret((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time), -EFAULT);
+ if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
+ return -EFAULT;
return 0;
@@ -106,7+107,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_TIME))
return -EPERM;
- copy_from_user_ret(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time), -EFAULT);
+ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
+ return -EFAULT;
set_rtc_time(&rtc_tm);
#ifdef CONFIG_SPARC32_COMPAT
if (current->thread.flags & SPARC_FLAG_32BIT) {
- copy_to_user_ret((Firm_event *)p, &this_event,
- sizeof(Firm_event)-sizeof(struct timeval),
- -EFAULT);
+ if (copy_to_user((Firm_event *)p, &this_event,
+ sizeof(Firm_event)-sizeof(struct timeval)))
+ return -EFAULT;
p += sizeof(Firm_event)-sizeof(struct timeval);
- __put_user_ret(this_event.time.tv_sec, (u32 *)p, -EFAULT);
+ if (__put_user(this_event.time.tv_sec, (u32 *)p))
+ return -EFAULT;
p += sizeof(u32);
- __put_user_ret(this_event.time.tv_usec, (u32 *)p, -EFAULT);
+ if (__put_user(this_event.time.tv_usec, (u32 *)p))
+ return -EFAULT;
p += sizeof(u32);
} else
#endif
{
- copy_to_user_ret((Firm_event *)p, &this_event,
- sizeof(Firm_event), -EFAULT);
+ if (copy_to_user((Firm_event *)p, &this_event,
+ sizeof(Firm_event)))
+ return -EFAULT;
p += sizeof (Firm_event);
}
#ifdef KBD_DEBUG
@@ -1401,22+1404,27 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
switch (cmd){
case KIOCTYPE: /* return keyboard type */
- put_user_ret(sunkbd_type, (int *) arg, -EFAULT);
+ if (put_user(sunkbd_type, (int *) arg))
+ return -EFAULT;
break;
case KIOCGTRANS:
- put_user_ret(TR_UNTRANS_EVENT, (int *) arg, -EFAULT);
+ if (put_user(TR_UNTRANS_EVENT, (int *) arg))
+ return -EFAULT;
break;
case KIOCTRANS:
- get_user_ret(value, (int *) arg, -EFAULT);
+ if (get_user(value, (int *) arg))
+ return -EFAULT;
if (value != TR_UNTRANS_EVENT)
return -EINVAL;
break;
case KIOCLAYOUT:
- put_user_ret(sunkbd_layout, (int *) arg, -EFAULT);
+ if (put_user(sunkbd_layout, (int *) arg))
+ return -EFAULT;
break;
case KIOCSDIRECT:
#ifndef CODING_NEW_DRIVER
- get_user_ret(value, (int *) arg, -EFAULT);
+ if (get_user(value, (int *) arg))
+ return -EFAULT;
if(value)
kbd_redirected = fg_console + 1;
else
@@ -1425,7+1433,8 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) #endif
break;
case KIOCCMD:
- get_user_ret(value, (int *) arg, -EFAULT);
+ if (get_user(value, (int *) arg))
+ return -EFAULT;
c = (unsigned char) value;
switch (c) {
case SKBDCMD_CLICK:
@@ -1444,8+1453,9 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) return -EINVAL;
}
case KIOCSLED:
- get_user_ret(c, (unsigned char *) arg, -EFAULT);
-
+ if (get_user(c, (unsigned char *) arg))
+ return -EFAULT;
+
if (c & LED_SCRLCK) leds |= (1 << VC_SCROLLOCK);
if (c & LED_NLOCK) leds |= (1 << VC_NUMLOCK);
if (c & LED_CLOCK) leds |= (1 << VC_CAPSLOCK);
@@ -1453,7+1463,8 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) sun_setledstate(kbd_table + fg_console, leds);
break;
case KIOCGLED:
- put_user_ret(vcleds_to_sunkbd(getleds()), (unsigned char *) arg, -EFAULT);
+ if (put_user(vcleds_to_sunkbd(getleds()), (unsigned char *) arg))
+ return -EFAULT;
break;
case KIOCGRATE:
{
@@ -1465,8+1476,9 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) else
rate.rate = 0;
- copy_to_user_ret((struct kbd_rate *)arg, &rate,
- sizeof(struct kbd_rate), -EFAULT);
+ if (copy_to_user((struct kbd_rate *)arg, &rate,
+ sizeof(struct kbd_rate)))
+ return -EFAULT;
return 0;
}
@@ -1495,7+1507,8 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) int count;
count = kbd_head - kbd_tail;
- put_user_ret((count < 0) ? KBD_QSIZE - count : count, (int *) arg, -EFAULT);
+ if (put_user((count < 0) ? KBD_QSIZE - count : count, (int *) arg))
+ return -EFAULT;
return 0;
}
default:
@@ -462,21+462,24 @@ repeat: ((sizeof(Firm_event) - sizeof(struct timeval) +
(sizeof(u32) * 2))))
break;
- copy_to_user_ret((Firm_event *)p, &this_event,
- sizeof(Firm_event)-sizeof(struct timeval),
- -EFAULT);
+ if (copy_to_user((Firm_event *)p, &this_event,
+ sizeof(Firm_event)-sizeof(struct timeval)))
+ return -EFAULT;
p += sizeof(Firm_event)-sizeof(struct timeval);
- __put_user_ret(this_event.time.tv_sec, (u32 *)p, -EFAULT);
+ if (__put_user(this_event.time.tv_sec, (u32 *)p))
+ return -EFAULT;
p += sizeof(u32);
- __put_user_ret(this_event.time.tv_usec, (u32 *)p, -EFAULT);
+ if (__put_user(this_event.time.tv_usec, (u32 *)p))
+ return -EFAULT;
p += sizeof(u32);
} else
#endif
{
if ((end - p) < sizeof(Firm_event))
break;
- copy_to_user_ret((Firm_event *)p, &this_event,
- sizeof(Firm_event), -EFAULT);
+ if (copy_to_user((Firm_event *)p, &this_event,
+ sizeof(Firm_event)))
+ return -EFAULT;
p += sizeof (Firm_event);
}
spin_lock_irqsave(&sunmouse.lock, flags);
@@ -540,16+543,19 @@ sun_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsig switch (cmd){
/* VUIDGFORMAT - Get input device byte stream format */
case _IOR('v', 2, int):
- put_user_ret(sunmouse.vuid_mode, (int *) arg, -EFAULT);
+ if (put_user(sunmouse.vuid_mode, (int *) arg))
+ return -EFAULT;
break;
/* VUIDSFORMAT - Set input device byte stream format*/
case _IOW('v', 1, int):
- get_user_ret(i, (int *) arg, -EFAULT);
+ if (get_user(i, (int *) arg))
+ return -EFAULT;
if (i == VUID_NATIVE || i == VUID_FIRM_EVENT){
int value;
- get_user_ret(value, (int *)arg, -EFAULT);
+ if (get_user(value, (int *)arg))
+ return -EFAULT;
spin_lock_irq(&sunmouse.lock);
sunmouse.vuid_mode = value;
-/* $Id: zs.c,v 1.58 2000/07/06 01:41:38 davem Exp $
+/* $Id: zs.c,v 1.59 2000/08/29 07:01:55 davem Exp $
* zs.c: Zilog serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1319,7+1319,8 @@ static int get_serial_info(struct sun_serial * info, tmp.close_delay = info->close_delay;
tmp.closing_wait = info->closing_wait;
tmp.custom_divisor = info->custom_divisor;
- copy_to_user_ret(retinfo,&tmp,sizeof(*retinfo), -EFAULT);
+ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+ return -EFAULT;
return 0;
}
@@ -1390,7+1391,8 @@ static int get_lsr_info(struct sun_serial * info, unsigned int *value) ZSDELAY();
ZSLOG(REGCTRL, status, 0);
sti();
- put_user_ret(status, value, -EFAULT);
+ if (put_user(status, value))
+ return -EFAULT;
return 0;
}
@@ -1409,7+1411,8 @@ static int get_modem_info(struct sun_serial * info, unsigned int *value) | ((status & DCD) ? TIOCM_CAR : 0)
| ((status & SYNC) ? TIOCM_DSR : 0)
| ((status & CTS) ? TIOCM_CTS : 0);
- put_user_ret(result, value, -EFAULT);
+ if (put_user(result, value))
+ return -EFAULT;
return 0;
}
@@ -1418,7+1421,8 @@ static int set_modem_info(struct sun_serial * info, unsigned int cmd, {
unsigned int arg;
- get_user_ret(arg, value, -EFAULT);
+ if (get_user(arg, value))
+ return -EFAULT;
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
@@ -1494,11+1498,13 @@ static int zs_ioctl(struct tty_struct *tty, struct file * file, send_break(info, arg ? arg*(HZ/10) : HZ/4);
return 0;
case TIOCGSOFTCAR:
- put_user_ret(C_CLOCAL(tty) ? 1 : 0,
- (unsigned long *) arg, -EFAULT);
+ if (put_user(C_CLOCAL(tty) ? 1 : 0,
+ (unsigned long *) arg))
+ return -EFAULT;
return 0;
case TIOCSSOFTCAR:
- get_user_ret(arg, (unsigned long *) arg, -EFAULT);
+ if (get_user(arg, (unsigned long *) arg))
+ return -EFAULT;
tty->termios->c_cflag =
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
@@ -1519,8+1525,9 @@ static int zs_ioctl(struct tty_struct *tty, struct file * file, return get_lsr_info(info, (unsigned int *) arg);
case TIOCSERGSTRUCT:
- copy_to_user_ret((struct sun_serial *) arg,
- info, sizeof(struct sun_serial), -EFAULT);
+ if (copy_to_user((struct sun_serial *) arg,
+ info, sizeof(struct sun_serial)))
+ return -EFAULT;
return 0;
default:
@@ -1906,7+1913,7 @@ int zs_open(struct tty_struct *tty, struct file * filp)
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.58 $";
+ char *revision = "$Revision: 1.59 $";
char *version, *p;
version = strchr(revision, ' ');
-/* $Id: esp.c,v 1.95 2000/08/23 22:32:37 davem Exp $
+/* $Id: esp.c,v 1.96 2000/08/24 03:51:26 davem Exp $
* esp.c: EnhancedScsiProcessor Sun SCSI driver code.
*
* Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
@@ -1599,7+1599,9 @@ static void esp_exec_cmd(struct esp *esp)
if (SDptr->sync) {
/* this targets sync is known */
+#ifndef __sparc_v9__
do_sync_known:
+#endif
if (SDptr->disconnect)
*cmdp++ = IDENTIFY(1, lun);
else
@@ -2583,6+2585,8 @@ static int esp_do_data(struct esp *esp) esp_advance_phase(SCptr, thisphase);
ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT"));
hmuch = dma_can_transfer(esp, SCptr);
+ if (hmuch > (64 * 1024) && (esp->erev != fashme))
+ hmuch = (64 * 1024);
ESPDATA(("hmuch<%d> ", hmuch));
esp->current_transfer_size = hmuch;
#define __PUT_USER __put_user
#endif
- #ifndef PUT_USER_RET
- #define PUT_USER_RET put_user_ret
- #endif
-
#ifndef GET_USER
#define GET_USER get_user
#endif
#define __GET_USER __get_user
#endif
- #ifndef GET_USER_RET
- #define GET_USER_RET get_user_ret
- #endif
-
/*
* Lock macros
*/
This driver supports the Adaptec AHA-1460, the New Media Bus
Toaster, and the New Media Toast & Jam.
- aha152x_cs.c 1.53 2000/05/04 01:30:00
+ aha152x_cs.c 1.54 2000/06/12 21:27:25
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -62,7+62,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"aha152x_cs.c 1.53 2000/05/04 01:30:00 (David Hinds)";
+"aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
A driver for the Adaptec APA1480 CardBus SCSI Host Adapter
- apa1480_cb.c 1.19 2000/02/14 22:39:25
+ apa1480_cb.c 1.22 2000/06/12 21:27:25
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -55,7+55,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"apa1480_cb.c 1.19 2000/02/14 22:39:25 (David Hinds)";
+"apa1480_cb.c 1.22 2000/06/12 21:27:25 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
A driver for Future Domain-compatible PCMCIA SCSI cards
- fdomain_cs.c 1.42 2000/05/04 01:30:00
+ fdomain_cs.c 1.43 2000/06/12 21:27:25
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -59,7+59,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"fdomain_cs.c 1.42 2000/05/04 01:30:00 (David Hinds)";
+"fdomain_cs.c 1.43 2000/06/12 21:27:25 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
A driver for the Qlogic SCSI card
- qlogic_cs.c 1.78 2000/05/04 01:30:00
+ qlogic_cs.c 1.79 2000/06/12 21:27:26
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
- <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
@@ -66,7+66,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"qlogic_cs.c 1.78 2000/05/04 01:30:00 (David Hinds)";
+"qlogic_cs.c 1.79 2000/06/12 21:27:26 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -100,9+100,10 @@ sgi_graphics_ioctl (struct inode *inode, struct file *file, unsigned int cmd, un i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct gfx_getboardinfo_args));
if (i) return i;
- __get_user_ret (board, &bia->board, -EFAULT);
- __get_user_ret (dest_buf, &bia->buf, -EFAULT);
- __get_user_ret (max_len, &bia->len, -EFAULT);
+ if (__get_user (board, &bia->board) ||
+ __get_user (dest_buf, &bia->buf) ||
+ __get_user (max_len, &bia->len))
+ return -EFAULT;
if (board >= boards)
return -EINVAL;
@@ -125,8+126,9 @@ sgi_graphics_ioctl (struct inode *inode, struct file *file, unsigned int cmd, un i = verify_area (VERIFY_READ, (void *)arg, sizeof (struct gfx_attach_board_args));
if (i) return i;
- __get_user_ret (board, &att->board, -EFAULT);
- __get_user_ret (vaddr, &att->vaddr, -EFAULT);
+ if (__get_user (board, &att->board) ||
+ __get_user (vaddr, &att->vaddr))
+ return -EFAULT;
/* Ok for now we are assuming /dev/graphicsN -> head N even
* if the ioctl api suggests that this is not quite the case.
@@ -60,7+60,8 @@ rrm_command (unsigned int cmd, void *arg) i = verify_area (VERIFY_READ, arg, rrm_functions [cmd].arg_size);
if (i) return i;
- __get_user_ret (rnid, (int *) arg, -EFAULT);
+ if (__get_user (rnid, (int *) arg))
+ return -EFAULT;
return (*(rrm_functions [cmd].r_fn))(rnid, arg);
}
@@ -419,7+419,8 @@ static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned
if (_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) {
codec->modcnt++;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
switch (_IOC_NR(cmd)) {
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
@@ -1038,7+1038,8 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) s->mix.modcnt++;
switch (_IOC_NR(cmd)) {
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
i = hweight32(val);
for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
if (!(val & (1 << i)))
@@ -1056,7+1057,8 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) return 0;
case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
if (!(val & (1 << i)))
continue;
@@ -1075,7+1077,8 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) i = _IOC_NR(cmd);
if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
l = val & 0xff;
r = (val >> 8) & 0xff;
if (l > 100)
@@ -1469,7+1472,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -1485,7+1489,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
fmtd = 0;
fmtm = ~0;
if (file->f_mode & FMODE_READ) {
@@ -1508,7+1513,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
fmtd = 0;
fmtm = ~0;
@@ -1537,7+1543,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
fmtd = 0;
fmtm = ~0;
@@ -1574,7+1581,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
@@ -1671,7+1679,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(s->dma_adc.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = val & 0xffff;
s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1698,7+1707,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
(file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
@@ -1233,7+1233,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0;
case SNDCTL_DSP_SPEED: /* set smaple rate */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1249,7+1250,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(dmabuf->rate, (int *)arg);
case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
dmabuf->ready = 0;
@@ -1291,7+1293,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_S16_LE, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Select sample format */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
if(val==AFMT_S16_LE/* || val==AFMT_U8*/)
{
@@ -1315,7+1318,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_U8, (int *)arg);
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1340,14+1344,16 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un case SNDCTL_DSP_SUBDIVIDE:
if (dmabuf->subdivision)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2)
return -EINVAL;
dmabuf->subdivision = val;
return 0;
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
dmabuf->ossfragshift = val & 0xffff;
dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
@@ -1408,7+1414,8 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
@@ -523,7+523,8 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, strncpy(info.name, dmasound.mach.name2, sizeof(info.name));
info.name[sizeof(info.name)-1] = 0;
info.modify_counter = mixer.modify_counter;
- copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT);
+ if (copy_to_user((int *)arg, &info, sizeof(info)))
+ return -EFAULT;
return 0;
}
}
@@ -361,7+361,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SPEED:
DPF(2, "SNDCTL_DSP_SPEED:\n");
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
DPD(2, "val is %d\n", val);
if (val > 0) {
@@ -415,7+416,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_STEREO:
DPF(2, "SNDCTL_DSP_STEREO:\n");
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
DPD(2, " val is %d\n", val);
if (file->f_mode & FMODE_READ) {
@@ -460,7+462,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_CHANNELS:
DPF(2, "SNDCTL_DSP_CHANNELS:\n");
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
DPD(2, " val is %d\n", val);
if (val > 0) {
@@ -522,7+525,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */
DPF(2, "SNDCTL_DSP_SETFMT:\n");
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
DPD(2, " val is %d\n", val);
if (val != AFMT_QUERY) {
@@ -624,7+628,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SETTRIGGER:
DPF(2, "SNDCTL_DSP_SETTRIGGER:\n");
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
if (file->f_mode & FMODE_WRITE) {
spin_lock_irqsave(&woinst->lock, flags);
@@ -850,7+855,8 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned case SNDCTL_DSP_SETFRAGMENT:
DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n");
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
DPD(2, "val is 0x%x\n", val);
@@ -1038,7+1038,8 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned if (card->isaps)
return -EINVAL;
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
i = hweight32(val);
if (i == 0)
return 0; /* val = mixer_recmask(s); */
@@ -1062,7+1063,8 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned
if (i >= SOUND_MIXER_NRDEVICES)
return -EINVAL;
- get_user_ret(val, (int *) arg, -EFAULT);
+ if (get_user(val, (int *) arg))
+ return -EFAULT;
if (emu10k1_mixer_wrch(card, i, val))
return -EINVAL;
@@ -842,7+842,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a VALIDATE_STATE(s);
if (cmd == SOUND_MIXER_PRIVATE1) {
/* enable/disable/query mixer preamp */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != -1) {
s->mix.micpreamp = !!val;
wrcodec(s, 0x19, s->mix.micpreamp);
@@ -851,7+852,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a }
if (cmd == SOUND_MIXER_PRIVATE2) {
/* enable/disable/query use of linein as second lineout */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != -1) {
spin_lock_irqsave(&s->lock, flags);
if (val)
@@ -865,7+867,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a }
if (cmd == SOUND_MIXER_PRIVATE3) {
/* enable/disable/query microphone impedance setting */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != -1) {
spin_lock_irqsave(&s->lock, flags);
if (val)
@@ -941,12+944,14 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a switch (_IOC_NR(cmd)) {
case SOUND_MIXER_IMIX:
- get_user_ret(s->mix.imix, (int *)arg, -EFAULT);
+ if (get_user(s->mix.imix, (int *)arg))
+ return -EFAULT;
set_recsrc(s, s->mix.recsrc);
return 0;
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
set_recsrc(s, val);
return 0;
@@ -954,7+959,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a i = _IOC_NR(cmd);
if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
l = val & 0xff;
if (l > 100)
l = 100;
@@ -1382,7+1388,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (s->open_mode & (~file->f_mode) & (FMODE_READ|FMODE_WRITE))
return -EINVAL;
@@ -1401,7+1408,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
stop_adc(s);
s->dma_adc.ready = 0;
@@ -1427,7+1435,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -1458,7+1467,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -1498,7+1508,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -1609,7+1620,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(s->dma_adc.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = val & 0xffff;
s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1636,7+1648,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
(file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
@@ -1916,7+1929,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
stop_dac1(s);
s->dma_dac1.ready = 0;
@@ -1931,7+1945,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
stop_dac1(s);
s->dma_dac1.ready = 0;
spin_lock_irqsave(&s->lock, flags);
@@ -1944,7+1959,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
if (s->dma_dac1.mapped)
return -EINVAL;
@@ -1964,7+1980,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
stop_dac1(s);
s->dma_dac1.ready = 0;
@@ -1985,7+2002,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val & PCM_ENABLE_OUTPUT) {
if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
return ret;
@@ -2044,7+2062,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dma_dac1.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
s->dma_dac1.ossfragshift = val & 0xffff;
s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
if (s->dma_dac1.ossfragshift < 4)
@@ -2058,7+2077,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int case SNDCTL_DSP_SUBDIVIDE:
if (s->dma_dac1.subdivision)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
s->dma_dac1.subdivision = val;
@@ -1165,7+1165,8 @@ static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned lon return 0;
case SOUND_MIXER_WRITE_PCM: /* use SRC for PCM volume */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
right = ((val >> 8) & 0xff);
left = (val & 0xff);
if (right > 100)
@@ -1570,7+1571,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -1586,7+1588,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
stop_adc(s);
s->dma_adc.ready = 0;
@@ -1612,7+1615,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -1643,7+1647,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -1683,7+1688,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -1794,7+1800,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(s->dma_adc.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = val & 0xffff;
s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1821,7+1828,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
(file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
@@ -2100,7+2108,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
stop_dac1(s);
s->dma_dac1.ready = 0;
@@ -2109,7+2118,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dac1rate, (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
stop_dac1(s);
s->dma_dac1.ready = 0;
spin_lock_irqsave(&s->lock, flags);
@@ -2122,7+2132,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
stop_dac1(s);
s->dma_dac1.ready = 0;
@@ -2140,7+2151,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
stop_dac1(s);
s->dma_dac1.ready = 0;
@@ -2161,7+2173,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val & PCM_ENABLE_OUTPUT) {
if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
return ret;
@@ -2220,7+2233,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dma_dac1.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
s->dma_dac1.ossfragshift = val & 0xffff;
s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
if (s->dma_dac1.ossfragshift < 4)
@@ -2234,7+2248,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int case SNDCTL_DSP_SUBDIVIDE:
if (s->dma_dac1.subdivision)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
s->dma_dac1.subdivision = val;
@@ -686,7+686,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar
if (cmd == SOUND_MIXER_PRIVATE1) {
/* enable/disable/query mixer preamp */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != -1) {
val = val ? 0xff : 0xf7;
write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val);
@@ -696,7+697,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar }
if (cmd == SOUND_MIXER_PRIVATE2) {
/* enable/disable/query spatializer */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != -1) {
val &= 0x3f;
write_mixer(s, 0x52, val);
@@ -773,7+775,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar 0xb4, read_ctrl(s, 0xb4));
}
#endif
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
i = hweight32(val);
if (i == 0)
return 0;
@@ -789,7+792,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar return 0;
case SOUND_MIXER_VOLUME:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
l = val & 0xff;
if (l > 100)
l = 100;
@@ -820,7+824,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar return put_user(s->mix.vol[9], (int *)arg);
case SOUND_MIXER_SPEAKER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
l = val & 0xff;
if (l > 100)
l = 100;
@@ -837,7+842,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar return put_user(s->mix.vol[7], (int *)arg);
case SOUND_MIXER_RECLEV:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
l = (val << 1) & 0x1fe;
if (l > 200)
l = 200;
@@ -864,7+870,8 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar i = _IOC_NR(cmd);
if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
l = (val << 1) & 0x1fe;
if (l > 200)
l = 200;
@@ -1268,7+1275,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
stop_adc(s);
stop_dac(s);
@@ -1295,7+1303,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(s->rate, (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
stop_adc(s);
stop_dac(s);
s->dma_adc.ready = s->dma_dac.ready = 0;
@@ -1305,7+1314,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
stop_adc(s);
stop_dac(s);
@@ -1320,7+1330,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
stop_adc(s);
stop_dac(s);
@@ -1346,7+1357,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -1459,7+1471,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(s->dma_adc.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = val & 0xffff;
s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1486,7+1499,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
(file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
@@ -1300,7+1300,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0;
case SNDCTL_DSP_SPEED: /* set smaple rate */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1320,7+1321,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(dmabuf->rate, (int *)arg);
case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if(val==0)
return -EINVAL;
if (file->f_mode & FMODE_WRITE) {
@@ -1351,7+1353,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(AFMT_S16_LE, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Select sample format */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1365,7+1368,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(AFMT_S16_LE, (int *)arg);
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1385,14+1389,16 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case SNDCTL_DSP_SUBDIVIDE:
if (dmabuf->subdivision)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
dmabuf->subdivision = val;
return 0;
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
dmabuf->ossfragshift = val & 0xffff;
dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
@@ -1450,7+1456,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
@@ -2034,7+2034,8 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar
card->mix.modcnt++;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
switch (_IOC_NR(cmd)) {
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
@@ -2502,7+2503,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -2518,7+2520,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
fmtd = 0;
fmtm = ~0;
if (file->f_mode & FMODE_READ) {
@@ -2541,7+2544,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
fmtd = 0;
fmtm = ~0;
@@ -2570,7+2574,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user(AFMT_U8|AFMT_S16_LE, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
fmtd = 0;
fmtm = ~0;
@@ -2615,7+2620,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
@@ -2712,7+2718,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return put_user(s->dma_adc.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
M_printk("maestro: SETFRAGMENT: %0x\n",val);
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = val & 0xffff;
@@ -2740,7+2747,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
(file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
@@ -1419,7+1419,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) switch (cmd)
{
case SOUND_PCM_WRITE_RATE:
- get_user_ret(ret, (int *) arg, -EFAULT);
+ if (get_user(ret, (int *) arg))
+ return -EFAULT;
if (ret != 0) {
oldinfo = card->sinfo[w].samplerate;
@@ -1437,7+1438,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) break;
case SNDCTL_DSP_STEREO:
- get_user_ret(ret, (int *) arg, -EFAULT);
+ if (get_user(ret, (int *) arg))
+ return -EFAULT;
card->sinfo[w].stereo = ret ? 1 : 0;
ret = nm256_setInfo (dev, card);
@@ -1447,7+1449,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) break;
case SOUND_PCM_WRITE_CHANNELS:
- get_user_ret(ret, (int *) arg, -EFAULT);
+ if (get_user(ret, (int *) arg))
+ return -EFAULT;
if (ret < 1 || ret > 3)
ret = card->sinfo[w].stereo + 1;
@@ -1464,7+1467,8 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) break;
case SNDCTL_DSP_SETFMT:
- get_user_ret(ret, (int *) arg, -EFAULT);
+ if (get_user(ret, (int *) arg)
+ return -EFAULT;
if (ret != 0) {
oldinfo = card->sinfo[w].bits;
@@ -1051,7+1051,8 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg) if (cmd == OSS_GETVERSION)
return put_user(SOUND_VERSION, (int *)arg);
if (cmd == SOUND_MIXER_PRIVATE1) { /* SRS settings */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
spin_lock_irqsave(&s->lock, flags);
if (val & 1) {
if (val & 2) {
@@ -1119,7+1120,8 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg) s->mix.modcnt++;
switch (_IOC_NR(cmd)) {
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
i = hweight32(val);
if (i == 0)
return 0; /*val = mixer_recmask(s);*/
@@ -1143,7+1145,8 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg) i = _IOC_NR(cmd);
if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
l = val & 0xff;
r = (val >> 8) & 0xff;
if (mixtable[i].type == MT_4MUTEMONO)
@@ -1582,7+1585,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_READ) {
stop_adc(s);
@@ -1598,7+1602,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
fmtd = 0;
fmtm = ~0;
if (file->f_mode & FMODE_READ) {
@@ -1621,7+1626,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
fmtd = 0;
fmtm = ~0;
@@ -1650,7+1656,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
fmtd = 0;
fmtm = ~0;
@@ -1687,7+1694,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
@@ -1798,7+1806,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(s->dma_adc.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = val & 0xffff;
s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1825,7+1834,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
(file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
@@ -1633,7+1633,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return 0;
case SNDCTL_DSP_SPEED: /* set smaple rate */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1653,7+1654,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return put_user(dmabuf->rate, (int *)arg);
case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
dmabuf->ready = 0;
@@ -1688,7+1690,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Select sample format */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1711,7+1714,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm AFMT_S16_LE : AFMT_U8, (int *)arg);
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
@@ -1740,14+1744,16 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm case SNDCTL_DSP_SUBDIVIDE:
if (dmabuf->subdivision)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
dmabuf->subdivision = val;
return 0;
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
dmabuf->ossfragshift = val & 0xffff;
dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
@@ -1805,7+1811,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
@@ -1881,7+1888,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm if (state->card->pci_id != PCI_DEVICE_ID_SI_7018)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val == DSP_BIND_QUERY) {
val = dmabuf->channel->attribute | 0x3c00;
val = attr2mask[val >> 8];
@@ -1900,7+1900,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* query or set current channel's PCM data format */
case SNDCTL_DSP_SETFMT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
rc = 0;
@@ -1928,7+1929,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* query or set number of channels (1=mono, 2=stereo) */
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
rc = 0;
spin_lock_irq (&card->lock);
@@ -1954,7+1956,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* enable (val is not zero) or disable (val == 0) stereo */
case SNDCTL_DSP_STEREO:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
rc = 0;
spin_lock_irq (&card->lock);
if (rc == 0 && rd)
@@ -1969,7+1972,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* query or set sampling rate */
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val < 0)
return -EINVAL;
if (val > 0) {
@@ -2061,7+2065,8 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* set fragment size. implemented as a successful no-op for now */
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
DPRINTK ("SNDCTL_DSP_SETFRAGMENT (fragshift==0x%04X (%d), maxfrags==0x%04X (%d))\n",
val & 0xFFFF,
@@ -2476,7+2476,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg);
case SNDCTL_DSP_SPEED: /* _SIOWR('P', 2, int) */
- get_user_ret(ival, (int *) arg, -EFAULT);
+ if (get_user(ival, (int *) arg))
+ return -EFAULT;
DBGX("SNDCTL_DSP_SPEED %d\n", ival);
if (ival) {
if (aport->swstate != SW_INITIAL) {
@@ -2497,7+2498,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg);
case SNDCTL_DSP_STEREO: /* _SIOWR('P', 3, int) */
- get_user_ret(ival, (int *) arg, -EFAULT);
+ if (get_user(ival, (int *) arg))
+ return -EFAULT;
DBGX("SNDCTL_DSP_STEREO %d\n", ival);
if (ival != 0 && ival != 1)
return -EINVAL;
@@ -2510,7+2512,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg);
case SNDCTL_DSP_CHANNELS: /* _SIOWR('P', 6, int) */
- get_user_ret(ival, (int *) arg, -EFAULT);
+ if (get_user(ival, (int *) arg))
+ return -EFAULT;
DBGX("SNDCTL_DSP_CHANNELS %d\n", ival);
if (ival != 1 && ival != 2)
return -EINVAL;
@@ -2533,7+2536,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg);
case SNDCTL_DSP_SETFRAGMENT: /* _SIOWR('P',10, int) */
- get_user_ret(ival, (int *) arg, -EFAULT);
+ if (get_user(ival, (int *) arg))
+ return -EFAULT;
DBGX("SNDCTL_DSP_SETFRAGMENT %d:%d\n",
ival >> 16, ival & 0xFFFF);
if (aport->swstate != SW_INITIAL)
@@ -2571,7+2575,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg);
case SNDCTL_DSP_SUBDIVIDE: /* _SIOWR('P', 9, int) */
- get_user_ret(ival, (int *) arg, -EFAULT);
+ if (get_user(ival, (int *) arg))
+ return -EFAULT;
DBGX("SNDCTL_DSP_SUBDIVIDE %d\n", ival);
if (aport->swstate != SW_INITIAL)
return -EINVAL;
@@ -2601,7+2606,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return 0;
case SNDCTL_DSP_SETFMT: /* _SIOWR('P',5, int) */
- get_user_ret(ival, (int *) arg, -EFAULT);
+ if (get_user(ival, (int *) arg))
+ return -EFAULT;
DBGX("SNDCTL_DSP_SETFMT %d\n", ival);
if (ival != AFMT_QUERY) {
if (aport->swstate != SW_INITIAL) {
@@ -2809,7+2815,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, return put_user(ival, (int *) arg);
case SNDCTL_DSP_SETTRIGGER: /* _SIOW ('P',16, int) */
- get_user_ret(ival, (int *) arg, -EFAULT);
+ if (get_user(ival, (int *) arg))
+ return -EFAULT;
DBGX("SNDCTL_DSP_SETTRIGGER %d\n", ival);
/*
@@ -1628,7+1628,8 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) u_int prev_spkr_mute, prev_line_mute, prev_auto_state;
int val;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
/* check if parameter is logical */
if (val & ~(VNC_MUTE_INTERNAL_SPKR |
@@ -1657,7+1658,8 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) }
case SOUND_MIXER_PRIVATE2:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
switch (val) {
#define VNC_SOUND_PAUSE 0x53 //to pause the DSP
@@ -1681,8+1683,10 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) unsigned long flags;
int mixer_reg[15], i, val;
- get_user_ret(val, (int *)arg, -EFAULT);
- copy_from_user_ret(mixer_reg, (void *)val, sizeof(mixer_reg), -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (copy_from_user(mixer_reg, (void *)val, sizeof(mixer_reg)))
+ return -EFAULT;
switch (mixer_reg[14]) {
case MIXER_PRIVATE3_RESET:
@@ -1708,7+1712,8 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg)
spin_unlock_irqrestore(&waveartist_lock, flags);
- copy_to_user_ret((void *)val, mixer_reg, sizeof(mixer_reg), -EFAULT);
+ if (copy_to_user((void *)val, mixer_reg, sizeof(mixer_reg)))
+ return -EFAULT;
break;
default:
@@ -559,7+559,8 @@ static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void *b rem = db->dmasize - ptr;
if (pgrem > rem)
pgrem = rem;
- copy_from_user_ret((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem, -EFAULT);
+ if (copy_from_user((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem))
+ return -EFAULT;
size -= pgrem;
(char *)buffer += pgrem;
ptr += pgrem;
@@ -583,7+584,8 @@ static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void *buffer rem = db->dmasize - ptr;
if (pgrem > rem)
pgrem = rem;
- copy_to_user_ret(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem, -EFAULT);
+ if (copy_to_user(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem))
+ return -EFAULT;
size -= pgrem;
(char *)buffer += pgrem;
ptr += pgrem;
@@ -2029,7+2031,8 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign ms->modcnt++;
switch (_IOC_NR(cmd)) {
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
return set_rec_src(ms, val);
default:
@@ -2039,7+2042,8 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++);
if (j >= ms->numch)
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (wrmixer(ms, j, val))
return -EIO;
return put_user(ms->ch[j].value, (int *)arg);
@@ -2352,7+2356,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return 0;
case SNDCTL_DSP_SPEED:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val >= 0) {
if (val < 4000)
val = 4000;
@@ -2370,7+2375,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return 0;
case SNDCTL_DSP_CHANNELS:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 0) {
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
if (val == 1)
@@ -2388,7+2394,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != AFMT_QUERY) {
if (hweight32(val) != 1)
return -EINVAL;
@@ -2415,7+2422,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as)))
@@ -2509,7+2517,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int return put_user(as->usbin.dma.fragsize, (int *)arg);
case SNDCTL_DSP_SETFRAGMENT:
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (file->f_mode & FMODE_READ) {
as->usbin.dma.ossfragshift = val & 0xffff;
as->usbin.dma.ossmaxfrags = (val >> 16) & 0xffff;
@@ -2536,7+2545,8 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) ||
(file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision))
return -EINVAL;
- get_user_ret(val, (int *)arg, -EFAULT);
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
@@ -607,7+607,8 @@ static int proc_control(struct dev_state *ps, void *arg) unsigned char *tbuf;
int i, ret;
- copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
+ if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl)))
+ return -EFAULT;
switch (ctrl.requesttype & 0x1f) {
case USB_RECIP_ENDPOINT:
if ((ret = findintfep(ps->dev, ctrl.index & 0xff)) < 0)
@@ -636,11+637,13 @@ static int proc_control(struct dev_state *ps, void *arg) i = my_usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
if ((i > 0) && ctrl.length) {
- copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
+ if (copy_to_user(ctrl.data, tbuf, ctrl.length))
+ return -EFAULT;
}
} else {
if (ctrl.length) {
- copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
+ if (copy_from_user(tbuf, ctrl.data, ctrl.length))
+ return -EFAULT;
}
i = my_usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
@@ -662,7+665,8 @@ static int proc_bulk(struct dev_state *ps, void *arg) unsigned char *tbuf;
int i, ret;
- copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
+ if (copy_from_user(&bulk, (void *)arg, sizeof(bulk)))
+ return -EFAULT;
if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
return ret;
if ((ret = checkintf(ps, ret)))
@@ -686,11+690,13 @@ static int proc_bulk(struct dev_state *ps, void *arg) }
i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
if (!i && len2) {
- copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
+ if (copy_to_user(bulk.data, tbuf, len2))
+ return -EFAULT;
}
} else {
if (len1) {
- copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
+ if (copy_from_user(tbuf, bulk.data, len1))
+ return -EFAULT;
}
i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
}
@@ -708,7+714,8 @@ static int proc_resetep(struct dev_state *ps, void *arg) unsigned int ep;
int ret;
- get_user_ret(ep, (unsigned int *)arg, -EFAULT);
+ if (get_user(ep, (unsigned int *)arg))
+ return -EFAULT;
if ((ret = findintfep(ps->dev, ep)) < 0)
return ret;
if ((ret = checkintf(ps, ret)))
@@ -723,7+730,8 @@ static int proc_clearhalt(struct dev_state *ps, void *arg) int pipe;
int ret;
- get_user_ret(ep, (unsigned int *)arg, -EFAULT);
+ if (get_user(ep, (unsigned int *)arg))
+ return -EFAULT;
if ((ret = findintfep(ps->dev, ep)) < 0)
return ret;
if ((ret = checkintf(ps, ret)))
@@ -743,7+751,8 @@ static int proc_getdriver(struct dev_state *ps, void *arg) struct usb_interface *interface;
int ret;
- copy_from_user_ret(&gd, arg, sizeof(gd), -EFAULT);
+ if (copy_from_user(&gd, arg, sizeof(gd)))
+ return -EFAULT;
if ((ret = findintfif(ps->dev, gd.interface)) < 0)
return ret;
interface = usb_ifnum_to_if(ps->dev, gd.interface);
@@ -752,7+761,8 @@ static int proc_getdriver(struct dev_state *ps, void *arg) if (!interface->driver)
return -ENODATA;
strcpy(gd.driver, interface->driver->name);
- copy_to_user_ret(arg, &gd, sizeof(gd), -EFAULT);
+ if (copy_to_user(arg, &gd, sizeof(gd)))
+ return -EFAULT;
return 0;
}
@@ -762,7+772,8 @@ static int proc_connectinfo(struct dev_state *ps, void *arg)
ci.devnum = ps->dev->devnum;
ci.slow = ps->dev->slow;
- copy_to_user_ret(arg, &ci, sizeof(ci), -EFAULT);
+ if (copy_to_user(arg, &ci, sizeof(ci)))
+ return -EFAULT;
return 0;
}
@@ -798,7+809,8 @@ static int proc_setintf(struct dev_state *ps, void *arg) struct usb_interface *interface;
int ret;
- copy_from_user_ret(&setintf, arg, sizeof(setintf), -EFAULT);
+ if (copy_from_user(&setintf, arg, sizeof(setintf)))
+ return -EFAULT;
if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
return ret;
interface = usb_ifnum_to_if(ps->dev, setintf.interface);
@@ -817,7+829,8 @@ static int proc_setconfig(struct dev_state *ps, void *arg) {
unsigned int u;
- get_user_ret(u, (unsigned int *)arg, -EFAULT);
+ if (get_user(u, (unsigned int *)arg))
+ return -EFAULT;
if (usb_set_configuration(ps->dev, u) < 0)
return -EINVAL;
return 0;
@@ -831,7+844,8 @@ static int proc_submiturb(struct dev_state *ps, void *arg) unsigned int u, totlen, isofrmlen;
int ret;
- copy_from_user_ret(&uurb, arg, sizeof(uurb), -EFAULT);
+ if (copy_from_user(&uurb, arg, sizeof(uurb)))
+ return -EFAULT;
if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD))
return -EINVAL;
if (!uurb.buffer)
@@ -948,18+962,22 @@ static int processcompl(struct async *as) if (as->userbuffer)
if (copy_to_user(as->userbuffer, as->urb.transfer_buffer, as->urb.transfer_buffer_length))
return -EFAULT;
- put_user_ret(as->urb.status, &((struct usbdevfs_urb *)as->userurb)->status, -EFAULT);
- put_user_ret(as->urb.actual_length, &((struct usbdevfs_urb *)as->userurb)->actual_length, -EFAULT);
- put_user_ret(as->urb.error_count, &((struct usbdevfs_urb *)as->userurb)->error_count, -EFAULT);
+ if (put_user(as->urb.status,
+ &((struct usbdevfs_urb *)as->userurb)->status) ||
+ __put_user(as->urb.actual_length,
+ &((struct usbdevfs_urb *)as->userurb)->actual_length) ||
+ __put_user(as->urb.error_count,
+ &((struct usbdevfs_urb *)as->userurb)->error_count))
+ return -EFAULT;
+
if (!(usb_pipeisoc(as->urb.pipe)))
return 0;
for (i = 0; i < as->urb.number_of_packets; i++) {
- put_user_ret(as->urb.iso_frame_desc[i].actual_length,
- &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length,
- -EFAULT);
- put_user_ret(as->urb.iso_frame_desc[i].status,
- &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status,
- -EFAULT);
+ if (put_user(as->urb.iso_frame_desc[i].actual_length,
+ &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length) ||
+ __put_user(as->urb.iso_frame_desc[i].status,
+ &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))
+ return -EFAULT;
}
return 0;
}
@@ -990,7+1008,8 @@ static int proc_reapurb(struct dev_state *ps, void *arg) free_async(as);
if (ret)
return ret;
- put_user_ret(addr, (void **)arg, -EFAULT);
+ if (put_user(addr, (void **)arg))
+ return -EFAULT;
return 0;
}
if (signal_pending(current))
@@ -1011,7+1030,8 @@ static int proc_reapurbnonblock(struct dev_state *ps, void *arg) free_async(as);
if (ret)
return ret;
- put_user_ret(addr, (void **)arg, -EFAULT);
+ if (put_user(addr, (void **)arg))
+ return -EFAULT;
return 0;
}
@@ -1019,7+1039,8 @@ static int proc_disconnectsignal(struct dev_state *ps, void *arg) {
struct usbdevfs_disconnectsignal ds;
- copy_from_user_ret(&ds, arg, sizeof(ds), -EFAULT);
+ if (copy_from_user(&ds, arg, sizeof(ds)))
+ return -EFAULT;
if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX))
return -EINVAL;
ps->discsignr = ds.signr;
@@ -1032,7+1053,8 @@ static int proc_claiminterface(struct dev_state *ps, void *arg) unsigned int intf;
int ret;
- get_user_ret(intf, (unsigned int *)arg, -EFAULT);
+ if (get_user(intf, (unsigned int *)arg))
+ return -EFAULT;
if ((ret = findintfif(ps->dev, intf)) < 0)
return ret;
return claimintf(ps, ret);
@@ -1043,7+1065,8 @@ static int proc_releaseinterface(struct dev_state *ps, void *arg) unsigned int intf;
int ret;
- get_user_ret(intf, (unsigned int *)arg, -EFAULT);
+ if (get_user(intf, (unsigned int *)arg))
+ return -EFAULT;
if ((ret = findintfif(ps->dev, intf)) < 0)
return ret;
return releaseintf(ps, intf);
@@ -1057,7+1080,8 @@ static int proc_ioctl (struct dev_state *ps, void *arg) int retval = 0;
/* get input parameters and alloc buffer */
- copy_from_user_ret (&ctrl, (void *) arg, sizeof (ctrl), -EFAULT);
+ if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl)))
+ return -EFAULT;
if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
if ((buf = kmalloc (size, GFP_KERNEL)) == 0)
return -ENOMEM;
@@ -113,15+113,15 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, data = (void *) arg;
if (data == NULL)
break;
- copy_from_user_ret(&rio_cmd, data, sizeof(struct RioCommand),
- -EFAULT);
+ if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand)))
+ return -EFAULT;
if (rio_cmd.length > PAGE_SIZE)
return -EINVAL;
buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
if (buffer == NULL)
return -ENOMEM;
- copy_from_user_ret(buffer, rio_cmd.buffer, rio_cmd.length,
- -EFAULT);
+ if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length))
+ return -EFAULT;
requesttype = rio_cmd.requesttype | USB_DIR_IN |
USB_TYPE_VENDOR | USB_RECIP_DEVICE;
@@ -150,8+150,9 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, dbg("Executed ioctl. Result = %d (data=%04x)",
le32_to_cpu(result),
le32_to_cpu(*((long *) buffer)));
- copy_to_user_ret(rio_cmd.buffer, buffer,
- rio_cmd.length, -EFAULT);
+ if (copy_to_user(rio_cmd.buffer, buffer,
+ rio_cmd.length))
+ return -EFAULT;
retries = 0;
}
@@ -170,15+171,15 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, data = (void *) arg;
if (data == NULL)
break;
- copy_from_user_ret(&rio_cmd, data, sizeof(struct RioCommand),
- -EFAULT);
+ if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand)))
+ return -EFAULT;
if (rio_cmd.length > PAGE_SIZE)
return -EINVAL;
buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
if (buffer == NULL)
return -ENOMEM;
- copy_from_user_ret(buffer, rio_cmd.buffer, rio_cmd.length,
- -EFAULT);
+ if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length))
+ return -EFAULT;
requesttype = rio_cmd.requesttype | USB_DIR_OUT |
USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-/* $Id: atyfb.c,v 1.146 2000/07/26 23:02:51 davem Exp $
+/* $Id: atyfb.c,v 1.147 2000/08/29 07:01:56 davem Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -3010,7+3010,8 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, fbtyp.fb_depth = info->current_par.crtc.bpp;
fbtyp.fb_cmsize = disp->cmap.len;
fbtyp.fb_size = info->total_vram;
- copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
+ if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp)))
+ return -EFAULT;
break;
#endif /* __sparc__ */
#ifdef DEBUG
@@ -3031,8+3032,8 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, clk.dsp_precision = (dsp_config>>20) & 7;
clk.dsp_on = dsp_on_off & 0x7ff;
clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
- copy_to_user_ret((struct atyclk *)arg, &clk, sizeof(clk),
- -EFAULT);
+ if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk)))
+ return -EFAULT;
} else
return -EINVAL;
break;
@@ -3040,8+3041,8 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
struct atyclk clk;
struct pll_ct *pll = &info->current_par.pll.ct;
- copy_from_user_ret(&clk, (struct atyclk *)arg, sizeof(clk),
- -EFAULT);
+ if (copy_from_user(&clk, (struct atyclk *)arg, sizeof(clk)))
+ return -EFAULT;
info->ref_clk_per = clk.ref_clk_per;
pll->pll_ref_div = clk.pll_ref_div;
pll->mclk_fb_div = clk.mclk_fb_div;
-/* $Id: cgfourteenfb.c,v 1.7 1999/11/19 09:57:01 davem Exp $
+/* $Id: cgfourteenfb.c,v 1.8 2000/08/29 07:01:56 davem Exp $
* cgfourteenfb.c: CGfourteen frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -299,15+299,17 @@ static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned lon break;
case MDI_GET_CFGINFO:
mdii = (struct mdi_cfginfo *)arg;
- put_user_ret(FBTYPE_MDICOLOR, &mdii->mdi_type, -EFAULT);
- __put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT);
- __put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT);
- __put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT);
- __put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */
- __put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT);
+ if (put_user(FBTYPE_MDICOLOR, &mdii->mdi_type) ||
+ __put_user(fb->type.fb_height, &mdii->mdi_height) ||
+ __put_user(fb->type.fb_width, &mdii->mdi_width) ||
+ __put_user(fb->s.cg14.mode, &mdii->mdi_mode) ||
+ __put_user(72, &mdii->mdi_pixfreq) || /* FIXME */
+ __put_user(fb->s.cg14.ramsize, &mdii->mdi_size))
+ return -EFAULT;
break;
case MDI_SET_PIXELMODE:
- get_user_ret(mode, (int *)arg, -EFAULT);
+ if (get_user(mode, (int *)arg))
+ return -EFAULT;
spin_lock_irqsave(&fb->lock, flags);
tmp = sbus_readb(mcr);
@@ -1030,7+1030,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, err = matroxfb_get_vblank(PMINFO &vblank);
if (err)
return err;
- copy_to_user_ret((struct fb_vblank*)arg, &vblank, sizeof(vblank), -EFAULT);
+ if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank)))
+ return -EFAULT;
return 0;
}
case MATROXFB_SET_OUTPUT_MODE:
@@ -1038,7+1039,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, struct matroxioc_output_mode mom;
int val;
- copy_from_user_ret(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom), -EFAULT);
+ if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
+ return -EFAULT;
if (mom.output >= sizeof(u_int32_t))
return -EINVAL;
switch (mom.output) {
@@ -1084,7+1086,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, struct matroxioc_output_mode mom;
int val;
- copy_from_user_ret(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom), -EFAULT);
+ if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
+ return -EFAULT;
if (mom.output >= sizeof(u_int32_t))
return -EINVAL;
switch (mom.output) {
@@ -1108,14+1111,16 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, default:
return -EINVAL;
}
- copy_to_user_ret((struct matroxioc_output_mode*)arg, &mom, sizeof(mom), -EFAULT);
+ if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom)))
+ return -EFAULT;
return 0;
}
case MATROXFB_SET_OUTPUT_CONNECTION:
{
u_int32_t tmp;
- copy_from_user_ret(&tmp, (u_int32_t*)arg, sizeof(tmp), -EFAULT);
+ if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp)))
+ return -EFAULT;
if (tmp & ~ACCESS_FBINFO(output.all))
return -EINVAL;
if (tmp & ACCESS_FBINFO(output.sh))
@@ -1134,7+1139,8 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, }
case MATROXFB_GET_OUTPUT_CONNECTION:
{
- put_user_ret(ACCESS_FBINFO(output.ph), (u_int32_t*)arg, -EFAULT);
+ if (put_user(ACCESS_FBINFO(output.ph), (u_int32_t*)arg))
+ return -EFAULT;
return 0;
}
case MATROXFB_GET_AVAILABLE_OUTPUTS:
@@ -1146,12+1152,14 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, tmp &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY)
tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
- put_user_ret(tmp, (u_int32_t*)arg, -EFAULT);
+ if (put_user(tmp, (u_int32_t*)arg))
+ return -EFAULT;
return 0;
}
case MATROXFB_GET_ALL_OUTPUTS:
{
- put_user_ret(ACCESS_FBINFO(output.all), (u_int32_t*)arg, -EFAULT);
+ if (put_user(ACCESS_FBINFO(output.all), (u_int32_t*)arg))
+ return -EFAULT;
return 0;
}
}
@@ -509,7+509,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, err = matroxfb_dh_get_vblank(m2info, &vblank);
if (err)
return err;
- copy_to_user_ret((struct fb_vblank*)arg, &vblank, sizeof(vblank), -EFAULT);
+ if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank)))
+ return -EFAULT;
return 0;
}
case MATROXFB_SET_OUTPUT_MODE:
@@ -522,7+523,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, {
u_int32_t tmp;
- get_user_ret(tmp, (u_int32_t*)arg, -EFAULT);
+ if (get_user(tmp, (u_int32_t*)arg))
+ return -EFAULT;
if (tmp & ~ACCESS_FBINFO(output.all))
return -EINVAL;
if (tmp & ACCESS_FBINFO(output.ph))
@@ -539,7+541,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, }
case MATROXFB_GET_OUTPUT_CONNECTION:
{
- put_user_ret(ACCESS_FBINFO(output.sh), (u_int32_t*)arg, -EFAULT);
+ if (put_user(ACCESS_FBINFO(output.sh), (u_int32_t*)arg))
+ return -EFAULT;
return 0;
}
case MATROXFB_GET_AVAILABLE_OUTPUTS:
@@ -551,7+554,8 @@ static int matroxfb_dh_ioctl(struct inode* inode, /* CRTC1 in DFP mode disables CRTC2 at all (I know, I'm lazy) */
if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP)
tmp = 0;
- put_user_ret(tmp, (u_int32_t*)arg, -EFAULT);
+ if (put_user(tmp, (u_int32_t*)arg))
+ return -EFAULT;
return 0;
}
}
@@ -584,22+584,26 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
switch (cmd){
case FBIOGTYPE: /* return frame buffer type */
- copy_to_user_ret((struct fbtype *)arg, &fb->type, sizeof(struct fbtype), -EFAULT);
+ if (copy_to_user((struct fbtype *)arg, &fb->type, sizeof(struct fbtype)))
+ return -EFAULT;
break;
case FBIOGATTR: {
struct fbgattr *fba = (struct fbgattr *) arg;
i = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct fbgattr));
if (i) return i;
- __put_user_ret(fb->emulations[0], &fba->real_type, -EFAULT);
- __put_user_ret(0, &fba->owner, -EFAULT);
- __copy_to_user_ret(&fba->fbtype, &fb->type,
- sizeof(struct fbtype), -EFAULT);
- __put_user_ret(0, &fba->sattr.flags, -EFAULT);
- __put_user_ret(fb->type.fb_type, &fba->sattr.emu_type, -EFAULT);
- __put_user_ret(-1, &fba->sattr.dev_specific[0], -EFAULT);
- for (i = 0; i < 4; i++)
- put_user_ret(fb->emulations[i], &fba->emu_types[i], -EFAULT);
+ if (__put_user(fb->emulations[0], &fba->real_type) ||
+ __put_user(0, &fba->owner) ||
+ __copy_to_user(&fba->fbtype, &fb->type,
+ sizeof(struct fbtype)) ||
+ __put_user(0, &fba->sattr.flags) ||
+ __put_user(fb->type.fb_type, &fba->sattr.emu_type) ||
+ __put_user(-1, &fba->sattr.dev_specific[0]))
+ return -EFAULT;
+ for (i = 0; i < 4; i++) {
+ if (put_user(fb->emulations[i], &fba->emu_types[i]))
+ return -EFAULT;
+ }
break;
}
case FBIOSATTR:
@@ -612,7+616,8 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, if (vt_cons[lastconsole]->vc_mode == KD_TEXT)
break;
}
- get_user_ret(i, (int *)arg, -EFAULT);
+ if (get_user(i, (int *)arg))
+ return -EFAULT;
if (i){
if (!fb->blanked || !fb->unblank)
break;
@@ -627,7+632,8 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, }
break;
case FBIOGVIDEO:
- put_user_ret(fb->blanked, (int *) arg, -EFAULT);
+ if (put_user(fb->blanked, (int *) arg))
+ return -EFAULT;
break;
case FBIOGETCMAP_SPARC: {
char *rp, *gp, *bp;
@@ -639,23+645,29 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap));
if (i) return i;
cmap = (struct fbcmap *) arg;
- __get_user_ret(count, &cmap->count, -EFAULT);
- __get_user_ret(index, &cmap->index, -EFAULT);
+ if (__get_user(count, &cmap->count) ||
+ __get_user(index, &cmap->index))
+ return -EFAULT;
if ((index < 0) || (index > 255))
return -EINVAL;
if (index + count > 256)
count = 256 - index;
- __get_user_ret(rp, &cmap->red, -EFAULT);
- __get_user_ret(gp, &cmap->green, -EFAULT);
- __get_user_ret(bp, &cmap->blue, -EFAULT);
- if(verify_area (VERIFY_WRITE, rp, count)) return -EFAULT;
- if(verify_area (VERIFY_WRITE, gp, count)) return -EFAULT;
- if(verify_area (VERIFY_WRITE, bp, count)) return -EFAULT;
+ if (__get_user(rp, &cmap->red) ||
+ __get_user(gp, &cmap->green) ||
+ __get_user(bp, &cmap->blue))
+ return -EFAULT;
+ if (verify_area (VERIFY_WRITE, rp, count))
+ return -EFAULT;
+ if (verify_area (VERIFY_WRITE, gp, count))
+ return -EFAULT;
+ if (verify_area (VERIFY_WRITE, bp, count))
+ return -EFAULT;
end = index + count;
for (i = index; i < end; i++){
- __put_user_ret(fb->color_map CM(i,0), rp, -EFAULT);
- __put_user_ret(fb->color_map CM(i,1), gp, -EFAULT);
- __put_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
+ if (__put_user(fb->color_map CM(i,0), rp) ||
+ __put_user(fb->color_map CM(i,1), gp) ||
+ __put_user(fb->color_map CM(i,2), bp))
+ return -EFAULT;
rp++; gp++; bp++;
}
(*fb->loadcmap)(fb, NULL, index, count);
@@ -671,24+683,32 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap));
if (i) return i;
cmap = (struct fbcmap *) arg;
- __get_user_ret(count, &cmap->count, -EFAULT);
- __get_user_ret(index, &cmap->index, -EFAULT);
+ if (__get_user(count, &cmap->count) ||
+ __get_user(index, &cmap->index))
+ return -EFAULT;
if ((index < 0) || (index > 255))
return -EINVAL;
if (index + count > 256)
count = 256 - index;
- __get_user_ret(rp, &cmap->red, -EFAULT);
- __get_user_ret(gp, &cmap->green, -EFAULT);
- __get_user_ret(bp, &cmap->blue, -EFAULT);
- if(verify_area (VERIFY_READ, rp, count)) return -EFAULT;
- if(verify_area (VERIFY_READ, gp, count)) return -EFAULT;
- if(verify_area (VERIFY_READ, bp, count)) return -EFAULT;
+ if (__get_user(rp, &cmap->red) ||
+ __get_user(gp, &cmap->green) ||
+ __get_user(bp, &cmap->blue))
+ return -EFAULT;
+ if (verify_area (VERIFY_READ, rp, count))
+ return -EFAULT;
+ if (verify_area (VERIFY_READ, gp, count))
+ return -EFAULT;
+ if (verify_area (VERIFY_READ, bp, count))
+ return -EFAULT;
end = index + count;
for (i = index; i < end; i++){
- __get_user_ret(fb->color_map CM(i,0), rp, -EFAULT);
- __get_user_ret(fb->color_map CM(i,1), gp, -EFAULT);
- __get_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
+ if (__get_user(fb->color_map CM(i,0), rp))
+ return -EFAULT;
+ if (__get_user(fb->color_map CM(i,1), gp))
+ return -EFAULT;
+ if (__get_user(fb->color_map CM(i,2), bp))
+ return -EFAULT;
rp++; gp++; bp++;
}
(*fb->loadcmap)(fb, NULL, index, count);
@@ -699,8+719,9 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, if (!fb->setcursor) return -EINVAL;
if(verify_area (VERIFY_WRITE, p, sizeof (struct fbcurpos)))
return -EFAULT;
- __put_user_ret(fb->cursor.hwsize.fbx, &p->fbx, -EFAULT);
- __put_user_ret(fb->cursor.hwsize.fby, &p->fby, -EFAULT);
+ if (__put_user(fb->cursor.hwsize.fbx, &p->fbx) ||
+ __put_user(fb->cursor.hwsize.fby, &p->fby))
+ return -EFAULT;
break;
}
case FBIOSCURSOR:
/*
- * SiS 300/630/540 frame buffer device For Kernal 2.3.x
+ * SiS 300/630/540 frame buffer device For Kernal 2.4.x
*
* This driver is partly based on the VBE 2.0 compliant graphic
* boards framebuffer driver, which is
#define EXPORT_SYMTAB
#undef SISFBDEBUG
+#undef CONFIG_FB_SIS_LINUXBIOS
#include <linux/module.h>
#include <linux/kernel.h>
@@ -174,11+175,10 @@ static struct board { u16 vendor, device;
const char *name;
} dev_list[] = {
- {
- PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"}, {
- PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5300, "SIS 540"}, {
- PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_6300, "SIS 630"}, {
- 0, 0, NULL}
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"},
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540"},
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630"},
+ {0, 0, NULL}
};
/* card parameters */
@@ -192,9+192,16 @@ static int video_cmap_len; static int sisfb_off = 0;
static struct fb_var_screeninfo default_var = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0,
+ 0,
+ 0,
+ {0, 8, 0},
+ {0, 8, 0},
+ {0, 8, 0},
+ {0, 0, 0},
+ 0,
+ FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
0,
FB_VMODE_NONINTERLACED,
{0, 0, 0, 0, 0, 0}
@@ -202,9+209,11 @@ static struct fb_var_screeninfo default_var = {
static struct display disp;
static struct fb_info fb_info;
+
static struct {
u16 blue, green, red, pad;
} palette[256];
+
static union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
@@ -230,7+239,7 @@ u16 P3c4, P3d4, P3c0, P3ce, P3c2, P3ca, P3c6, P3c7, P3c8, P3c9, P3da; u16 CRT1VCLKLen;
u16 flag_clearbuffer;
u16 CRT1VCLKLen;
-int ModeIDOffset, StandTable, CRT1Table, ScreenOffset, MCLKData, ECLKData;
+int ModeIDOffset, StandTable, CRT1Table, ScreenOffset;
int REFIndex, ModeType;
int VCLKData;
int RAMType;
@@ -249,26+258,25 @@ static const struct _sisbios_mode { u16 cols;
u16 rows;
} sisbios_mode[] = {
- {
- "640x480x8", 0x2E, 640, 480, 8, 1, 80, 30}, {
- "640x480x16", 0x44, 640, 480, 16, 1, 80, 30}, {
- "640x480x32", 0x62, 640, 480, 32, 1, 80, 30}, {
- "800x600x8", 0x30, 800, 600, 8, 2, 100, 37}, {
- "800x600x16", 0x47, 800, 600, 16, 2, 100, 37}, {
- "800x600x32", 0x63, 800, 600, 32, 2, 100, 37}, {
- "1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48}, {
- "1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48}, {
- "1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48}, {
- "1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64}, {
- "1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64}, {
- "1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64}, {
- "1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75}, {
- "1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75}, {
- "1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75}, {
- "1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75}, {
- "1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75}, {
- "1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75}, {
- "\0", 0x00, 0, 0, 0, 0, 0, 0}
+ {"640x480x8", 0x2E, 640, 480, 8, 1, 80, 30},
+ {"640x480x16", 0x44, 640, 480, 16, 1, 80, 30},
+ {"640x480x32", 0x62, 640, 480, 32, 1, 80, 30},
+ {"800x600x8", 0x30, 800, 600, 8, 2, 100, 37},
+ {"800x600x16", 0x47, 800, 600, 16, 2, 100, 37},
+ {"800x600x32", 0x63, 800, 600, 32, 2, 100, 37},
+ {"1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48},
+ {"1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48},
+ {"1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48},
+ {"1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64},
+ {"1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64},
+ {"1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64},
+ {"1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75},
+ {"1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75},
+ {"1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75},
+ {"1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75},
+ {"1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75},
+ {"1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75},
+ {"\0", 0x00, 0, 0, 0, 0, 0, 0}
};
static struct _vrate {
@@ -277,57+285,33 @@ static struct _vrate { u16 yres;
u16 refresh;
} vrate[] = {
- {
- 1, 640, 480, 60}, {
- 2, 640, 480, 72}, {
- 3, 640, 480, 75}, {
- 4, 640, 480, 85}, {
- 5, 640, 480, 100}, {
- 6, 640, 480, 120}, {
- 7, 640, 480, 160}, {
- 8, 640, 480, 200}, {
- 1, 800, 600, 56}, {
- 2, 800, 600, 60}, {
- 3, 800, 600, 72}, {
- 4, 800, 600, 75}, {
- 5, 800, 600, 85}, {
- 6, 800, 600, 100}, {
- 7, 800, 600, 120}, {
- 8, 800, 600, 160}, {
- 1, 1024, 768, 56}, {
- 2, 1024, 768, 60}, {
- 3, 1024, 768, 72}, {
- 4, 1024, 768, 75}, {
- 5, 1024, 768, 85}, {
- 6, 1024, 768, 100}, {
- 7, 1024, 768, 120}, {
- 1, 1280, 1024, 43}, {
- 2, 1280, 1024, 60}, {
- 3, 1280, 1024, 75}, {
- 4, 1280, 1024, 85}, {
- 1, 1600, 1200, 60}, {
- 2, 1600, 1200, 65}, {
- 3, 1600, 1200, 70}, {
- 4, 1600, 1200, 75}, {
- 5, 1600, 1200, 85}, {
- 1, 1920, 1440, 60}, {
- 0, 0, 0, 0}
+ {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85},
+ {5, 640, 480, 100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200},
+ {1, 800, 600, 56}, {2, 800, 600, 60}, {3, 800, 600, 72}, {4, 800, 600, 75},
+ {5, 800, 600, 85}, {6, 800, 600, 100}, {7, 800, 600, 120}, {8, 800, 600, 160},
+ {1, 1024, 768, 43}, {2, 1024, 768, 60}, {3, 1024, 768, 70}, {4, 1024, 768, 75},
+ {5, 1024, 768, 85}, {6, 1024, 768, 100}, {7, 1024, 768, 120},
+ {1, 1280, 1024, 43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85},
+ {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
+ {5, 1600, 1200, 85},
+ {1, 1920, 1440, 60},
+ {0, 0, 0, 0}
};
-
-u16 DRAMType[17][5] =
- { {0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48},
-{0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44},
-{0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40},
-{0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32},
-{0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30},
-{0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28},
-{0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24},
-{0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10},
-{0x09, 0x08, 0x01, 0x01, 0x00}
+u16 DRAMType[17][5] = {
+ {0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48},
+ {0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44},
+ {0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40},
+ {0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32},
+ {0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30},
+ {0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28},
+ {0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24},
+ {0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10},
+ {0x09, 0x08, 0x01, 0x01, 0x00}
};
-u16 MDA_DAC[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+u16 MDA_DAC[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
@@ -337,7+321,8 @@ u16 MDA_DAC[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
};
-u16 CGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+u16 CGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
@@ -347,7+332,8 @@ u16 CGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
};
-u16 EGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
+u16 EGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D,
@@ -357,7+343,8 @@ u16 EGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15, 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
};
-u16 VGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
+u16 VGA_DAC[] = {
+ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
@@ -369,6+356,55 @@ u16 VGA_DAC[] = { 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, 0x0B, 0x0C, 0x0D, 0x0F, 0x10
};
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+
+#define Monitor1Sense 0x20
+
+unsigned char SRegsInit[] = {
+ 0x03, 0x00, 0x03, 0x00, 0x02, 0xa1, 0x00, 0x13,
+ 0x2f, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa1, 0x76, 0xb2, 0xf6, 0x0d, 0x00, 0x00, 0x00,
+ 0x37, 0x61, 0x80, 0x1b, 0xe1, 0x01, 0x55, 0x43,
+ 0x80, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff,
+ 0x8e, 0x40, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff
+};
+
+unsigned char SRegs[] = {
+ 0x03, 0x01, 0x0F, 0x00, 0x0E, 0xA1, 0x02, 0x13,
+ 0x3F, 0x86, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0B, 0x0F, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0xA1, 0xB6, 0xB2, 0xF6, 0x0D, 0x00, 0xF8, 0xF0,
+ 0x37, 0x61, 0x80, 0x1B, 0xE1, 0x80, 0x55, 0x43,
+ 0x80, 0x00, 0x11, 0xFF, 0x00, 0x00, 0x00, 0xFF,
+ 0x8E, 0x40, 0x00, 0x00, 0x08, 0x00, 0xFF, 0xFF
+};
+
+unsigned char CRegs[] = {
+ 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe9, 0x0b, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xa3,
+ 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff
+}; // clear CR11[7]
+
+unsigned char GRegs[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, 0x00
+};
+
+unsigned char ARegs[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char MReg = 0x6f;
+
+#endif
+
+
/* HEAP stuff */
struct OH {
@@ -463,6+499,7 @@ static void set_reg3(u16 port, u16 data); static void set_reg4(u16 port, unsigned long data);
static u8 get_reg1(u16 port, u16 index);
static u8 get_reg2(u16 port);
+//#ifndef CONFIG_FB_SIS_LINUXBIOS
static u32 get_reg3(u16 port);
static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo);
static int search_modeID(unsigned long ROMAddr, u16 ModeNo);
@@ -488,6+525,7 @@ static void set_crt1_FIFO(unsigned long ROMAddr); static void set_crt1_FIFO2(unsigned long ROMAddr);
static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo);
static void set_interlace(unsigned long ROMAddr, u16 ModeNo);
+//#endif
static void write_DAC(u16 dl, u16 ah, u16 al, u16 dh);
static void load_DAC(unsigned long ROMAddr);
static void display_on(void);
@@ -781,6+819,7 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var) sw = &fbcon_cfb8;
break;
#endif
+
#ifdef FBCON_HAS_CFB16
case 15:
case 16:
@@ -788,18+827,21 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var) display->dispsw_data = fbcon_cmap.cfb16;
break;
#endif
+
#ifdef FBCON_HAS_CFB24
case 24:
sw = &fbcon_cfb24;
display->dispsw_data = fbcon_cmap.cfb24;
break;
#endif
+
#ifdef FBCON_HAS_CFB32
case 32:
sw = &fbcon_cfb32;
display->dispsw_data = fbcon_cmap.cfb32;
break;
#endif
+
default:
sw = &fbcon_dummy;
return;
@@ -810,7+852,6 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var)
display->scrollmode = SCROLL_YREDRAW;
sisfb_sw.bmove = fbcon_redraw_bmove;
-
}
/*
@@ -818,9+859,8 @@ static void sisfb_set_disp(int con, struct fb_var_screeninfo *var) * Return != 0 for invalid regno.
*/
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *fb_info)
+static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+ unsigned *transp, struct fb_info *fb_info)
{
if (regno >= video_cmap_len)
return 1;
@@ -838,9+878,8 @@ static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, * entries in the var structure). Return != 0 for invalid regno.
*/
-static int sis_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *fb_info)
+static int sis_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *fb_info)
{
if (regno >= video_cmap_len)
@@ -949,14+988,13 @@ static int do_set_var(struct fb_var_screeninfo *var, int isactive, return 1;
}
- if (search_refresh_rate(ivideo.refresh_rate) == 0) { /* not supported rate */
+ if (search_refresh_rate(ivideo.refresh_rate) == 0) {
+ /* not supported rate */
rate_idx = sisbios_mode[mode_idx].rate_idx;
ivideo.refresh_rate = 60;
}
-
- if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
- && isactive) {
+ if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
pre_setmode();
if (SiSSetMode(mode_no)) {
@@ -1020,7+1058,8 @@ static int sisfb_heap_init(void) struct OH *poh;
u8 jTemp, tq_state;
- if(ivideo.video_size > 0x800000) /* video ram is large than 8M */
+ if (ivideo.video_size > 0x800000)
+ /* video ram is large than 8M */
heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_8M;
else
heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_4M;
@@ -1401,22+1440,28 @@ static u32 get_reg3(u16 port)
static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo)
{
-#if 0
unsigned char ModeID;
u16 modeidlength;
u16 usModeIDOffset;
+ unsigned short PreviousWord,CurrentWord;
- modeidlength = 0;
- usModeIDOffset = *((u16 *) (ROMAddr + 0x20A));
- ModeID = *((unsigned char *) (ROMAddr + usModeIDOffset));
- while (ModeID != 0x2E) {
- modeidlength++;
- usModeIDOffset = usModeIDOffset + 1;
- ModeID = *((unsigned char *) (ROMAddr + usModeIDOffset));
- }
- return (modeidlength);
-#endif
return(10);
+
+ modeidlength=0;
+ usModeIDOffset=*((unsigned short *)(ROMAddr+0x20A)); // Get EModeIDTable
+
+ CurrentWord=*((unsigned short *)(ROMAddr+usModeIDOffset)); // Offset 0x20A
+ PreviousWord=*((unsigned short *)(ROMAddr+usModeIDOffset-2)); // Offset 0x20A
+ while((CurrentWord!=0x2E07)||(PreviousWord!=0x0801))
+ {
+ modeidlength++;
+ usModeIDOffset=usModeIDOffset+1; // 10 <= ExtStructSize
+ CurrentWord=*((unsigned short *)(ROMAddr+usModeIDOffset));
+ PreviousWord=*((unsigned short *)(ROMAddr+usModeIDOffset-2));
+ }
+ modeidlength++;
+
+ return(modeidlength);
}
static int search_modeID(unsigned long ROMAddr, u16 ModeNo)
@@ -1470,8+1515,7 @@ static void get_mode_ptr(unsigned long ROMAddr, u16 ModeNo) StandTable = *((u16 *) (ROMAddr + 0x202));
if (ModeNo <= 13)
- index =
- *((unsigned char *) (ROMAddr + ModeIDOffset + 0x03));
+ index = *((unsigned char *) (ROMAddr + ModeIDOffset + 0x03));
else {
if (ModeType <= 0x02)
index = 0x1B;
@@ -1488,26+1532,40 @@ static void set_seq_regs(unsigned long ROMAddr) unsigned char SRdata;
u16 i;
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ SRdata = SRegs[0x01];
+#else
set_reg1(P3c4, 0x00, 0x03);
StandTable = StandTable + 0x05;
SRdata = *((unsigned char *) (ROMAddr + StandTable));
+#endif
+
SRdata = SRdata | 0x20;
set_reg1(P3c4, 0x01, SRdata);
+
for (i = 02; i <= 04; i++) {
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ SRdata = SRegs[i];
+#else
StandTable++;
SRdata = *((unsigned char *) (ROMAddr + StandTable));
+#endif
set_reg1(P3c4, i, SRdata);
}
}
static void set_misc_regs(unsigned long ROMAddr)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg3(P3c2, 0x23);
+#else
unsigned char Miscdata;
StandTable++;
Miscdata = *((unsigned char *) (ROMAddr + StandTable));
set_reg3(P3c2, Miscdata);
+#endif
}
static void set_crtc_regs(unsigned long ROMAddr)
@@ -1516,13+1574,19 @@ static void set_crtc_regs(unsigned long ROMAddr) u16 i;
CRTCdata = (unsigned char) get_reg1(P3d4, 0x11);
+#ifndef CONFIG_FB_SIS_LINUXBIOS
CRTCdata = CRTCdata & 0x7f;
+#endif
set_reg1(P3d4, 0x11, CRTCdata);
for (i = 0; i <= 0x18; i++) {
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3d4, i, CRegs[i]);
+#else
StandTable++;
CRTCdata = *((unsigned char *) (ROMAddr + StandTable));
set_reg1(P3d4, i, CRTCdata);
+#endif
}
}
@@ -1532,17+1596,23 @@ static void set_attregs(unsigned long ROMAddr) u16 i;
for (i = 0; i <= 0x13; i++) {
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ get_reg2(P3da);
+ set_reg3(P3c0, i);
+ set_reg3(P3c0, ARegs[i]);
+#else
StandTable++;
ARdata = *((unsigned char *) (ROMAddr + StandTable));
get_reg2(P3da);
set_reg3(P3c0, i);
set_reg3(P3c0, ARdata);
+#endif
}
+
get_reg2(P3da);
set_reg3(P3c0, 0x14);
set_reg3(P3c0, 0x00);
-
get_reg2(P3da);
set_reg3(P3c0, 0x20);
}
@@ -1553,15+1623,22 @@ static void set_grc_regs(unsigned long ROMAddr) u16 i;
for (i = 0; i <= 0x08; i++) {
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3ce, i, GRegs[i]);
+#else
StandTable++;
GRdata = *((unsigned char *) (ROMAddr + StandTable));
set_reg1(P3ce, i, GRdata);
+#endif
}
+
+#ifndef CONFIG_FB_SIS_LINUXBIOS
if (ModeType > ModeVGA) {
GRdata = (unsigned char) get_reg1(P3ce, 0x05);
GRdata = GRdata & 0xBF;
set_reg1(P3ce, 0x05, GRdata);
}
+#endif
}
static void ClearExt1Regs(void)
@@ -1637,6+1714,9 @@ static int get_rate_ptr(unsigned long ROMAddr, u16 ModeNo)
static void set_sync(unsigned long ROMAddr)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg3(P3c2, MReg);
+#else
u16 sync;
u16 temp;
@@ -1645,10+1725,33 @@ static void set_sync(unsigned long ROMAddr) temp = 0x2F;
temp = temp | sync;
set_reg3(P3c2, temp);
+#endif
}
static void set_crt1_crtc(unsigned long ROMAddr)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ unsigned char data;
+ u16 i;
+
+ data = (unsigned char) get_reg1(P3d4, 0x11);
+ data = data & 0x7F;
+ set_reg1(P3d4, 0x11, data);
+
+ for (i = 0; i <= 0x07; i++)
+ set_reg1(P3d4, i, CRegs[i]);
+ for (i = 0x10; i <= 0x12; i++)
+ set_reg1(P3d4, i, CRegs[i]);
+ for (i = 0x15; i <= 0x16; i++)
+ set_reg1(P3d4, i, CRegs[i]);
+ for (i = 0x0A; i <= 0x0C; i++)
+ set_reg1(P3c4, i, SRegs[i]);
+
+ data = SRegs[0x0E] & 0xE0;
+ set_reg1(P3c4, 0x0E, data);
+
+ set_reg1(P3d4, 0x09, CRegs[0x09]);
+#else
unsigned char index;
unsigned char data;
u16 i;
@@ -1707,10+1810,16 @@ static void set_crt1_crtc(unsigned long ROMAddr)
if (ModeType > 0x03)
set_reg1(P3d4, 0x14, 0x4F);
+#endif
}
+
static void set_crt1_offset(unsigned long ROMAddr)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3c4, 0x0E, SRegs[0x0E]);
+ set_reg1(P3c4, 0x10, SRegs[0x10]);
+#else
u16 temp, ah, al;
u16 temp2, i;
u16 DisplayUnit;
@@ -1773,6+1882,7 @@ static void set_crt1_offset(unsigned long ROMAddr) else
ah = ah + 2;
set_reg1(P3c4, 0x10, ah);
+#endif
}
static u16 get_vclk_len(unsigned long ROMAddr)
@@ -1792,31+1902,44 @@ static u16 get_vclk_len(unsigned long ROMAddr) static void set_crt1_vclk(unsigned long ROMAddr)
{
u16 i;
+
+#ifndef CONFIG_FB_SIS_LINUXBIOS
unsigned char index, data;
index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
+ index &= 0x03F;
CRT1VCLKLen = get_vclk_len(ROMAddr);
data = index * CRT1VCLKLen;
VCLKData = *((u16 *) (ROMAddr + 0x208));
VCLKData = VCLKData + data;
+#endif
set_reg1(P3c4, 0x31, 0);
for (i = 0x2B; i <= 0x2C; i++) {
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3c4, i, SRegs[i]);
+#else
data = *((unsigned char *) (ROMAddr + VCLKData));
set_reg1(P3c4, i, data);
VCLKData++;
+#endif
}
set_reg1(P3c4, 0x2D, 0x80);
}
-
static void set_vclk_state(unsigned long ROMAddr, u16 ModeNo)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3c4, 0x32, SRegs[0x32]);
+ set_reg1(P3c4, 0x07, SRegs[0x07]);
+#else
+
u16 data, data2;
u16 VCLK;
unsigned char index;
index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
+ index &= 0x3F;
CRT1VCLKLen = get_vclk_len(ROMAddr);
data = index * CRT1VCLKLen;
VCLKData = *((u16 *) (ROMAddr + 0x208));
@@ -1849,6+1972,7 @@ static void set_vclk_state(unsigned long ROMAddr, u16 ModeNo) data = data & 0xFC;
data = data | data2;
set_reg1(P3c4, 0x07, data);
+#endif
}
static u16 calc_delay2(unsigned long ROMAddr, u16 key)
@@ -1926,6+2050,7 @@ static void set_crt1_FIFO(unsigned long ROMAddr) u16 ah, bl, A, B;
index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
+ index &= 0x3F;
CRT1VCLKLen = get_vclk_len(ROMAddr);
data = index * CRT1VCLKLen;
VCLKData = *((u16 *) (ROMAddr + 0x208));
@@ -2017,14+2142,26 @@ static void set_crt1_FIFO(unsigned long ROMAddr) set_reg1(P3c4, 0x09, data2);
}
-
static void set_crt1_FIFO2(unsigned long ROMAddr)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3c4, 0x15, SRegs[0x15]);
+
+ set_reg4(0xcf8, 0x80000050);
+ set_reg4(0xcfc, 0xc5041e04);
+
+ set_reg1(P3c4, 0x08, SRegs[0x08]);
+ set_reg1(P3c4, 0x0F, SRegs[0x0F]);
+ set_reg1(P3c4, 0x3b, 0x00);
+ set_reg1(P3c4, 0x09, SRegs[0x09]);
+#else
+
u16 index, data, VCLK, data2, MCLKOffset, MCLK, colorth = 1;
u16 ah, bl, B;
unsigned long eax;
index = *((unsigned char *) (ROMAddr + REFIndex + 0x03));
+ index &= 0x3F;
CRT1VCLKLen = get_vclk_len(ROMAddr);
data = index * CRT1VCLKLen;
VCLKData = *((u16 *) (ROMAddr + 0x208));
@@ -2115,10+2252,17 @@ static void set_crt1_FIFO2(unsigned long ROMAddr) data2 = data2 & 0xF0;
data2 = data2 | data;
set_reg1(P3c4, 0x09, data2);
+#endif
}
static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3c4, 0x06, SRegs[0x06]);
+ set_reg1(P3c4, 0x01, SRegs[0x01]);
+ set_reg1(P3c4, 0x0F, SRegs[0x0F]);
+ set_reg1(P3c4, 0x21, SRegs[0x21]);
+#else
u16 data, data2, data3;
@@ -2166,11+2310,16 @@ static void set_crt1_mode_regs(unsigned long ROMAddr, u16 ModeNo) else
data = data | 0xA0;
set_reg1(P3c4, 0x21, data);
+#endif
}
-
static void set_interlace(unsigned long ROMAddr, u16 ModeNo)
{
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ set_reg1(P3d4, 0x19, CRegs[0x19]);
+ set_reg1(P3d4, 0x1A, CRegs[0x1A]);
+#else
+
unsigned long Temp;
u16 data, Temp2;
@@ -2201,6+2350,7 @@ static void set_interlace(unsigned long ROMAddr, u16 ModeNo) if (ModeNo == 0x37)
Temp2 = Temp2 | 0x40;
set_reg1(P3d4, 0x1A, (u16) Temp2);
+#endif
}
static void write_DAC(u16 dl, u16 ah, u16 al, u16 dh)
@@ -2239,6+2389,7 @@ static void load_DAC(unsigned long ROMAddr) u16 al, ah, dh;
u16 *table = VGA_DAC;
+#ifndef CONFIG_FB_SIS_LINUXBIOS
data = *((u16 *) (ROMAddr + ModeIDOffset + 0x01));
data = data & DACInfoFlag;
time = 64;
@@ -2252,6+2403,11 @@ static void load_DAC(unsigned long ROMAddr) time = 256;
table = VGA_DAC;
}
+#else
+ time = 256;
+ table = VGA_DAC;
+#endif
+
if (time == 256)
j = 16;
else
@@ -2316,12+2472,339 @@ static void display_on(void) set_reg1(P3c4, 0x01, data);
}
+void SetMemoryClock(void)
+{
+ unsigned char i;
+ int idx;
+
+ u8 MCLK[] = {
+ 0x5A, 0x64, 0x80, 0x66, 0x00, // SDRAM
+ 0xB3, 0x45, 0x80, 0x83, 0x00, // SGRAM
+ 0x37, 0x61, 0x80, 0x00, 0x01, // ESDRAM
+ 0x37, 0x22, 0x80, 0x33, 0x01,
+ 0x37, 0x61, 0x80, 0x00, 0x01,
+ 0x37, 0x61, 0x80, 0x00, 0x01,
+ 0x37, 0x61, 0x80, 0x00, 0x01,
+ 0x37, 0x61, 0x80, 0x00, 0x01
+ };
+
+ u8 ECLK[] = {
+ 0x54, 0x43, 0x80, 0x00, 0x01,
+ 0x53, 0x43, 0x80, 0x00, 0x01,
+ 0x55, 0x43, 0x80, 0x00, 0x01,
+ 0x52, 0x43, 0x80, 0x00, 0x01,
+ 0x3f, 0x42, 0x80, 0x00, 0x01,
+ 0x54, 0x43, 0x80, 0x00, 0x01,
+ 0x54, 0x43, 0x80, 0x00, 0x01,
+ 0x54, 0x43, 0x80, 0x00, 0x01
+ };
+
+ idx = RAMType * 5;
+
+ for (i = 0x28; i <= 0x2A; i++) { // Set MCLK
+ set_reg1(P3c4, i, MCLK[idx]);
+ idx++;
+ }
+
+ idx = RAMType * 5;
+ for (i = 0x2E; i <= 0x30; i++) { // Set ECLK
+ set_reg1(P3c4, i, ECLK[idx]);
+ idx++;
+ }
+}
+
+void ClearDAC(u16 port)
+{
+ int i;
+
+ set_reg3(P3c8, 0x00);
+ for (i = 0; i < (256 * 3); i++)
+ set_reg3(P3c9, 0x00);
+}
+
+void ClearALLBuffer(void)
+{
+ unsigned long AdapterMemorySize;
+
+ AdapterMemorySize = get_reg1(P3c4, 0x14);
+ AdapterMemorySize = AdapterMemorySize & 0x3F;
+ AdapterMemorySize++;
+
+ memset((char *) ivideo.video_vbase, 0, AdapterMemorySize);
+}
+
+void LongWait(void)
+{
+ unsigned long temp;
+
+ for (temp = 1; temp > 0;) {
+ temp = get_reg2(P3da);
+ temp = temp & 0x08;
+ }
+ for (; temp == 0;) {
+ temp = get_reg2(P3da);
+ temp = temp & 0x08;
+ }
+}
+
+void WaitDisplay(void)
+{
+ unsigned short temp;
+
+ for (temp = 0; temp == 0;) {
+ temp = get_reg2(P3da);
+ temp = temp & 0x01;
+ }
+ for (; temp == 1;) {
+ temp = get_reg2(P3da);
+ temp = temp & 0x01;
+ }
+}
+
+int TestMonitorType(unsigned short d1, unsigned short d2, unsigned short d3)
+{
+ unsigned short temp;
+ set_reg3(P3c6, 0xFF);
+ set_reg3(P3c8, 0x00);
+ set_reg3(P3c9, d1);
+ set_reg3(P3c9, d2);
+ set_reg3(P3c9, d3);
+ WaitDisplay(); //wait horizontal retrace
+ temp = get_reg2(P3c2);
+ if (temp & 0x10)
+ return 1;
+ else
+ return 0;
+}
+
+void SetRegANDOR(unsigned short Port, unsigned short Index,
+ unsigned short DataAND, unsigned short DataOR)
+{
+ unsigned short temp1;
+ temp1 = get_reg1(Port, Index); //part1port index 02
+ temp1 = (temp1 & (DataAND)) | DataOR;
+ set_reg1(Port, Index, temp1);
+}
+
+
+int DetectMonitor(void)
+{
+ unsigned short flag1;
+ unsigned short DAC_TEST_PARMS[3] = { 0x0F, 0x0F, 0x0F };
+ unsigned short DAC_CLR_PARMS[3] = { 0x00, 0x00, 0x00 };
+
+ flag1 = get_reg1(P3c4, 0x38); //call BridgeisOn
+ if ((flag1 & 0x20)) {
+ set_reg1(P3d4, 0x30, 0x41);
+ }
+
+ SiSSetMode(0x2E); //set mode to 0x2E instead of 0x3
+
+ ClearDAC(P3c8);
+ ClearALLBuffer();
+
+ LongWait();
+ LongWait();
+
+ flag1 = TestMonitorType(DAC_TEST_PARMS[0], DAC_TEST_PARMS[1],
+ DAC_TEST_PARMS[2]);
+ if (flag1 == 0) {
+ flag1 = TestMonitorType(DAC_TEST_PARMS[0], DAC_TEST_PARMS[1],
+ DAC_TEST_PARMS[2]);
+ }
+
+ if (flag1 == 1) {
+ SetRegANDOR(P3d4, 0x32, ~Monitor1Sense, Monitor1Sense);
+ } else {
+ SetRegANDOR(P3d4, 0x32, ~Monitor1Sense, 0x0);
+ }
+
+ TestMonitorType(DAC_CLR_PARMS[0], DAC_CLR_PARMS[1],
+ DAC_CLR_PARMS[2]);
+
+ set_reg1(P3d4, 0x34, 0x4A);
+
+ return 1;
+}
+
+int SiSInit300(void)
+{
+ //unsigned long ROMAddr = rom_vbase;
+ u16 BaseAddr = (u16) ivideo.vga_base;
+ unsigned char i, temp, AGP;
+ unsigned long j, k, ulTemp;
+ unsigned char SR11, SR19, SR1A, SR21, SR22;
+ unsigned char SR14;
+ unsigned long Temp;
+
+ P3c4 = BaseAddr + 0x14;
+ P3d4 = BaseAddr + 0x24;
+ P3c0 = BaseAddr + 0x10;
+ P3ce = BaseAddr + 0x1e;
+ P3c2 = BaseAddr + 0x12;
+ P3ca = BaseAddr + 0x1a;
+ P3c6 = BaseAddr + 0x16;
+ P3c7 = BaseAddr + 0x17;
+ P3c8 = BaseAddr + 0x18;
+ P3c9 = BaseAddr + 0x19;
+ P3da = BaseAddr + 0x2A;
+
+ set_reg1(P3c4, 0x05, 0x86); // 1.Openkey
+
+ SR14 = (unsigned char) get_reg1(P3c4, 0x14);
+ SR19 = (unsigned char) get_reg1(P3c4, 0x19);
+ SR1A = (unsigned char) get_reg1(P3c4, 0x1A);
+
+ for (i = 0x06; i < 0x20; i++)
+ set_reg1(P3c4, i, 0); // 2.Reset Extended register
+ for (i = 0x21; i <= 0x27; i++)
+ set_reg1(P3c4, i, 0); // Reset Extended register
+ for (i = 0x31; i <= 0x3D; i++)
+ set_reg1(P3c4, i, 0);
+ for (i = 0x30; i <= 0x37; i++)
+ set_reg1(P3d4, i, 0);
+
+#if 0
+ if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan))
+ // 3.Set Define Extended register
+ temp = (unsigned char) SR1A;
+ else {
+ temp = *((unsigned char *) (ROMAddr + SoftSettingAddr));
+ if ((temp & SoftDRAMType) == 0) {
+ // 3.Set Define Extended register
+ temp = (unsigned char) get_reg1(P3c4, 0x3A);
+ }
+ }
+#endif
+
+ // 3.Set Define Extended register
+ temp = (unsigned char) SR1A;
+
+ RAMType = temp & 0x07;
+ SetMemoryClock();
+ for (k = 0; k < 5; k++)
+ for (j = 0; j < 0xffff; j++)
+ ulTemp = (unsigned long) get_reg1(P3c4, 0x05);
+
+ Temp = (unsigned long) get_reg1(P3c4, 0x3C);
+ Temp = Temp | 0x01;
+ set_reg1(P3c4, 0x3C, (unsigned short) Temp);
+ for (k = 0; k < 5; k++)
+ for (j = 0; j < 0xffff; j++)
+ Temp = (unsigned long) get_reg1(P3c4, 0x05);
+
+ Temp = (unsigned long) get_reg1(P3c4, 0x3C);
+ Temp = Temp & 0xFE;
+ set_reg1(P3c4, 0x3C, (unsigned short) Temp);
+ for (k = 0; k < 5; k++)
+ for (j = 0; j < 0xffff; j++)
+ Temp = (unsigned long) get_reg1(P3c4, 0x05);
+
+ //SR07=*((unsigned char *)(ROMAddr+0xA4)); // todo
+ set_reg1(P3c4, 0x07, SRegsInit[0x07]);
+#if 0
+ if (HwDeviceExtension->jChipID == SIS_Glamour)
+ for (i = 0x15; i <= 0x1C; i++) {
+ temp = *((unsigned char *) (ROMAddr + 0xA5 + ((i - 0x15) * 8) + RAMType));
+ set_reg1(P3c4, i, temp);
+ }
+#endif
+
+ //SR1F=*((unsigned char *)(ROMAddr+0xE5));
+ set_reg1(P3c4, 0x1F, SRegsInit[0x1F]);
+
+ // Get AGP
+ AGP = 1;
+ temp = (unsigned char) get_reg1(P3c4, 0x3A);
+ temp = temp & 0x30;
+ if (temp == 0x30)
+ // PCI
+ AGP = 0;
+
+ //SR21=*((unsigned char *)(ROMAddr+0xE6));
+ SR21 = SRegsInit[0x21];
+ if (AGP == 0)
+ SR21 = SR21 & 0xEF; // PCI
+ set_reg1(P3c4, 0x21, SR21);
+
+ //SR22=*((unsigned char *)(ROMAddr+0xE7));
+ SR22 = SRegsInit[0x22];
+ if (AGP == 1)
+ SR22 = SR22 & 0x20; // AGP
+ set_reg1(P3c4, 0x22, SR22);
+
+ //SR23=*((unsigned char *)(ROMAddr+0xE8));
+ set_reg1(P3c4, 0x23, SRegsInit[0x23]);
+
+ //SR24=*((unsigned char *)(ROMAddr+0xE9));
+ set_reg1(P3c4, 0x24, SRegsInit[0x24]);
+
+ //SR25=*((unsigned char *)(ROMAddr+0xEA));
+ set_reg1(P3c4, 0x25, SRegsInit[0x25]);
+
+ //SR32=*((unsigned char *)(ROMAddr+0xEB));
+ set_reg1(P3c4, 0x32, SRegsInit[0x32]);
+
+ SR11 = 0x0F;
+ set_reg1(P3c4, 0x11, SR11);
+
+#if 0
+ if (IF_DEF_LVDS == 1) {
+ //LVDS
+ temp = ExtChipLVDS;
+ } else if (IF_DEF_TRUMPION == 1) {
+ //Trumpion
+ temp = ExtChipTrumpion;
+ } else {
+ //301
+ temp = ExtChip301;
+ }
+#endif
+
+ // 301;
+ temp = 0x02;
+ set_reg1(P3d4, 0x37, temp);
+
+#if 0
+ //09/07/99 modify by domao for 630/540 MM
+ if (HwDeviceExtension->jChipID == SIS_Glamour) {
+ //For SiS 300 Chip
+ SetDRAMSize(HwDeviceExtension);
+ SetDRAMSize(HwDeviceExtension);
+ } else {
+ //For SiS 630/540 Chip
+ //Restore SR14, SR19 and SR1A
+ set_reg1(P3c4, 0x14, SR14);
+ set_reg1(P3c4, 0x19, SR19);
+ set_reg1(P3c4, 0x1A, SR1A);
+ }
+#endif
+
+ set_reg1(P3c4, 0x14, SR14);
+ set_reg1(P3c4, 0x19, SR19);
+ set_reg1(P3c4, 0x1A, SR1A);
+ set_reg3(P3c6, 0xff);
+ ClearDAC(P3c8);
+ DetectMonitor();
+
+#if 0
+ //sense CRT2
+ GetSenseStatus(HwDeviceExtension, BaseAddr, ROMAddr);
+#endif
+
+ return (TRUE);
+}
+
static int SiSSetMode(u16 ModeNo)
{
+ //#ifndef CONFIG_FB_SIS_LINUXBIOS
unsigned long temp;
+ //#endif
+
u16 cr30flag, cr31flag;
unsigned long ROMAddr = rom_vbase;
u16 BaseAddr = (u16) ivideo.vga_base;
+ u_short i;
P3c4 = BaseAddr + 0x14;
P3d4 = BaseAddr + 0x24;
@@ -2335,6+2818,7 @@ static int SiSSetMode(u16 ModeNo) P3c9 = BaseAddr + 0x19;
P3da = BaseAddr + 0x2A;
+#ifndef CONFIG_FB_SIS_LINUXBIOS
temp = search_modeID(ROMAddr, ModeNo);
if (temp == 0)
@@ -2343,39+2827,186 @@ static int SiSSetMode(u16 ModeNo) temp = check_memory_size(ROMAddr);
if (temp == 0)
return (0);
+#endif
+#if 1
cr30flag = (unsigned char) get_reg1(P3d4, 0x30);
if (((cr30flag & 0x01) == 1) || ((cr30flag & 0x02) == 0)) {
+#ifndef CONFIG_FB_SIS_LINUXBIOS
get_mode_ptr(ROMAddr, ModeNo);
+#endif
set_seq_regs(ROMAddr);
set_misc_regs(ROMAddr);
set_crtc_regs(ROMAddr);
set_attregs(ROMAddr);
set_grc_regs(ROMAddr);
ClearExt1Regs();
+
+#ifndef CONFIG_FB_SIS_LINUXBIOS
temp = get_rate_ptr(ROMAddr, ModeNo);
if (temp) {
+#endif
set_sync(ROMAddr);
set_crt1_crtc(ROMAddr);
set_crt1_offset(ROMAddr);
set_crt1_vclk(ROMAddr);
set_vclk_state(ROMAddr, ModeNo);
- if ((ivideo.chip_id == SIS_Trojan)
- || (ivideo.chip_id == SIS_Spartan))
+
+ if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan))
set_crt1_FIFO2(ROMAddr);
else /* SiS 300 */
set_crt1_FIFO(ROMAddr);
+#ifndef CONFIG_FB_SIS_LINUXBIOS
}
+#endif
set_crt1_mode_regs(ROMAddr, ModeNo);
+ if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan))
+ set_interlace(ROMAddr, ModeNo);
+ load_DAC(ROMAddr);
+
+ /* clear OnScreen */
+ memset((char *) ivideo.video_vbase, 0,
+ video_linelength * ivideo.video_height);
+ }
+#else
+ cr30flag = (unsigned char) get_reg1(P3d4, 0x30);
+ if (((cr30flag & 0x01) == 1) || ((cr30flag & 0x02) == 0)) {
+ //set_seq_regs(ROMAddr);
+ {
+ unsigned char SRdata;
+ SRdata = SRegs[0x01] | 0x20;
+ set_reg1(P3c4, 0x01, SRdata);
+
+ for (i = 02; i <= 04; i++)
+ set_reg1(P3c4, i, SRegs[i]);
+ }
+
+ //set_misc_regs(ROMAddr);
+ {
+ set_reg3(P3c2, 0x23);
+ }
+
+ //set_crtc_regs(ROMAddr);
+ {
+ unsigned char CRTCdata;
+
+ CRTCdata = (unsigned char) get_reg1(P3d4, 0x11);
+ set_reg1(P3d4, 0x11, CRTCdata);
+
+ for (i = 0; i <= 0x18; i++)
+ set_reg1(P3d4, i, CRegs[i]);
+ }
+
+ //set_attregs(ROMAddr);
+ {
+ for (i = 0; i <= 0x13; i++) {
+ get_reg2(P3da);
+ set_reg3(P3c0, i);
+ set_reg3(P3c0, ARegs[i]);
+ }
+ get_reg2(P3da);
+ set_reg3(P3c0, 0x14);
+ set_reg3(P3c0, 0x00);
+ get_reg2(P3da);
+ set_reg3(P3c0, 0x20);
+ }
+
+ //set_grc_regs(ROMAddr);
+ {
+ for (i = 0; i <= 0x08; i++)
+ set_reg1(P3ce, i, GRegs[i]);
+ }
+
+ //ClearExt1Regs();
+ {
+ for (i = 0x0A; i <= 0x0E; i++)
+ set_reg1(P3c4, i, 0x00);
+ }
+
+ //set_sync(ROMAddr);
+ {
+ set_reg3(P3c2, MReg);
+ }
+
+ //set_crt1_crtc(ROMAddr);
+ {
+ unsigned char data;
+
+ data = (unsigned char) get_reg1(P3d4, 0x11);
+ data = data & 0x7F;
+ set_reg1(P3d4, 0x11, data);
+
+ for (i = 0; i <= 0x07; i++)
+ set_reg1(P3d4, i, CRegs[i]);
+ for (i = 0x10; i <= 0x12; i++)
+ set_reg1(P3d4, i, CRegs[i]);
+ for (i = 0x15; i <= 0x16; i++)
+ set_reg1(P3d4, i, CRegs[i]);
+ for (i = 0x0A; i <= 0x0C; i++)
+ set_reg1(P3c4, i, SRegs[i]);
+
+ data = SRegs[0x0E] & 0xE0;
+ set_reg1(P3c4, 0x0E, data);
+
+ set_reg1(P3d4, 0x09, CRegs[0x09]);
+
+ }
+
+ //set_crt1_offset(ROMAddr);
+ {
+ set_reg1(P3c4, 0x0E, SRegs[0x0E]);
+ set_reg1(P3c4, 0x10, SRegs[0x10]);
+ }
+
+ //set_crt1_vclk(ROMAddr);
+ {
+ set_reg1(P3c4, 0x31, 0);
+
+ for (i = 0x2B; i <= 0x2C; i++)
+ set_reg1(P3c4, i, SRegs[i]);
+ set_reg1(P3c4, 0x2D, 0x80);
+ }
+
+ //set_vclk_state(ROMAddr, ModeNo);
+ {
+ set_reg1(P3c4, 0x32, SRegs[0x32]);
+ set_reg1(P3c4, 0x07, SRegs[0x07]);
+ }
+
if ((ivideo.chip_id == SIS_Trojan)
- || (ivideo.chip_id ==
- SIS_Spartan)) set_interlace(ROMAddr, ModeNo);
+ || (ivideo.chip_id == SIS_Spartan)) {
+ //set_crt1_FIFO2(ROMAddr);
+ set_reg1(P3c4, 0x15, SRegs[0x15]);
+
+ set_reg4(0xcf8, 0x80000050);
+ set_reg4(0xcfc, 0xc5041e04);
+
+ set_reg1(P3c4, 0x08, SRegs[0x08]);
+ set_reg1(P3c4, 0x0F, SRegs[0x0F]);
+ set_reg1(P3c4, 0x3b, 0x00);
+ set_reg1(P3c4, 0x09, SRegs[0x09]);
+ }
+
+ //set_crt1_mode_regs(ROMAddr, ModeNo);
+ {
+ set_reg1(P3c4, 0x06, SRegs[0x06]);
+ set_reg1(P3c4, 0x01, SRegs[0x01]);
+ set_reg1(P3c4, 0x0F, SRegs[0x0F]);
+ set_reg1(P3c4, 0x21, SRegs[0x21]);
+ }
+
+ if ((ivideo.chip_id == SIS_Trojan) || (ivideo.chip_id == SIS_Spartan)) {
+ //set_interlace(ROMAddr, ModeNo);
+ set_reg1(P3d4, 0x19, CRegs[0x19]);
+ set_reg1(P3d4, 0x1A, CRegs[0x1A]);
+ }
load_DAC(ROMAddr);
/* clear OnScreen */
memset((char *) ivideo.video_vbase, 0,
video_linelength * ivideo.video_height);
}
+#endif
cr31flag = (unsigned char) get_reg1(P3d4, 0x31);
display_on();
@@ -2508,8+3139,7 @@ static int sisfb_get_var(struct fb_var_screeninfo *var, int con, DPRINTK("sisfb: sisfb_get_var:[%d]\n", con);
if (con == -1)
- memcpy(var, &default_var,
- sizeof(struct fb_var_screeninfo));
+ memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
else
*var = fb_display[con].var;
return 0;
@@ -2570,8+3200,8 @@ static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
- fb_copy_cmap(fb_default_cmap(video_cmap_len),
- cmap, kspc ? 0 : 2);
+ fb_copy_cmap(fb_default_cmap(video_cmap_len), cmap, kspc ? 0 : 2);
+
return 0;
}
@@ -2602,12+3232,12 @@ static int sisfb_ioctl(struct inode *inode, struct file *file, {
switch (cmd) {
case FBIO_ALLOC:
- if(!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO))
return -EPERM;
sis_malloc((struct sis_memreq *) arg);
break;
case FBIO_FREE:
- if(!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO))
return -EPERM;
sis_free(*(unsigned long *) arg);
break;
@@ -2668,9+3298,9 @@ static int sisfb_mmap(struct fb_info *info, struct file *file, if (boot_cpu_data.x86 > 3)
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
#endif
- if (io_remap_page_range(vma->vm_start, off,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot)) return -EAGAIN;
+ if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
return 0;
}
@@ -2695,7+3325,7 @@ int sisfb_setup(char *options) if (!options || !*options)
return 0;
- for (this_opt = strtok(options, ","); this_opt;
+ for (this_opt = strtok(options, ","); this_opt;
this_opt = strtok(NULL, ",")) {
if (!*this_opt)
continue;
@@ -2786,10+3416,13 @@ static void sisfb_blank(int blank, struct fb_info *info)
int __init sisfb_init(void)
{
- struct pci_dev *pdev;
+ struct pci_dev *pdev = NULL;
struct board *b;
int pdev_valid = 0;
unsigned char jTemp;
+ u32 cmd;
+
+ outb(0x77, 0x80);
if (sisfb_off)
return -ENXIO;
@@ -2814,12+3447,45 @@ int __init sisfb_init(void) if (!pdev_valid)
return -1;
- ivideo.video_base = pdev->resource[0].start & ~0x7FFFFF;
- ivideo.mmio_base = pdev->resource[1].start & ~0x3FFF;
- ivideo.vga_base = (pdev->resource[2].start & 0xFFFFFC) + 0x30;
- rom_base = 0x000C0000;
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_IO;
+ cmd |= PCI_COMMAND_MEMORY;
+ pci_write_config_dword(pdev, PCI_COMMAND, cmd);
+#endif
+ ivideo.video_base = pci_resource_start(pdev, 0);
+ if (!request_mem_region(ivideo.video_base, pci_resource_len(pdev, 0),
+ "sisfb FB")) {
+ printk(KERN_ERR "sisfb: cannot reserve frame buffer memory\n");
+ return -ENODEV;
+ }
+ ivideo.mmio_base = pci_resource_start(pdev, 1);
+ if (!request_mem_region(ivideo.mmio_base, pci_resource_len(pdev, 1),
+ "sisfb MMIO")) {
+ printk(KERN_ERR "sisfb: cannot reserve MMIO region\n");
+ release_mem_region(pci_resource_start(pdev, 1),
+ pci_resource_len(pdev, 1));
+ return -ENODEV;
+ }
+ ivideo.vga_base = pci_resource_start(pdev, 2);
+ if (!request_region(ivideo.vga_base, pci_resource_len(pdev, 2),
+ "sisfb IO")) {
+ printk(KERN_ERR "sisfb: cannot reserve I/O ports\n");
+ release_mem_region(pci_resource_start(pdev, 1),
+ pci_resource_len(pdev, 1));
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ return -ENODEV;
+ }
+ ivideo.vga_base += 0x30;
+
+#ifndef CONFIG_FB_SIS_LINUXBIOS
+ rom_base = 0x000C0000;
request_region(rom_base, 32, "sisfb");
+#else
+ rom_base = 0x0;
+#endif
/* set passwd */
vgawb(SEQ_ADR, IND_SIS_PASSWORD);
@@ -2839,13+3505,21 @@ int __init sisfb_init(void) if (mode_idx < 0)
mode_idx = DEFAULT_MODE; /* 0:640x480x8 */
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+ mode_idx = DEFAULT_MODE;
+ rate_idx = sisbios_mode[mode_idx].rate_idx;
+ /* set to default refresh rate 60MHz */
+ ivideo.refresh_rate = 60;
+#endif
+
mode_no = sisbios_mode[mode_idx].mode_no;
if (ivideo.refresh_rate != 0)
search_refresh_rate(ivideo.refresh_rate);
if (rate_idx == 0) {
- rate_idx = sisbios_mode[mode_idx].rate_idx; /* set to default refresh rate 60MHz */
+ rate_idx = sisbios_mode[mode_idx].rate_idx;
+ /* set to default refresh rate 60MHz */
ivideo.refresh_rate = 60;
}
@@ -2854,25+3528,14 @@ int __init sisfb_init(void) ivideo.video_height = sisbios_mode[mode_idx].yres;
video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
- if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB"))
- {
- printk(KERN_ERR
- "sisfb: abort, cannot reserve video memory at 0x%lx\n",
- ivideo.video_base);
- return -1;
- }
-
- if (!request_mem_region(ivideo.mmio_base, MMIO_SIZE, "sisfb MMIO"))
- {
- printk(KERN_ERR
- "sisfb: abort, cannot reserve mmio memory at 0x%lx\n",
- ivideo.mmio_base);
- return -1;
- }
-
ivideo.video_vbase = ioremap(ivideo.video_base, ivideo.video_size);
ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE);
+
+#ifndef CONFIG_FB_SIS_LINUXBIOS
rom_vbase = (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);
+#endif
+
+ SiSInit300();
printk(KERN_INFO
"sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
@@ -11,9+11,10 @@ FILESYSTEMS = $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o)) O_TARGET := fs.o
O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \
super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
- ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
+ ioctl.o readdir.o select.o fifo.o locks.o \
dcache.o inode.o attr.o bad_inode.o file.o iobuf.o \
$(BINFMTS) $(FILESYSTEMS)
+OX_OBJS := filesystems.o
ALL_SUB_DIRS := coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
@@ -53,7+53,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes)
/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/
- sigpipe = sigismember(¤t->signal, SIGPIPE);
+ sigpipe = sigismember(¤t->pending.signal, SIGPIPE);
/* Save pointer to user space and point back to kernel space */
fs = get_fs();
@@ -71,7+71,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes) SIGPIPE unless it was already supposed to get one */
if (wr == -EPIPE && !sigpipe) {
spin_lock_irqsave(¤t->sigmask_lock, flags);
- sigdelset(¤t->signal, SIGPIPE);
+ sigdelset(¤t->pending.signal, SIGPIPE);
recalc_sigpending(current);
spin_unlock_irqrestore(¤t->sigmask_lock, flags);
}
@@ -57,7+57,7 @@ static int autofs4_write(struct file *file, const void *addr, int bytes)
/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/
- sigpipe = sigismember(¤t->signal, SIGPIPE);
+ sigpipe = sigismember(¤t->pending.signal, SIGPIPE);
/* Save pointer to user space and point back to kernel space */
fs = get_fs();
@@ -75,7+75,7 @@ static int autofs4_write(struct file *file, const void *addr, int bytes) SIGPIPE unless it was already supposed to get one */
if (wr == -EPIPE && !sigpipe) {
spin_lock_irqsave(¤t->sigmask_lock, flags);
- sigdelset(¤t->signal, SIGPIPE);
+ sigdelset(¤t->pending.signal, SIGPIPE);
recalc_sigpending(current);
spin_unlock_irqrestore(¤t->sigmask_lock, flags);
}
@@ -1045,7+1045,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) notes[0].datasz = sizeof(prstatus);
notes[0].data = &prstatus;
prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
- prstatus.pr_sigpend = current->signal.sig[0];
+ prstatus.pr_sigpend = current->pending.signal.sig[0];
prstatus.pr_sighold = current->blocked.sig[0];
psinfo.pr_pid = prstatus.pr_pid = current->pid;
psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid;
@@ -2606,8+2606,8 @@ int kupdate(void *sem) if (signal_pending(tsk)) {
int stopped = 0;
spin_lock_irq(&tsk->sigmask_lock);
- if (sigismember(&tsk->signal, SIGSTOP)) {
- sigdelset(&tsk->signal, SIGSTOP);
+ if (sigismember(&tsk->pending.signal, SIGSTOP)) {
+ sigdelset(&tsk->pending.signal, SIGSTOP);
stopped = 1;
}
recalc_sigpending(tsk);
@@ -2625,9+2625,9 @@ int kupdate(void *sem) static int __init bdflush_init(void)
{
DECLARE_MUTEX_LOCKED(sem);
- kernel_thread(bdflush, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ kernel_thread(bdflush, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
down(&sem);
- kernel_thread(kupdate, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ kernel_thread(kupdate, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
down(&sem);
return 0;
}
@@ -427,7+427,7 @@ static int exec_mmap(void) * This function makes sure the current process has its own signal table,
* so that flush_signal_handlers can later reset the handlers without
* disturbing other processes. (Other processes might share the signal
- * table via the CLONE_SIGHAND option to clone().)
+ * table via the CLONE_SIGNAL option to clone().)
*/
static inline int make_private_signals(void)
O_TARGET := ext2.o
O_OBJS := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o truncate.o
+ ioctl.o namei.o super.o symlink.o
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
@@ -398,9+398,13 @@ repeat: ext2_error (sb, "ext2_new_inode",
"Free inodes count corrupted in group %d",
i);
- unlock_super (sb);
- iput (inode);
- return NULL;
+ if (sb->s_flags & MS_RDONLY) {
+ unlock_super (sb);
+ iput (inode);
+ return NULL;
+ }
+ gdp->bg_free_inodes_count = 0;
+ mark_buffer_dirty(bh2, 1);
}
goto repeat;
}
@@ -411,6+415,7 @@ repeat: "block_group = %d,inode=%d", i, j);
unlock_super (sb);
iput (inode);
+ *err = -EIO;
return NULL;
}
gdp->bg_free_inodes_count =
@@ -704,6+704,285 @@ struct address_space_operations ext2_aops = { bmap: ext2_bmap
};
+/*
+ * Probably it should be a library function... search for first non-zero word
+ * or memcmp with zero_page, whatever is better for particular architecture.
+ * Linus?
+ */
+static inline int all_zeroes(u32 *p, u32 *q)
+{
+ while (p < q)
+ if (*p++)
+ return 1;
+ return 0;
+}
+
+/**
+ * ext2_find_shared - find the indirect blocks for partial truncation.
+ * @inode: inode in question
+ * @depth: depth of the affected branch
+ * @offsets: offsets of pointers in that branch (see ext2_block_to_path)
+ * @chain: place to store the pointers to partial indirect blocks
+ * @top: place to the (detached) top of branch
+ *
+ * This is a helper function used by ext2_truncate().
+ *
+ * When we do truncate() we may have to clean the ends of several indirect
+ * blocks but leave the blocks themselves alive. Block is partially
+ * truncated if some data below the new i_size is refered from it (and
+ * it is on the path to the first completely truncated data block, indeed).
+ * We have to free the top of that path along with everything to the right
+ * of the path. Since no allocation past the truncation point is possible
+ * until ext2_truncate() finishes, we may safely do the latter, but top
+ * of branch may require special attention - pageout below the truncation
+ * point might try to populate it.
+ *
+ * We atomically detach the top of branch from the tree, store the block
+ * number of its root in *@top, pointers to buffer_heads of partially
+ * truncated blocks - in @chain[].bh and pointers to their last elements
+ * that should not be removed - in @chain[].p. Return value is the pointer
+ * to last filled element of @chain.
+ *
+ * The work left to caller to do the actual freeing of subtrees:
+ * a) free the subtree starting from *@top
+ * b) free the subtrees whose roots are stored in
+ * (@chain[i].p+1 .. end of @chain[i].bh->b_data)
+ * c) free the subtrees growing from the inode past the @chain[0].p
+ * (no partially truncated stuff there).
+ */
+
+static Indirect *ext2_find_shared(struct inode *inode,
+ int depth,
+ int offsets[4],
+ Indirect chain[4],
+ u32 *top)
+{
+ Indirect *partial, *p;
+ int k, err;
+
+ *top = 0;
+ for (k = depth; k > 1 && !offsets[k-1]; k--)
+ ;
+ partial = ext2_get_branch(inode, k, offsets, chain, &err);
+ /* Writer: pointers */
+ if (!partial)
+ partial = chain + k-1;
+ /*
+ * If the branch acquired continuation since we've looked at it -
+ * fine, it should all survive and (new) top doesn't belong to us.
+ */
+ if (!partial->key && *partial->p)
+ /* Writer: end */
+ goto no_top;
+ for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+ ;
+ /*
+ * OK, we've found the last block that must survive. The rest of our
+ * branch should be detached before unlocking. However, if that rest
+ * of branch is all ours and does not grow immediately from the inode
+ * it's easier to cheat and just decrement partial->p.
+ */
+ if (p == chain + k - 1 && p > chain) {
+ p->p--;
+ } else {
+ *top = *p->p;
+ *p->p = 0;
+ }
+ /* Writer: end */
+
+ while(partial > p)
+ {
+ brelse(partial->bh);
+ partial--;
+ }
+no_top:
+ return partial;
+}
+
+/**
+ * ext2_free_data - free a list of data blocks
+ * @inode: inode we are dealing with
+ * @p: array of block numbers
+ * @q: points immediately past the end of array
+ *
+ * We are freeing all blocks refered from that array (numbers are
+ * stored as little-endian 32-bit) and updating @inode->i_blocks
+ * appropriately.
+ */
+static inline void ext2_free_data(struct inode *inode, u32 *p, u32 *q)
+{
+ int blocks = inode->i_sb->s_blocksize / 512;
+ unsigned long block_to_free = 0, count = 0;
+ unsigned long nr;
+
+ for ( ; p < q ; p++) {
+ nr = le32_to_cpu(*p);
+ if (nr) {
+ *p = 0;
+ /* accumulate blocks to free if they're contiguous */
+ if (count == 0)
+ goto free_this;
+ else if (block_to_free == nr - count)
+ count++;
+ else {
+ /* Writer: ->i_blocks */
+ inode->i_blocks -= blocks * count;
+ /* Writer: end */
+ ext2_free_blocks (inode, block_to_free, count);
+ mark_inode_dirty(inode);
+ free_this:
+ block_to_free = nr;
+ count = 1;
+ }
+ }
+ }
+ if (count > 0) {
+ /* Writer: ->i_blocks */
+ inode->i_blocks -= blocks * count;
+ /* Writer: end */
+ ext2_free_blocks (inode, block_to_free, count);
+ mark_inode_dirty(inode);
+ }
+}
+
+/**
+ * ext2_free_branches - free an array of branches
+ * @inode: inode we are dealing with
+ * @p: array of block numbers
+ * @q: pointer immediately past the end of array
+ * @depth: depth of the branches to free
+ *
+ * We are freeing all blocks refered from these branches (numbers are
+ * stored as little-endian 32-bit) and updating @inode->i_blocks
+ * appropriately.
+ */
+static void ext2_free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
+{
+ struct buffer_head * bh;
+ unsigned long nr;
+
+ if (depth--) {
+ int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+ for ( ; p < q ; p++) {
+ nr = le32_to_cpu(*p);
+ if (!nr)
+ continue;
+ *p = 0;
+ bh = bread (inode->i_dev, nr, inode->i_sb->s_blocksize);
+ /*
+ * A read failure? Report error and clear slot
+ * (should be rare).
+ */
+ if (!bh) {
+ ext2_error(inode->i_sb, "ext2_free_branches",
+ "Read failure, inode=%ld, block=%ld",
+ inode->i_ino, nr);
+ continue;
+ }
+ ext2_free_branches(inode,
+ (u32*)bh->b_data,
+ (u32*)bh->b_data + addr_per_block,
+ depth);
+ bforget(bh);
+ /* Writer: ->i_blocks */
+ inode->i_blocks -= inode->i_sb->s_blocksize / 512;
+ /* Writer: end */
+ ext2_free_blocks(inode, nr, 1);
+ mark_inode_dirty(inode);
+ }
+ } else
+ ext2_free_data(inode, p, q);
+}
+
+void ext2_truncate (struct inode * inode)
+{
+ u32 *i_data = inode->u.ext2_i.i_data;
+ int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+ int offsets[4];
+ Indirect chain[4];
+ Indirect *partial;
+ int nr = 0;
+ int n;
+ long iblock;
+
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode)))
+ return;
+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+ return;
+
+ ext2_discard_prealloc(inode);
+
+ iblock = (inode->i_size + inode->i_sb->s_blocksize-1)
+ >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
+
+ n = ext2_block_to_path(inode, iblock, offsets);
+ if (n == 0)
+ return;
+
+ if (n == 1) {
+ ext2_free_data(inode, i_data+offsets[0],
+ i_data + EXT2_NDIR_BLOCKS);
+ goto do_indirects;
+ }
+
+ partial = ext2_find_shared(inode, n, offsets, chain, &nr);
+ /* Kill the top of shared branch (already detached) */
+ if (nr) {
+ if (partial == chain)
+ mark_inode_dirty(inode);
+ else
+ mark_buffer_dirty(partial->bh, 1);
+ ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
+ }
+ /* Clear the ends of indirect blocks on the shared branch */
+ while (partial > chain) {
+ ext2_free_branches(inode,
+ partial->p + 1,
+ (u32*)partial->bh->b_data + addr_per_block,
+ (chain+n-1) - partial);
+ mark_buffer_dirty(partial->bh, 1);
+ if (IS_SYNC(inode)) {
+ ll_rw_block (WRITE, 1, &partial->bh);
+ wait_on_buffer (partial->bh);
+ }
+ brelse (partial->bh);
+ partial--;
+ }
+do_indirects:
+ /* Kill the remaining (whole) subtrees */
+ switch (offsets[0]) {
+ default:
+ nr = i_data[EXT2_IND_BLOCK];
+ if (nr) {
+ i_data[EXT2_IND_BLOCK] = 0;
+ mark_inode_dirty(inode);
+ ext2_free_branches(inode, &nr, &nr+1, 1);
+ }
+ case EXT2_IND_BLOCK:
+ nr = i_data[EXT2_DIND_BLOCK];
+ if (nr) {
+ i_data[EXT2_DIND_BLOCK] = 0;
+ mark_inode_dirty(inode);
+ ext2_free_branches(inode, &nr, &nr+1, 2);
+ }
+ case EXT2_DIND_BLOCK:
+ nr = i_data[EXT2_TIND_BLOCK];
+ if (nr) {
+ i_data[EXT2_TIND_BLOCK] = 0;
+ mark_inode_dirty(inode);
+ ext2_free_branches(inode, &nr, &nr+1, 3);
+ }
+ case EXT2_TIND_BLOCK:
+ ;
+ }
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ if (IS_SYNC(inode))
+ ext2_sync_inode (inode);
+ else
+ mark_inode_dirty(inode);
+}
+
void ext2_read_inode (struct inode * inode)
{
struct buffer_head * bh;
@@ -781,30+1060,22 @@ void ext2_read_inode (struct inode * inode) inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
inode->i_version = ++event;
- inode->u.ext2_i.i_new_inode = 0;
inode->u.ext2_i.i_flags = le32_to_cpu(raw_inode->i_flags);
inode->u.ext2_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
inode->u.ext2_i.i_frag_no = raw_inode->i_frag;
inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
- inode->u.ext2_i.i_osync = 0;
inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
if (S_ISDIR(inode->i_mode))
inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
else {
- inode->u.ext2_i.i_dir_acl = 0;
inode->u.ext2_i.i_high_size = le32_to_cpu(raw_inode->i_size_high);
inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
}
inode->i_generation = le32_to_cpu(raw_inode->i_generation);
inode->u.ext2_i.i_block_group = block_group;
- inode->u.ext2_i.i_next_alloc_block = 0;
- inode->u.ext2_i.i_next_alloc_goal = 0;
- if (inode->u.ext2_i.i_prealloc_count)
- ext2_error (inode->i_sb, "ext2_read_inode",
- "New inode has non-zero prealloc count!");
/*
- * NOTE! The in-memory inode i_blocks array is in little-endian order
+ * NOTE! The in-memory inode i_data array is in little-endian order
* even on big-endian machines: we do NOT byteswap the block numbers!
*/
for (block = 0; block < EXT2_N_BLOCKS; block++)
@@ -940,9+1211,23 @@ static int ext2_update_inode(struct inode * inode, int do_sync) raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl);
if (S_ISDIR(inode->i_mode))
raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
- else
+ else {
raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
-
+ if (raw_inode->i_size_high) {
+ struct super_block *sb = inode->i_sb;
+ struct ext2_super_block *es = sb->u.ext2_sb.s_es;
+ if (!(es->s_feature_ro_compat & cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
+ /* If this is the first large file
+ * created, add a flag to the superblock.
+ */
+ lock_kernel();
+ es->s_feature_ro_compat |= cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+ unlock_kernel();
+ ext2_write_super(sb);
+ }
+ }
+ }
+
raw_inode->i_generation = cpu_to_le32(inode->i_generation);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
@@ -966,7+1251,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) void ext2_write_inode (struct inode * inode, int wait)
{
lock_kernel();
- ext2_update_inode (inode, 0);
+ ext2_update_inode (inode, wait);
unlock_kernel();
}
@@ -366,12+366,9 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode) struct inode * inode;
int err;
- /*
- * N.B. Several error exits in ext2_new_inode don't set err.
- */
inode = ext2_new_inode (dir, mode, &err);
if (!inode)
- return -EIO;
+ return err;
inode->i_op = &ext2_file_inode_operations;
inode->i_fop = &ext2_file_operations;
@@ -397,7+394,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int
inode = ext2_new_inode (dir, mode, &err);
if (!inode)
- return -EIO;
+ return err;
inode->i_uid = current->fsuid;
init_special_inode(inode, mode, rdev);
@@ -428,7+425,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
inode = ext2_new_inode (dir, S_IFDIR, &err);
if (!inode)
- return -EIO;
+ return err;
inode->i_op = &ext2_dir_inode_operations;
inode->i_fop = &ext2_dir_operations;
@@ -634,7+631,7 @@ static int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * return -ENAMETOOLONG;
if (!(inode = ext2_new_inode (dir, S_IFLNK, &err)))
- return -EIO;
+ return err;
inode->i_mode = S_IFLNK | S_IRWXUGO;
+++ /dev/null
-/*
- * linux/fs/ext2/truncate.c
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/fs/minix/truncate.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Big-endian to little-endian byte-swapping/bitmaps by
- * David S. Miller (davem@caip.rutgers.edu), 1995
- *
- * General cleanup and race fixes, wsh, 1998
- */
-
-#include <linux/fs.h>
-#include <linux/locks.h>
-
-
-/*
- * Real random numbers for secure rm added 94/02/18
- * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
- */
-
-#if 0
-
-/*
- * Secure deletion currently doesn't work. It interacts very badly
- * with buffers shared with memory mappings, and for that reason
- * can't be done in the truncate() routines. It should instead be
- * done separately in "release()" before calling the truncate routines
- * that will release the actual file blocks.
- *
- * Linus
- */
-static int ext2_secrm_seed = 152; /* Random generator base */
-
-#define RANDOM_INT (ext2_secrm_seed = ext2_secrm_seed * 69069l +1)
-#endif
-
-/*
- * Macros to return the block number for the inode size and offset.
- * Currently we always hold the inode semaphore during truncate, so
- * there's no need to test for changes during the operation.
- */
-#define DIRECT_BLOCK(inode) \
- ((unsigned long) ((inode->i_size + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits))
-#define INDIRECT_BLOCK(inode,offset) ((int)DIRECT_BLOCK(inode) - offset)
-#define DINDIRECT_BLOCK(inode,offset) \
- (INDIRECT_BLOCK(inode,offset) / addr_per_block)
-#define TINDIRECT_BLOCK(inode,offset) \
- (INDIRECT_BLOCK(inode,offset) / (addr_per_block*addr_per_block))
-
-/*
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**. Especially as I don't do any locking...
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- *
- *
- * Truncate operations have been rewritten to avoid various races. The
- * previous code was allowing blocking operations to precede a call to
- * bforget(), possible allowing the buffer to be used again.
- *
- * We now ensure that b_count == 1 before calling bforget() and that the
- * parent buffer (if any) is unlocked before clearing the block pointer.
- * The operations are always performed in this order:
- * (1) Make sure that the parent buffer is unlocked.
- * (2) Use find_buffer() to find the block buffer without blocking,
- * and set 'retry' if the buffer is locked or b_count > 1.
- * (3) Clear the block pointer in the parent (buffer or inode).
- * (4) Update the inode block count and mark the inode dirty.
- * (5) Forget the block buffer, if any. This call won't block, as
- * we know the buffer is unlocked from (2).
- * (6) If the block pointer is in a (parent) buffer, mark the buffer
- * dirty. (Note that this can block on a loop device.)
- * (7) Accumulate the blocks to free and/or update the block bitmap.
- * (This operation will frequently block.)
- *
- * The requirement that parent buffers be unlocked follows from the general
- * principle of not modifying a buffer that may be undergoing I/O. With the
- * the present kernels there's no problem with modifying a locked inode, as
- * the I_DIRTY bit is cleared before setting I_LOCK.
- * -- WSH, 1998
- */
-
-/*
- * Check whether any of the slots in an indirect block are
- * still in use, and if not free the block.
- */
-static int check_block_empty(struct inode *inode, struct buffer_head *bh,
- u32 *p, struct buffer_head *ind_bh)
-{
- int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
- u32 * ind = (u32 *) bh->b_data;
- int i, retry;
-
- /* Make sure both buffers are unlocked */
- do {
- retry = 0;
- if (buffer_locked(bh)) {
- __wait_on_buffer(bh);
- retry = 1;
- }
- if (ind_bh && buffer_locked(ind_bh)) {
- __wait_on_buffer(ind_bh);
- retry = 1;
- }
- } while (retry);
-
- for (i = 0; i < addr_per_block; i++)
- if (*(ind++))
- goto in_use;
-
- if (atomic_read(&bh->b_count) == 1) {
- int tmp;
- tmp = le32_to_cpu(*p);
- *p = 0;
- inode->i_blocks -= (inode->i_sb->s_blocksize / 512);
- mark_inode_dirty(inode);
- /*
- * Forget the buffer, then mark the parent buffer dirty.
- */
- bforget(bh);
- if (ind_bh)
- mark_buffer_dirty(ind_bh, 1);
- ext2_free_blocks(inode, tmp, 1);
- goto out;
- }
- retry = 1;
-
-in_use:
- if (IS_SYNC(inode) && buffer_dirty(bh)) {
- ll_rw_block (WRITE, 1, &bh);
- wait_on_buffer (bh);
- }
- brelse (bh);
-
-out:
- return retry;
-}
-
-#define DATA_BUFFER_USED(bh) \
- (atomic_read(&bh->b_count) || buffer_locked(bh))
-
-static int trunc_direct (struct inode * inode)
-{
- int i, retry = 0;
- unsigned long block_to_free = 0, free_count = 0;
- int blocks = inode->i_sb->s_blocksize / 512;
- int direct_block = DIRECT_BLOCK(inode);
-
- for (i = direct_block ; i < EXT2_NDIR_BLOCKS ; i++) {
- u32 * p = inode->u.ext2_i.i_data + i;
- int tmp = le32_to_cpu(*p);
-
- if (!tmp)
- continue;
-
- *p = 0;
- inode->i_blocks -= blocks;
- mark_inode_dirty(inode);
-
- /* accumulate blocks to free if they're contiguous */
- if (free_count == 0)
- goto free_this;
- else if (block_to_free == tmp - free_count)
- free_count++;
- else {
- ext2_free_blocks (inode, block_to_free, free_count);
- free_this:
- block_to_free = tmp;
- free_count = 1;
- }
- }
- if (free_count > 0)
- ext2_free_blocks (inode, block_to_free, free_count);
- return retry;
-}
-
-static int trunc_indirect (struct inode * inode, int offset, u32 * p, struct buffer_head *dind_bh)
-{
- struct buffer_head * ind_bh;
- int i, tmp, retry = 0;
- unsigned long block_to_free = 0, free_count = 0;
- int indirect_block, addr_per_block, blocks;
-
- tmp = le32_to_cpu(*p);
- if (!tmp)
- return 0;
- ind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
- if (tmp != le32_to_cpu(*p)) {
- brelse (ind_bh);
- return 1;
- }
- /* A read failure? Report error and clear slot (should be rare). */
- if (!ind_bh) {
- ext2_error(inode->i_sb, "trunc_indirect",
- "Read failure, inode=%ld, block=%d",
- inode->i_ino, tmp);
- *p = 0;
- if (dind_bh)
- mark_buffer_dirty(dind_bh, 1);
- else
- mark_inode_dirty(inode);
- return 0;
- }
-
- blocks = inode->i_sb->s_blocksize / 512;
- addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
- indirect_block = INDIRECT_BLOCK(inode, offset);
- if (indirect_block < 0)
- indirect_block = 0;
- for (i = indirect_block ; i < addr_per_block ; i++) {
- u32 * ind = i + (u32 *) ind_bh->b_data;
-
- wait_on_buffer(ind_bh);
- tmp = le32_to_cpu(*ind);
- if (!tmp)
- continue;
-
- *ind = 0;
- inode->i_blocks -= blocks;
- mark_inode_dirty(inode);
- mark_buffer_dirty(ind_bh, 1);
-
- /* accumulate blocks to free if they're contiguous */
- if (free_count == 0)
- goto free_this;
- else if (block_to_free == tmp - free_count)
- free_count++;
- else {
- ext2_free_blocks (inode, block_to_free, free_count);
- free_this:
- block_to_free = tmp;
- free_count = 1;
- }
- }
- if (free_count > 0)
- ext2_free_blocks (inode, block_to_free, free_count);
- /*
- * Check the block and dispose of the ind_bh buffer.
- */
- retry |= check_block_empty(inode, ind_bh, p, dind_bh);
-
- return retry;
-}
-
-static int trunc_dindirect (struct inode * inode, int offset, u32 * p,
- struct buffer_head * tind_bh)
-{
- struct buffer_head * dind_bh;
- int i, tmp, retry = 0;
- int dindirect_block, addr_per_block;
-
- tmp = le32_to_cpu(*p);
- if (!tmp)
- return 0;
- dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
- if (tmp != le32_to_cpu(*p)) {
- brelse (dind_bh);
- return 1;
- }
- /* A read failure? Report error and clear slot (should be rare). */
- if (!dind_bh) {
- ext2_error(inode->i_sb, "trunc_dindirect",
- "Read failure, inode=%ld, block=%d",
- inode->i_ino, tmp);
- *p = 0;
- if (tind_bh)
- mark_buffer_dirty(tind_bh, 1);
- else
- mark_inode_dirty(inode);
- return 0;
- }
-
- addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
- dindirect_block = DINDIRECT_BLOCK(inode, offset);
- if (dindirect_block < 0)
- dindirect_block = 0;
- for (i = dindirect_block ; i < addr_per_block ; i++) {
- u32 * dind = i + (u32 *) dind_bh->b_data;
-
- retry |= trunc_indirect(inode,
- offset + (i * addr_per_block),
- dind, dind_bh);
- }
- /*
- * Check the block and dispose of the dind_bh buffer.
- */
- retry |= check_block_empty(inode, dind_bh, p, tind_bh);
-
- return retry;
-}
-
-static int trunc_tindirect (struct inode * inode)
-{
- u32 * p = inode->u.ext2_i.i_data + EXT2_TIND_BLOCK;
- struct buffer_head * tind_bh;
- int i, tmp, retry = 0;
- int tindirect_block, addr_per_block, offset;
-
- tmp = le32_to_cpu(*p);
- if (!tmp)
- return 0;
- tind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
- if (tmp != le32_to_cpu(*p)) {
- brelse (tind_bh);
- return 1;
- }
- /* A read failure? Report error and clear slot (should be rare). */
- if (!tind_bh) {
- ext2_error(inode->i_sb, "trunc_tindirect",
- "Read failure, inode=%ld, block=%d",
- inode->i_ino, tmp);
- *p = 0;
- mark_inode_dirty(inode);
- return 0;
- }
-
- addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
- offset = EXT2_NDIR_BLOCKS + addr_per_block +
- (addr_per_block * addr_per_block);
- tindirect_block = TINDIRECT_BLOCK(inode, offset);
- if (tindirect_block < 0)
- tindirect_block = 0;
- for (i = tindirect_block ; i < addr_per_block ; i++) {
- u32 * tind = i + (u32 *) tind_bh->b_data;
-
- retry |= trunc_dindirect(inode,
- offset + (i * addr_per_block * addr_per_block),
- tind, tind_bh);
- }
- /*
- * Check the block and dispose of the tind_bh buffer.
- */
- retry |= check_block_empty(inode, tind_bh, p, NULL);
-
- return retry;
-}
-
-void ext2_truncate (struct inode * inode)
-{
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
- ext2_discard_prealloc(inode);
- while (1) {
- int retry = trunc_direct(inode);
- retry |= trunc_indirect (inode,
- EXT2_IND_BLOCK,
- (u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK],
- NULL);
- retry |= trunc_dindirect (inode,
- EXT2_IND_BLOCK+EXT2_ADDR_PER_BLOCK(inode->i_sb),
- (u32 *)&inode->u.ext2_i.i_data[EXT2_DIND_BLOCK],
- NULL);
- retry |= trunc_tindirect (inode);
- if (!retry)
- break;
- if (IS_SYNC(inode) && (inode->i_state & I_DIRTY))
- ext2_sync_inode (inode);
- run_task_queue(&tq_disk);
- current->policy |= SCHED_YIELD;
- schedule();
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
-}
#include <linux/major.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
-#include <linux/lockd/bind.h>
-#include <linux/lockd/xdr.h>
#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/nfsd/interface.h>
#ifdef CONFIG_CODA_FS
extern int init_coda(void);
@@ -48,32+46,28 @@ void __init filesystem_setup(void) #endif
}
-#ifndef CONFIG_NFSD
-#ifdef CONFIG_NFSD_MODULE
-long (*do_nfsservctl)(int, void *, void *);
-#endif
+#if defined(CONFIG_NFSD_MODULE)
+struct nfsd_linkage *nfsd_linkage = NULL;
+
long
asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp)
{
-#ifndef CONFIG_NFSD_MODULE
- return -ENOSYS;
-#else
int ret = -ENOSYS;
lock_kernel();
- if (do_nfsservctl) {
- ret = do_nfsservctl(cmd, argp, resp);
- goto out;
- }
-#ifdef CONFIG_KMOD
- if (request_module ("nfsd") == 0) {
- if (do_nfsservctl)
- ret = do_nfsservctl(cmd, argp, resp);
- }
-#endif /* CONFIG_KMOD */
-out:
+
+ if (nfsd_linkage ||
+ (request_module ("nfsd") == 0 && nfsd_linkage))
+ ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp);
+
unlock_kernel();
return ret;
-#endif /* CONFIG_NFSD_MODULE */
+}
+EXPORT_SYMBOL(nfsd_linkage);
+
+#elif ! defined (CONFIG_NFSD)
+asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp)
+{
+ return -ENOSYS;
}
#endif /* CONFIG_NFSD */
@@ -1040,17+1040,12 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) */
if (IS_MANDLOCK(inode) &&
(inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
- struct vm_area_struct *vma;
struct address_space *mapping = inode->i_mapping;
- spin_lock(&mapping->i_shared_lock);
- for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) {
- if (!(vma->vm_flags & VM_MAYSHARE))
- continue;
- spin_unlock(&mapping->i_shared_lock);
+
+ if (mapping->i_mmap_shared != NULL) {
error = -EAGAIN;
goto out_putf;
}
- spin_unlock(&mapping->i_shared_lock);
}
error = -EINVAL;
@@ -1199,17+1194,12 @@ int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l) */
if (IS_MANDLOCK(inode) &&
(inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
- struct vm_area_struct *vma;
struct address_space *mapping = inode->i_mapping;
- spin_lock(&mapping->i_shared_lock);
- for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) {
- if (!(vma->vm_flags & VM_MAYSHARE))
- continue;
- spin_unlock(&mapping->i_shared_lock);
+
+ if (mapping->i_mmap_shared != NULL) {
error = -EAGAIN;
goto out_putf;
}
- spin_unlock(&mapping->i_shared_lock);
}
error = -EINVAL;
@@ -290,7+290,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return -EACCES;
}
/* get only low 8 bits... */
- get_user_ret(newstate, (unsigned char*)arg, -EFAULT);
+ if (get_user(newstate, (unsigned char *) arg))
+ return -EFAULT;
if (server->sign_active) {
/* cannot turn signatures OFF when active */
if (!newstate) return -EINVAL;
EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
-extern long (*do_nfsservctl)(int, void *, void *);
+struct nfsd_linkage nfsd_linkage_s = {
+ do_nfsservctl: handle_sys_nfsservctl,
+};
/*
* Initialize the module
init_module(void)
{
printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
- do_nfsservctl = handle_sys_nfsservctl;
+ nfsd_linkage = &nfsd_linkage_s;
return 0;
}
@@ -331,7+333,7 @@ init_module(void) void
cleanup_module(void)
{
- do_nfsservctl = NULL;
+ nfsd_linkage = NULL;
nfsd_export_shutdown();
nfsd_cache_shutdown();
remove_proc_entry("fs/nfs/exports", NULL);
@@ -213,7+213,7 @@ nfsd(struct svc_rqst *rqstp) unsigned int signo;
for (signo = 1; signo <= _NSIG; signo++)
- if (sigismember(¤t->signal, signo) &&
+ if (sigismember(¤t->pending.signal, signo) &&
!sigismember(¤t->blocked, signo))
break;
printk(KERN_WARNING "nfsd: terminating on signal %d\n", signo);
@@ -142,6+142,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, } else
dentry = dget(dparent->d_parent);
} else {
+ fh_lock(fhp);
dentry = lookup_one(name, dparent);
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
@@ -228,24+228,35 @@ unsigned int get_ptable_blocksize(kdev_t dev) }
#ifdef CONFIG_PROC_FS
-int get_partition_list(char * page)
+int get_partition_list(char *page, char **start, off_t offset, int count)
{
- struct gendisk *p;
- char buf[64];
- int n, len;
+ struct gendisk *dsk;
+ int len;
len = sprintf(page, "major minor #blocks name\n\n");
- for (p = gendisk_head; p; p = p->next) {
- for (n=0; n < (p->nr_real << p->minor_shift); n++) {
- if (p->part[n].nr_sects && len < PAGE_SIZE - 80) {
- len += sprintf(page+len,
+ for (dsk = gendisk_head; dsk; dsk = dsk->next) {
+ int n;
+
+ for (n = 0; n < (dsk->nr_real << dsk->minor_shift); n++)
+ if (dsk->part[n].nr_sects) {
+ char buf[64];
+
+ len += sprintf(page + len,
"%4d %4d %10d %s\n",
- p->major, n, p->sizes[n],
- disk_name(p, n, buf));
+ dsk->major, n, dsk->sizes[n],
+ disk_name(dsk, n, buf));
+ if (len < offset)
+ offset -= len, len = 0;
+ else if (len >= offset + count)
+ goto leave_loops;
}
- }
}
- return len;
+leave_loops:
+ *start = page + offset;
+ len -= offset;
+ if (len < 0)
+ len = 0;
+ return len > count ? count : len;
}
#endif
@@ -241,7+241,7 @@ static inline char * task_sig(struct task_struct *p, char *buffer) sigset_t ign, catch;
buffer += sprintf(buffer, "SigPnd:\t");
- buffer = render_sigset_t(&p->signal, buffer);
+ buffer = render_sigset_t(&p->pending.signal, buffer);
*buffer++ = '\n';
buffer += sprintf(buffer, "SigBlk:\t");
buffer = render_sigset_t(&p->blocked, buffer);
@@ -382,7+382,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) * It must be decimal for Linux 2.0 compatibility.
* Use /proc/#/status for real-time signals.
*/
- task->signal .sig[0] & 0x7fffffffUL,
+ task->pending.signal.sig[0] & 0x7fffffffUL,
task->blocked.sig[0] & 0x7fffffffUL,
sigign .sig[0] & 0x7fffffffUL,
sigcatch .sig[0] & 0x7fffffffUL,
@@ -56,7+56,7 @@ extern int get_module_list(char *); extern int get_ksyms_list(char *, char **, off_t, int);
#endif
extern int get_device_list(char *);
-extern int get_partition_list(char *);
+extern int get_partition_list(char *, char **, off_t, int);
extern int get_filesystem_list(char *);
extern int get_filesystem_info(char *);
extern int get_exec_domain_list(char *);
@@ -375,12+375,8 @@ static int devices_read_proc(char *page, char **start, off_t off, static int partitions_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
- int len = get_partition_list(page);
- if (len <= off+count) *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
+ int len = get_partition_list(page, start, off, count);
+ if (len < count) *eof = 1;
return len;
}
@@ -175,13+175,10 @@ extern inline unsigned long ffz_b(unsigned long x)
extern inline unsigned long ffz(unsigned long word)
{
-#if 0 && defined(__alpha_cix__)
- /* Swine architects -- a year after they publish v3 of the
- handbook, in the 21264 data sheet they quietly change CIX
- to FIX and remove the spiffy counting instructions. */
+#if defined(__alpha_cix__) && defined(__alpha_fix__)
/* Whee. EV6 can calculate it directly. */
unsigned long result;
- __asm__("ctlz %1,%0" : "=r"(result) : "r"(~word));
+ __asm__("cttz %1,%0" : "=r"(result) : "r"(~word));
return result;
#else
unsigned long bits, qofs, bofs;
@@ -214,10+211,7 @@ extern inline int ffs(int word) * of bits set) of a N-bit word
*/
-#if 0 && defined(__alpha_cix__)
-/* Swine architects -- a year after they publish v3 of the handbook, in
- the 21264 data sheet they quietly change CIX to FIX and remove the
- spiffy counting instructions. */
+#if defined(__alpha_cix__) && defined(__alpha_fix__)
/* Whee. EV6 can calculate it directly. */
extern __inline__ unsigned long hweight64(unsigned long w)
{
@@ -83,247+83,24 @@ typedef struct { igcsr32 agpmode; /* 0xB0 - AGP/GART mode control */
} Irongate0;
-/* Bitfield and mask register definitions */
-
-/* Device, vendor IDs - offset 0x00 */
-
-typedef union {
- igcsr32 i; /* integer value of CSR */
- struct {
- unsigned v : 16;
- unsigned d : 16;
- } r; /* structured interpretation */
-} ig_dev_vendor_t;
-
-
-/* Status, command registers - offset 0x04 */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned command;
- unsigned status;
- } s;
- struct {
- /* command register fields */
- unsigned iospc : 1; /* always reads zero */
- unsigned memspc : 1; /* PCI memory space accesses? */
- unsigned iten : 1; /* always 1: can be bus initiator */
- unsigned scmon : 1; /* always 0 special cycles not chckd */
- unsigned mwic : 1; /* always 0 - no mem write & invalid */
- unsigned vgaps : 1; /* always 0 - palette rds not special */
- unsigned per : 1; /* parity error resp: always 0 */
- unsigned step : 1; /* address/data stepping : always 0 */
- unsigned serre : 1; /* 1 = sys err output driver enable */
- unsigned fbbce : 1; /* fast back-back cycle : always 0 */
- unsigned zero1 : 6; /* must be zero */
-
- /* status register fields */
- unsigned zero2 : 4; /* must be zero */
- unsigned cl : 1; /* config space capa list: always 1 */
- unsigned pci66 : 1; /* 66 MHz PCI support - always 0 */
- unsigned udf : 1; /* user defined features - always 0 */
- unsigned fbbc : 1; /* back-back transactions - always 0 */
- unsigned ppe : 1; /* PCI parity error detected (0) */
- unsigned devsel : 2; /* DEVSEL timing (always 01) */
- unsigned sta : 1; /* signalled target abort (0) */
- unsigned rta : 1; /* recvd target abort */
- unsigned ria : 1; /* recvd initiator abort */
- unsigned serr : 1; /* SERR has been asserted */
- unsigned dpe : 1; /* DRAM parity error (0) */
- } r;
-} ig_stat_cmd_t;
-
-
-/* Revision ID, Programming interface, subclass, baseclass - offset 0x08 */
-
-typedef union {
- igcsr32 i;
- struct {
- /* revision ID */
- unsigned step : 4; /* stepping Revision ID */
- unsigned die : 4; /* die Revision ID */
- unsigned pif : 8; /* programming interface (0x00) */
- unsigned sub : 8; /* subclass code (0x00) */
- unsigned base: 8; /* baseclass code (0x06) */
- } r;
-} ig_class_t;
-
-
-/* Latency Timer, PCI Header type - offset 0x0C */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned zero1:8; /* reserved */
- unsigned lat : 8; /* latency in PCI bus clocks */
- unsigned hdr : 8; /* PCI header type */
- unsigned zero2:8; /* reserved */
- } r;
-} ig_latency_t;
-
-
-/* Base Address Register 0 - offset 0x10 */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned mem : 1; /* Reg pts to memory (always 0) */
- unsigned type: 2; /* 32 bit register = 0b00 */
- unsigned pref: 1; /* graphics mem prefetchable=1 */
- unsigned baddrl : 21; /* 32M = minimum alloc -> all zero */
- unsigned size : 6; /* size requirements for AGP */
- unsigned zero : 1; /* reserved=0 */
- } r;
-} ig_bar0_t;
-
-
-/* Base Address Register 1 - offset 0x14 */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned mem : 1; /* BAR0 maps to memory -> 0 */
- unsigned type : 2; /* BAR1 is 32-bit -> 0b00 */
- unsigned pref : 1; /* graphics mem prefetchable=1 */
- unsigned baddrl : 8; /* 4K alloc for AGP CSRs -> 0b00 */
- unsigned baddrh : 20; /* base addr of AGP CSRs A[30:11] */
- } r;
-} ig_bar1_t;
-
-
-/* Base Address Register 2 - offset 0x18 */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned io : 1; /* BAR2 maps to I/O space -> 1 */
- unsigned zero1: 1; /* reserved */
- unsigned addr : 22; /* BAR2[31:10] - PM2_BLK base */
- unsigned zero2: 8; /* reserved */
- } r;
-} ig_bar2_t;
-
-
-/* Capabilities Pointer - offset 0x34 */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned cap : 8; /* =0xA0, offset of AGP ctrl regs */
- unsigned zero: 24; /* reserved */
- } r;
-} ig_capptr_t;
-
-
-/* Base Address Chip Select Register 1,0 - offset 0x40 */
-/* Base Address Chip Select Register 3,2 - offset 0x44 */
-/* Base Address Chip Select Register 5,4 - offset 0x48 */
-
-typedef union {
-
- igcsr32 i;
- struct {
- /* lower bank */
- unsigned en0 : 1; /* memory bank enabled */
- unsigned mask0 : 6; /* Address mask for A[28:23] */
- unsigned base0 : 9; /* Bank Base Address A[31:23] */
-
- /* upper bank */
- unsigned en1 : 1; /* memory bank enabled */
- unsigned mask1 : 6; /* Address mask for A[28:23] */
- unsigned base1 : 9; /* Bank Base Address A[31:23] */
- } r;
-} ig_bacsr_t, ig_bacsr10_t, ig_bacsr32_t, ig_bacsr54_t;
-
-
-/* SDRAM Address Mapping Control Register - offset 0x50 */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned z1 : 1; /* reserved */
- unsigned bnks0: 1; /* 0->2 banks in chip select 0 */
- unsigned am0 : 1; /* row/column addressing */
- unsigned z2 : 1; /* reserved */
-
- unsigned z3 : 1; /* reserved */
- unsigned bnks1: 1; /* 0->2 banks in chip select 1 */
- unsigned am1 : 1; /* row/column addressing */
- unsigned z4 : 1; /* reserved */
-
- unsigned z5 : 1; /* reserved */
- unsigned bnks2: 1; /* 0->2 banks in chip select 2 */
- unsigned am2 : 1; /* row/column addressing */
- unsigned z6 : 1; /* reserved */
-
- unsigned z7 : 1; /* reserved */
- unsigned bnks3: 1; /* 0->2 banks in chip select 3 */
- unsigned am3 : 1; /* row/column addressing */
- unsigned z8 : 1; /* reserved */
-
- unsigned z9 : 1; /* reserved */
- unsigned bnks4: 1; /* 0->2 banks in chip select 4 */
- unsigned am4 : 1; /* row/column addressing */
- unsigned z10 : 1; /* reserved */
-
- unsigned z11 : 1; /* reserved */
- unsigned bnks5: 1; /* 0->2 banks in chip select 5 */
- unsigned am5 : 1; /* row/column addressing */
- unsigned z12 : 1; /* reserved */
-
- unsigned rsrvd: 8; /* reserved */
- } r;
-} ig_drammap_t;
-
-
-/* DRAM timing and driver strength register - offset 0x54 */
-
-typedef union {
- igcsr32 i;
- struct {
- /* DRAM timing parameters */
- unsigned trcd : 2;
- unsigned tcl : 2;
- unsigned tras: 3;
- unsigned trp : 2;
- unsigned trc : 3;
- unsigned icl: 2;
- unsigned ph : 2;
-
- /* Chipselect driver strength */
- unsigned adra : 1;
- unsigned adrb : 1;
- unsigned ctrl : 3;
- unsigned dqm : 1;
- unsigned cs : 1;
- unsigned clk: 1;
- unsigned rsrvd:8;
- } r;
-} ig_dramtm_t;
-
-
-/* DRAM Mode / Status and ECC Register - offset 0x58 */
-
-typedef union {
- igcsr32 i;
- struct {
- unsigned chipsel : 6; /* failing ECC chip select */
- unsigned zero1 : 2; /* always reads zero */
- unsigned status : 2; /* ECC Detect logic status */
- unsigned zero2 : 6; /* always reads zero */
-
- unsigned cycles : 2; /* cycles per refresh, see table */
- unsigned en : 1; /* ECC enable */
- unsigned r : 1; /* Large burst enable (=0) */
- unsigned bre : 1; /* Burst refresh enable */
- unsigned zero3 : 2; /* reserved = 0 */
- unsigned mwe : 1; /* Enable writes to DRAM mode reg */
- unsigned type : 1; /* SDRAM = 0, default */
- unsigned sdraminit : 1; /* SDRAM init - set params first! */
- unsigned zero4 : 6; /* reserved = 0 */
- } r;
-} ig_dramms_t;
+
+typedef struct {
+
+ igcsr32 dev_vendor; /* 0x00 - Device and Vendor IDs */
+ igcsr32 stat_cmd; /* 0x04 - Status and Command regs */
+ igcsr32 class; /* 0x08 - subclass, baseclass etc */
+ igcsr32 htype; /* 0x0C - header type (at 0x0E) */
+ igcsr32 rsrvd0[2]; /* 0x10-0x17 reserved */
+ igcsr32 busnos; /* 0x18 - Primary, secondary bus nos */
+ igcsr32 io_baselim_regs; /* 0x1C - IO base, IO lim, AGP status */
+ igcsr32 mem_baselim; /* 0x20 - memory base, memory lim */
+ igcsr32 pfmem_baselim; /* 0x24 - prefetchable base, lim */
+ igcsr32 rsrvd1[2]; /* 0x28-0x2F reserved */
+ igcsr32 io_baselim; /* 0x30 - IO base, IO limit */
+ igcsr32 rsrvd2[2]; /* 0x34-0x3B - reserved */
+ igcsr32 interrupt; /* 0x3C - interrupt, PCI bridge ctrl */
+
+} Irongate1;
/*
@@ -343,7+120,21 @@ typedef union { #define IRONGATE_IO (IDENT_ADDR | IRONGATE_BIAS | 0x1FC000000UL)
#define IRONGATE_CONF (IDENT_ADDR | IRONGATE_BIAS | 0x1FE000000UL)
-#define IRONGATE0 ((Irongate0 *) IRONGATE_CONF)
+/*
+ * PCI Configuration space accesses are formed like so:
+ *
+ * 0x1FE << 24 | : 2 2 2 2 1 1 1 1 : 1 1 1 1 1 1 0 0 : 0 0 0 0 0 0 0 0 :
+ * : 3 2 1 0 9 8 7 6 : 5 4 3 2 1 0 9 8 : 7 6 5 4 3 2 1 0 :
+ * ---bus numer--- -device-- -fun- ---register----
+ */
+
+#define IGCSR(dev,fun,reg) ( IRONGATE_CONF | \
+ ((dev)<<11) | \
+ ((fun)<<8) | \
+ (reg) )
+
+#define IRONGATE0 ((Irongate0 *) IGCSR(0, 0, 0))
+#define IRONGATE1 ((Irongate1 *) IGCSR(1, 0, 0))
/*
* Data structure for handling IRONGATE machine checks:
@@ -79,24+79,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
-
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
-
-/*
* The "lda %1, 2b-1b(%0)" bits are magic to get the assembler to
* encode the bits we need for resolving the exception. See the
* more extensive comments with fixup_inline_exception below for
@@ -417,16+399,6 @@ copy_from_user(void *to, const void *from, long n) return __copy_tofrom_user(to, from, n, from);
}
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
- return retval; \
-})
-
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
- return retval; \
-})
-
extern void __do_clear_user(void);
extern inline long
@@ -59,9+59,6 @@ extern __inline__ int verify_area(int type, const void * addr, unsigned long siz * address space - it must have been done previously with a separate
* "access_ok()" call.
*
- * The "xxx_ret" versions return constant specified in the third
- * argument if something bad happens.
- *
* The "xxx_error" versions set the third argument to EFAULT if an
* error occurs, and leave it unchanged on success. Note that these
* versions are void (ie, don't return a value as such).
@@ -69,14+66,10 @@ extern __inline__ int verify_area(int type, const void * addr, unsigned long siz #define get_user(x,p) __get_user_check((x),(p),sizeof(*(p)))
#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p)))
#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
-#define get_user_ret(x,p,r) ({ if (get_user(x,p)) return r; })
-#define __get_user_ret(x,p,r) ({ if (__get_user(x,p)) return r; })
#define put_user(x,p) __put_user_check((__typeof(*(p)))(x),(p),sizeof(*(p)))
#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
-#define put_user_ret(x,p,r) ({ if (put_user(x,p)) return r; })
-#define __put_user_ret(x,p,r) ({ if (__put_user(x,p)) return r; })
static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
{
@@ -91,9+84,6 @@ static __inline__ unsigned long __copy_from_user(void *to, const void *from, uns return n;
}
-#define copy_from_user_ret(t,f,n,r) \
- ({ if (copy_from_user(t,f,n)) return r; })
-
static __inline__ unsigned long copy_to_user(void *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
@@ -107,9+97,6 @@ static __inline__ unsigned long __copy_to_user(void *to, const void *from, unsig return n;
}
-#define copy_to_user_ret(t,f,n,r) \
- ({ if (copy_to_user(t,f,n)) return r; })
-
static __inline__ unsigned long clear_user (void *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
@@ -232,20+232,6 @@ do { \ : "=r"(err), ltype (x) \
: "m"(__m(addr)), "i"(-EFAULT), "0"(err))
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; })
-
-#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; })
-
/*
* Copy To/From Userspace
@@ -583,10+569,6 @@ __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n) __constant_copy_from_user((to),(from),(n)) : \
__generic_copy_from_user((to),(from),(n)))
-#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
-
-#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
-
#define __copy_to_user(to,from,n) \
(__builtin_constant_p(n) ? \
__constant_copy_to_user_nocheck((to),(from),(n)) : \
@@ -86,16+86,6 @@ verify_area (int type, const void *addr, unsigned long size) #define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
-#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
-#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; })
-#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; })
-
extern void __get_user_unknown (void);
#define __get_user_nocheck(x,ptr,size) \
@@ -280,18+270,6 @@ extern unsigned long __copy_user (void *to, const void *from, unsigned long coun __cu_len; \
})
-#define copy_to_user_ret(to,from,n,retval) \
-({ \
- if (copy_to_user(to,from,n)) \
- return retval; \
-})
-
-#define copy_from_user_ret(to,from,n,retval) \
-({ \
- if (copy_from_user(to,from,n)) \
- return retval; \
-})
-
extern unsigned long __do_clear_user (void *, unsigned long);
#define __clear_user(to,n) \
@@ -759,10+759,6 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n) #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
-#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
-
-#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
-
/*
* Copy a null terminated string from userspace.
*/
@@ -84,24+84,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) #define __get_user(x,ptr) \
__get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
-
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
-
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
@@ -281,16+263,6 @@ extern void __put_user_unknown(void); "jal\t" #destination "\n\t"
#endif
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
- return retval; \
-})
-
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
- return retval; \
-})
-
extern size_t __copy_user(void *__to, const void *__from, size_t __n);
#define __copy_to_user(to,from,n) ({ \
@@ -84,18+84,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) #define __get_user(x,ptr) \
__get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
-#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; })
-#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; })
-
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
@@ -213,16+201,6 @@ extern void __put_user_unknown(void); "jal\t" #destination "\n\t"
#endif
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
- return retval; \
-})
-
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
- return retval; \
-})
-
extern size_t __copy_user(void *__to, const void *__from, size_t __n);
#define __copy_to_user(to,from,n) ({ \
@@ -87,25+87,6 @@ extern unsigned long search_exception_table(unsigned long); #define __put_user(x,ptr) \
__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
-
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
-
-
extern long __put_user_bad(void);
#define __put_user_nocheck(x,ptr,size) \
@@ -236,10+217,6 @@ copy_to_user(void *to, const void *from, unsigned long n) return n;
}
-#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
-
-#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
-
#define __copy_from_user(to, from, size) \
__copy_tofrom_user((to), (from), (size))
#define __copy_to_user(to, from, size) \
@@ -407,10+407,6 @@ __copy_from_user_asm(void* to, const void* from, long n) err; \
})
-#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
-
-#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
-
/*
* Copy a null terminated string from userspace.
*/
@@ -83,24+83,6 @@ extern inline int verify_area(int type, const void * addr, unsigned long size) #define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
-/*
- * The "xxx_ret" versions return constant specified in third argument, if
- * something bad happens. These macros can be optimized for the
- * case of just returning from the function xxx_ret is used.
- */
-
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
-
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
-
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
@@ -256,20+238,10 @@ __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ } else __copy_res = __copy_size; \
__copy_res; })
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
- return retval; \
-})
-
#define __copy_to_user(to,from,n) \
__copy_user((void *)(to), \
(void *)(from), n)
-#define __copy_to_user_ret(to,from,n,retval) ({ \
-if (__copy_to_user(to,from,n)) \
- return retval; \
-})
-
#define copy_from_user(to,from,n) ({ \
void *__copy_to = (void *) (to); \
void *__copy_from = (void *) (from); \
@@ -280,20+252,10 @@ __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ } else __copy_res = __copy_size; \
__copy_res; })
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
- return retval; \
-})
-
#define __copy_from_user(to,from,n) \
__copy_user((void *)(to), \
(void *)(from), n)
-#define __copy_from_user_ret(to,from,n,retval) ({ \
-if (__copy_from_user(to,from,n)) \
- return retval; \
-})
-
/* XXX: Not sure it works well..
should be such that: 4byte clear and the rest. */
extern __inline__ __kernel_size_t
/* hardirq.h: 32-bit Sparc hard IRQ support.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
+ * Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com)
*/
#ifndef __SPARC_HARDIRQ_H
#include <linux/config.h>
#include <linux/threads.h>
+#include <linux/brlock.h>
+#include <linux/spinlock.h>
/* entry.S is sensitive to the offsets of these fields */
typedef struct {
unsigned int __softirq_active;
unsigned int __softirq_mask;
+#ifndef CONFIG_SMP
unsigned int __local_irq_count;
+#else
+ unsigned int __unused_on_SMP; /* DaveM says use brlock for SMP irq. KAO */
+#endif
unsigned int __local_bh_count;
unsigned int __syscall_count;
} ____cacheline_aligned irq_cpustat_t;
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+/* Note that local_irq_count() is replaced by sparc64 specific version for SMP */
+
+#ifndef CONFIG_SMP
+#define irq_enter(cpu, irq) ((void)(irq), local_irq_count(cpu)++)
+#define irq_exit(cpu, irq) ((void)(irq), local_irq_count(cpu)--)
+#else
+#undef local_irq_count
+#define local_irq_count(cpu) (__brlock_array[cpu][BR_GLOBALIRQ_LOCK])
+#define irq_enter(cpu, irq) br_read_lock(BR_GLOBALIRQ_LOCK)
+#define irq_exit(cpu, irq) br_read_unlock(BR_GLOBALIRQ_LOCK)
+#endif
/*
* Are we in an interrupt context? Either doing bottom half
* or hardware interrupt processing?
*/
-#define in_interrupt() ({ int __cpu = smp_processor_id(); \
- (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
+#define in_interrupt() ((local_irq_count(smp_processor_id()) + \
+ local_bh_count(smp_processor_id())) != 0)
-#define in_irq() ({ int __cpu = smp_processor_id(); \
- (local_irq_count(__cpu) != 0); })
+/* This tests only the local processors hw IRQ context disposition. */
+#define in_irq() (local_irq_count(smp_processor_id()) != 0)
#ifndef CONFIG_SMP
-#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
-#define hardirq_endlock(cpu) do { (void)(cpu); } while (0)
-
-#define hardirq_enter(cpu) (++local_irq_count(cpu))
-#define hardirq_exit(cpu) (--local_irq_count(cpu))
+#define hardirq_trylock(cpu) ((void)(cpu), local_irq_count(smp_processor_id()) == 0)
+#define hardirq_endlock(cpu) do { (void)(cpu); } while(0)
#define synchronize_irq() barrier()
-#else
+#else /* (CONFIG_SMP) */
-#include <asm/atomic.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <asm/smp.h>
+static __inline__ int irqs_running(void)
+{
+ int i;
+
+ for (i = 0; i < smp_num_cpus; i++)
+ if (local_irq_count(cpu_logical_map(i)))
+ return 1;
+ return 0;
+}
extern unsigned char global_irq_holder;
-extern spinlock_t global_irq_lock;
-extern atomic_t global_irq_count;
static inline void release_irqlock(int cpu)
{
- /* if we didn't own the irq lock, just ignore.. */
- if (global_irq_holder == (unsigned char) cpu) {
+ /* if we didn't own the irq lock, just ignore... */
+ if(global_irq_holder == (unsigned char) cpu) {
global_irq_holder = NO_PROC_ID;
- spin_unlock(&global_irq_lock);
+ br_write_unlock(BR_GLOBALIRQ_LOCK);
}
}
-static inline void hardirq_enter(int cpu)
-{
- ++local_irq_count(cpu);
- atomic_inc(&global_irq_count);
-}
-
-static inline void hardirq_exit(int cpu)
-{
- atomic_dec(&global_irq_count);
- --local_irq_count(cpu);
-}
-
static inline int hardirq_trylock(int cpu)
{
- return (! atomic_read(&global_irq_count) &&
- ! spin_is_locked (&global_irq_lock));
+ spinlock_t *lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock;
+
+ return (!local_irq_count(cpu) && !spin_is_locked(lock));
}
-#define hardirq_endlock(cpu) do { } while (0)
+#define hardirq_endlock(cpu) do { (void)(cpu); } while (0)
extern void synchronize_irq(void);
-/* $Id: irq.h,v 1.31 2000/08/05 10:48:41 davem Exp $
+/* $Id: irq.h,v 1.32 2000/08/26 02:42:28 anton Exp $
* irq.h: IRQ registers on the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -21,18+21,6 @@ BTFIXUPDEF_CALL(char *, __irq_itoa, unsigned int)
#define NR_IRQS 15
-/* IRQ handler dispatch entry and exit. */
-#ifdef CONFIG_SMP
-#define irq_enter(cpu, irq) \
-do { hardirq_enter(cpu); \
- spin_unlock_wait(&global_irq_lock); \
- } while(0)
-#define irq_exit(cpu, irq) hardirq_exit(cpu)
-#else
-#define irq_enter(cpu, irq) (++local_irq_count(cpu))
-#define irq_exit(cpu, irq) (--local_irq_count(cpu))
-#endif
-
/* Dave Redman (djhr@tadpole.co.uk)
* changed these to function pointers.. it saves cycles and will allow
* the irq dependencies to be split into different files at a later date
-/* $Id: oplib.h,v 1.20 1998/09/17 11:05:25 jj Exp $
+/* $Id: oplib.h,v 1.21 2000/08/26 02:38:04 anton Exp $
* oplib.h: Describes the interface and available routines in the
* Linux Prom library.
*
#define __SPARC_OPLIB_H
#include <asm/openprom.h>
+#include <linux/spinlock.h>
/* The master romvec pointer... */
extern struct linux_romvec *romvec;
@@ -311,6+312,7 @@ extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nr /* Apply ranges of any prom node (and optionally parent node as well) to registers. */
extern void prom_apply_generic_ranges(int node, int parent,
struct linux_prom_registers *sbusregs, int nregs);
-
+
+extern spinlock_t prom_lock;
#endif /* !(__SPARC_OPLIB_H) */
-/* $Id: uaccess.h,v 1.21 2000/01/08 16:38:23 anton Exp $
+/* $Id: uaccess.h,v 1.22 2000/08/29 07:01:58 davem Exp $
* uaccess.h: User space memore access functions.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -94,27+94,17 @@ extern void __ret_efault(void); unsigned long __pu_addr = (unsigned long)(ptr); \
__put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
-#define put_user_ret(x,ptr,retval) ({ \
-unsigned long __pu_addr = (unsigned long)(ptr); \
-__put_user_check_ret((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr)),retval); })
-
#define get_user(x,ptr) ({ \
unsigned long __gu_addr = (unsigned long)(ptr); \
__get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
-#define get_user_ret(x,ptr,retval) ({ \
-unsigned long __gu_addr = (unsigned long)(ptr); \
-__get_user_check_ret((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr)),retval); })
-
/*
* The "__xxx" versions do not do address space checking, useful when
* doing multiple accesses to the same area (the user has to do the
* checks by hand with "access_ok()")
*/
#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
-#define __put_user_ret(x,ptr,retval) __put_user_nocheck_ret((x),(ptr),sizeof(*(ptr)),retval)
#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
-#define __get_user_ret(x,ptr,retval) __get_user_nocheck_ret((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)),retval)
struct __large_struct { unsigned long buf[100]; };
#define __m(x) ((struct __large_struct *)(x))
@@ -303,20+293,10 @@ __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ } else __copy_res = __copy_size; \
__copy_res; })
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
- return retval; \
-})
-
#define __copy_to_user(to,from,n) \
__copy_user((void *)(to), \
(void *)(from), n)
-#define __copy_to_user_ret(to,from,n,retval) ({ \
-if (__copy_to_user(to,from,n)) \
- return retval; \
-})
-
#define copy_from_user(to,from,n) ({ \
void *__copy_to = (void *) (to); \
void *__copy_from = (void *) (from); \
@@ -327,20+307,10 @@ __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ } else __copy_res = __copy_size; \
__copy_res; })
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
- return retval; \
-})
-
#define __copy_from_user(to,from,n) \
__copy_user((void *)(to), \
(void *)(from), n)
-#define __copy_from_user_ret(to,from,n,retval) ({ \
-if (__copy_from_user(to,from,n)) \
- return retval; \
-})
-
extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
{
__kernel_size_t ret;
@@ -368,11+338,6 @@ __clear_res = __clear_user(__clear_addr, __clear_size); \ } else __clear_res = __clear_size; \
__clear_res; })
-#define clear_user_ret(addr,size,retval) ({ \
-if (clear_user(addr,size)) \
- return retval; \
-})
-
extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count);
#define strncpy_from_user(dest,src,count) ({ \
-/* $Id: uaccess.h,v 1.32 1999/11/23 08:56:48 davem Exp $ */
+/* $Id: uaccess.h,v 1.33 2000/08/29 07:01:58 davem Exp $ */
#ifndef _ASM_UACCESS_H
#define _ASM_UACCESS_H
@@ -102,22+102,12 @@ extern void __ret_efault(void); unsigned long __pu_addr = (unsigned long)(ptr); \
__put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
-#define put_user_ret(x,ptr,retval) ({ \
-unsigned long __pu_addr = (unsigned long)(ptr); \
-__put_user_nocheck_ret((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr)),retval); })
-
#define get_user(x,ptr) ({ \
unsigned long __gu_addr = (unsigned long)(ptr); \
__get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
-#define get_user_ret(x,ptr,retval) ({ \
-unsigned long __gu_addr = (unsigned long)(ptr); \
-__get_user_nocheck_ret((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr)),retval); })
-
#define __put_user(x,ptr) put_user(x,ptr)
-#define __put_user_ret(x,ptr,retval) put_user_ret(x,ptr,retval)
#define __get_user(x,ptr) get_user(x,ptr)
-#define __get_user_ret(x,ptr,retval) get_user_ret(x,ptr,retval)
struct __large_struct { unsigned long buf[100]; };
#define __m(x) ((struct __large_struct *)(x))
@@ -288,44+278,14 @@ extern __kernel_size_t __copy_in_user(void *to, const void *from, __copy_from_user((void *)(to), \
(void *)(from), (__kernel_size_t)(n))
-#define copy_from_user_ret(to,from,n,retval) ({ \
-if (copy_from_user(to,from,n)) \
- return retval; \
-})
-
-#define __copy_from_user_ret(to,from,n,retval) ({ \
-if (__copy_from_user(to,from,n)) \
- return retval; \
-})
-
#define copy_to_user(to,from,n) \
__copy_to_user((void *)(to), \
(void *) (from), (__kernel_size_t)(n))
-#define copy_to_user_ret(to,from,n,retval) ({ \
-if (copy_to_user(to,from,n)) \
- return retval; \
-})
-
-#define __copy_to_user_ret(to,from,n,retval) ({ \
-if (__copy_to_user(to,from,n)) \
- return retval; \
-})
-
#define copy_in_user(to,from,n) \
__copy_in_user((void *)(to), \
(void *) (from), (__kernel_size_t)(n))
-#define copy_in_user_ret(to,from,n,retval) ({ \
-if (copy_in_user(to,from,n)) \
- return retval; \
-})
-
-#define __copy_in_user_ret(to,from,n,retval) ({ \
-if (__copy_in_user(to,from,n)) \
- return retval; \
-})
-
extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
{
extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size);
@@ -336,11+296,6 @@ extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size) #define clear_user(addr,n) \
__clear_user((void *)(addr), (__kernel_size_t)(n))
-#define clear_user_ret(addr,size,retval) ({ \
-if (clear_user(addr,size)) \
- return retval; \
-})
-
extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count);
#define strncpy_from_user(dest,src,count) \
@@ -361,7+361,8 @@ struct address_space { unsigned long nrpages; /* number of pages */
struct address_space_operations *a_ops; /* methods */
void *host; /* owner: inode, block_device */
- struct vm_area_struct *i_mmap; /* list of mappings */
+ struct vm_area_struct *i_mmap; /* list of private mappings */
+ struct vm_area_struct *i_mmap_shared; /* list of shared mappings */
spinlock_t i_shared_lock; /* and spinlock protecting it */
};
@@ -52,7+52,8 @@ struct vm_area_struct { struct vm_area_struct * vm_avl_left;
struct vm_area_struct * vm_avl_right;
- /* For areas with inode, the list inode->i_mapping->i_mmap,
+ /* For areas with an address space and backing store,
+ * one of the address_space->i_mmap{,shared} lists,
* for shm areas, the list of attaches, otherwise unused.
*/
struct vm_area_struct *vm_next_share;
--- /dev/null
+/*
+ * include/linux/nfsd/interface.h
+ *
+ * defines interface between nfsd and other bits of
+ * the kernel. Particularly filesystems (eventually).
+ *
+ * Copyright (C) 2000 Neil Brown <neilb@cse.unsw.edu.au>
+ */
+
+#ifndef LINUX_NFSD_INTERFACE_H
+#define LINUX_NFSD_INTERFACE_H
+
+#ifdef CONFIG_NFSD_MODULE
+
+extern struct nfsd_linkage {
+ long (*do_nfsservctl)(int cmd, void *argp, void *resp);
+} * nfsd_linkage;
+
+#endif
+
+#endif /* LINUX_NFSD_INTERFACE_H */
#include <linux/nfsd/export.h>
#include <linux/nfsd/auth.h>
#include <linux/nfsd/stats.h>
-
+#include <linux/nfsd/interface.h>
/*
* nfsd version
*/
#define PCI_DEVICE_ID_SI_300 0x0300
#define PCI_DEVICE_ID_SI_530 0x0530
#define PCI_DEVICE_ID_SI_540 0x0540
+#define PCI_DEVICE_ID_SI_540_VGA 0x5300
#define PCI_DEVICE_ID_SI_601 0x0601
#define PCI_DEVICE_ID_SI_620 0x0620
#define PCI_DEVICE_ID_SI_630 0x0630
+#define PCI_DEVICE_ID_SI_630_VGA 0x6300
#define PCI_DEVICE_ID_SI_5107 0x5107
#define PCI_DEVICE_ID_SI_5300 0x5300
#define PCI_DEVICE_ID_SI_5511 0x5511
@@ -33,12+33,13 @@ extern unsigned long event; #define CLONE_VM 0x00000100 /* set if VM shared between processes */
#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
#define CLONE_FILES 0x00000400 /* set if open files shared between processes */
-#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */
+#define CLONE_SIGNAL 0x00000800 /* set if signal handlers and blocked signals shared */
#define CLONE_PID 0x00001000 /* set if pid shared */
#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
-#define CLONE_THREAD 0x00010000 /* set if we want to clone the "thread group" */
+
+#define CLONE_SIGHAND CLONE_SIGNAL /* Old name */
/*
* These are the constant used to fake the fixed-point load-average
@@ -233,6+234,7 @@ struct mm_struct { struct signal_struct {
atomic_t count;
struct k_sigaction action[_NSIG];
+ struct sigpending pending;
spinlock_t siglock;
};
@@ -240,6+242,7 @@ struct signal_struct { #define INIT_SIGNALS { \
ATOMIC_INIT(1), \
{ {{0,}}, }, \
+ { NULL, &init_signals.pending.head, }, \
SPIN_LOCK_UNLOCKED }
/*
@@ -366,8+369,10 @@ struct task_struct { /* signal handlers */
spinlock_t sigmask_lock; /* Protects signal and blocked */
struct signal_struct *sig;
- sigset_t signal, blocked;
- struct signal_queue *sigqueue, **sigqueue_tail;
+
+ sigset_t blocked;
+ struct sigpending pending;
+
unsigned long sas_ss_sp;
size_t sas_ss_size;
int (*notifier)(void *priv);
@@ -455,10+460,8 @@ struct task_struct { files: &init_files, \
sigmask_lock: SPIN_LOCK_UNLOCKED, \
sig: &init_signals, \
- signal: {{0}}, \
+ pending: { NULL, &tsk.pending.head, {{0}}}, \
blocked: {{0}}, \
- sigqueue: NULL, \
- sigqueue_tail: &tsk.sigqueue, \
alloc_lock: SPIN_LOCK_UNLOCKED \
}
@@ -575,11+578,11 @@ static inline int signal_pending(struct task_struct *p) return (p->sigpending != 0);
}
-/* Reevaluate whether the task has signals pending delivery.
- This is required every time the blocked sigset_t changes.
- All callers should have t->sigmask_lock. */
-
-static inline void recalc_sigpending(struct task_struct *t)
+/*
+ * Re-calculate pending state from the set of locally pending
+ * signals, globally pending signals, and blocked signals.
+ */
+static inline int has_pending_signals(sigset_t *p1, sigset_t *p2, sigset_t *blocked)
{
unsigned long ready;
long i;
@@ -587,23+590,31 @@ static inline void recalc_sigpending(struct task_struct *t) switch (_NSIG_WORDS) {
default:
for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;)
- ready |= t->signal.sig[i] &~ t->blocked.sig[i];
+ ready |= (p1->sig[i] | p2->sig[i]) &~ blocked->sig[i];
break;
- case 4: ready = t->signal.sig[3] &~ t->blocked.sig[3];
- ready |= t->signal.sig[2] &~ t->blocked.sig[2];
- ready |= t->signal.sig[1] &~ t->blocked.sig[1];
- ready |= t->signal.sig[0] &~ t->blocked.sig[0];
+ case 4: ready = (p1->sig[3] | p2->sig[3]) &~ blocked->sig[3];
+ ready |= (p1->sig[2] | p2->sig[2]) &~ blocked->sig[2];
+ ready |= (p1->sig[1] | p2->sig[1]) &~ blocked->sig[1];
+ ready |= (p1->sig[0] | p2->sig[0]) &~ blocked->sig[0];
break;
- case 2: ready = t->signal.sig[1] &~ t->blocked.sig[1];
- ready |= t->signal.sig[0] &~ t->blocked.sig[0];
+ case 2: ready = (p1->sig[1] | p2->sig[1]) &~ blocked->sig[1];
+ ready |= (p1->sig[0] | p2->sig[0]) &~ blocked->sig[0];
break;
- case 1: ready = t->signal.sig[0] &~ t->blocked.sig[0];
+ case 1: ready = (p1->sig[0] | p2->sig[0]) &~ blocked->sig[0];
}
+ return ready != 0;
+}
+
+/* Reevaluate whether the task has signals pending delivery.
+ This is required every time the blocked sigset_t changes.
+ All callers should have t->sigmask_lock. */
- t->sigpending = (ready != 0);
+static inline void recalc_sigpending(struct task_struct *t)
+{
+ t->sigpending = has_pending_signals(&t->pending.signal, &t->sig->pending.signal, &t->blocked);
}
/* True if we are on the alternate signal stack. */
* Real Time signals may be queued.
*/
-struct signal_queue
-{
- struct signal_queue *next;
+struct sigqueue {
+ struct sigqueue *next;
siginfo_t info;
};
+struct sigpending {
+ struct sigqueue *head, **tail;
+ sigset_t signal;
+};
+
/*
* Define some primitives to manipulate sigset_t.
*/
@@ -207,6+211,13 @@ extern inline void siginitsetinv(sigset_t *set, unsigned long mask)
#endif /* __HAVE_ARCH_SIG_SETOPS */
+static inline void init_sigpending(struct sigpending *sig)
+{
+ sigemptyset(&sig->signal);
+ sig->head = NULL;
+ sig->tail = &sig->head;
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SIGNAL_H */
/*
* Definitions for bulk memory services
*
- * bulkmem.h 1.11 1999/10/25 20:23:16
+ * bulkmem.h 1.12 2000/06/12 21:55:41
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * bus_ops.h 1.8 1999/10/25 20:23:16
+ * bus_ops.h 1.10 2000/06/12 21:55:41
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * ciscode.h 1.40 2000/02/01 19:06:40
+ * ciscode.h 1.45 2000/08/12 02:08:23
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
#define MANFID_NEW_MEDIA 0x0057
+#define MANFID_NOKIA 0x0124
+#define PRODID_NOKIA_CARDPHONE 0x0900
+
#define MANFID_OLICOM 0x0121
#define PRODID_OLICOM_OC2231 0x3122
#define PRODID_OLICOM_OC2232 0x3222
#define MANFID_PIONEER 0x000b
#define MANFID_PSION 0x016c
+#define PRODID_PSION_NET100 0x0023
#define MANFID_QUATECH 0x0137
#define PRODID_QUATECH_SPP100 0x0003
#define MANFID_SOCKET 0x0104
#define PRODID_SOCKET_DUAL_RS232 0x0006
+#define PRODID_SOCKET_EIO 0x000a
#define PRODID_SOCKET_LPE 0x000d
#define MANFID_SUNDISK 0x0045
#define MANFID_TDK 0x0105
+#define MANFID_TOSHIBA 0x0098
+
#define MANFID_XIRCOM 0x0105
#endif /* _LINUX_CISCODE_H */
/*
- * cisreg.h 1.16 2000/01/16 19:19:14
+ * cisreg.h 1.17 2000/06/12 21:55:41
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * cistpl.h 1.32 2000/01/11 19:06:50
+ * cistpl.h 1.34 2000/06/19 23:18:12
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
#define CISTPL_BYTEORDER 0x43
#define CISTPL_DATE 0x44
#define CISTPL_BATTERY 0x45
+#define CISTPL_FORMAT_A 0x47
/* Layer 3 tuples */
#define CISTPL_ORG 0x46
#define CISTPL_SPCL 0x90
@@ -530,6+531,21 @@ typedef struct cistpl_org_t { #define CISTPL_ORG_APPSPEC 0x01
#define CISTPL_ORG_XIP 0x02
+typedef struct cistpl_format_t {
+ u_char type;
+ u_char edc;
+ u_int offset;
+ u_int length;
+} cistpl_format_t;
+
+#define CISTPL_FORMAT_DISK 0x00
+#define CISTPL_FORMAT_MEM 0x01
+
+#define CISTPL_EDC_NONE 0x00
+#define CISTPL_EDC_CKSUM 0x01
+#define CISTPL_EDC_CRC 0x02
+#define CISTPL_EDC_PCC 0x03
+
typedef union cisparse_t {
cistpl_device_t device;
cistpl_checksum_t checksum;
@@ -548,6+564,7 @@ typedef union cisparse_t { cistpl_device_geo_t device_geo;
cistpl_vers_2_t vers_2;
cistpl_org_t org;
+ cistpl_format_t format;
} cisparse_t;
typedef struct tuple_t {
/*
- * cs.h 1.69 1999/10/25 20:23:17
+ * cs.h 1.71 2000/08/29 00:54:20
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
@@ -251,11+251,6 @@ typedef struct eventmask_t { #define PRESENT_IOBASE_3 0x100
#define PRESENT_IOSIZE 0x200
-/* Attributes for Request/GetConfiguration */
-#define CONF_ENABLE_IRQ 0x01
-#define EXCLUSIVE_USE 0x02
-#define VALID_CLIENT 0x04
-
/* For GetMemPage, MapMemPage */
typedef struct memreq_t {
u_int CardOffset;
/*
- * cs_types.h 1.17 2000/01/18 01:14:36
+ * cs_types.h 1.18 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * driver_ops.h 1.14 1999/10/25 20:23:17
+ * driver_ops.h 1.15 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * ds.h 1.55 1999/10/25 20:23:17
+ * ds.h 1.56 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * ftl.h 1.7 1999/10/25 20:23:17
+ * ftl.h 1.8 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * mem_op.h 1.12 1999/10/25 20:23:17
+ * mem_op.h 1.13 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * memory.h 1.6 1999/10/25 20:23:17
+ * memory.h 1.7 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
/*
- * ss.h 1.26 2000/02/04 20:35:21
+ * ss.h 1.28 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
@@ -61,6+61,7 @@ typedef struct socket_cap_t { #define SS_CAP_PAGE_REGS 0x0001
#define SS_CAP_VIRTUAL_BUS 0x0002
#define SS_CAP_MEM_ALIGN 0x0004
+#define SS_CAP_STATIC_MAP 0x0008
#define SS_CAP_PCCARD 0x4000
#define SS_CAP_CARDBUS 0x8000
-/* version.h 1.83 2000/02/03 02:16:14 (David Hinds) */
+/* version.h 1.92 2000/07/21 18:26:56 (David Hinds) */
-#define CS_RELEASE "3.1.11"
-#define CS_RELEASE_CODE 0x310b
+#define CS_RELEASE "3.1.20"
+#define CS_RELEASE_CODE 0x3115
@@ -584,7+584,7 @@ asmlinkage void __init start_kernel(void) * make syscalls (and thus be locked).
*/
smp_init();
- kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
unlock_kernel();
current->need_resched = 1;
cpu_idle();
@@ -267,26+267,6 @@ void exit_fs(struct task_struct *tsk) __exit_fs(tsk);
}
-static inline void __exit_sighand(struct task_struct *tsk)
-{
- struct signal_struct * sig = tsk->sig;
-
- if (sig) {
- spin_lock_irq(&tsk->sigmask_lock);
- tsk->sig = NULL;
- spin_unlock_irq(&tsk->sigmask_lock);
- if (atomic_dec_and_test(&sig->count))
- kmem_cache_free(sigact_cachep, sig);
- }
-
- flush_signals(tsk);
-}
-
-void exit_sighand(struct task_struct *tsk)
-{
- __exit_sighand(tsk);
-}
-
/*
* We can use these to temporarily drop into
* "lazy TLB" mode and back.
@@ -461,7+441,7 @@ fake_volatile: __exit_mm(tsk);
__exit_files(tsk);
__exit_fs(tsk);
- __exit_sighand(tsk);
+ exit_sighand(tsk);
exit_thread();
tsk->state = TASK_ZOMBIE;
tsk->exit_code = code;
@@ -500,15+500,21 @@ out_release:
static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
{
- if (clone_flags & CLONE_SIGHAND) {
+ struct signal_struct *sig;
+
+ if (clone_flags & CLONE_SIGNAL) {
atomic_inc(¤t->sig->count);
return 0;
}
- tsk->sig = kmem_cache_alloc(sigact_cachep, GFP_KERNEL);
- if (!tsk->sig)
+ sig = kmem_cache_alloc(sigact_cachep, GFP_KERNEL);
+ tsk->sig = sig;
+ if (!sig)
return -1;
- spin_lock_init(&tsk->sig->siglock);
- atomic_set(&tsk->sig->count, 1);
+ spin_lock_init(&sig->siglock);
+ atomic_set(&sig->count, 1);
+
+ init_sigpending(&sig->pending);
+
memcpy(tsk->sig->action, current->sig->action, sizeof(tsk->sig->action));
return 0;
}
@@ -591,9+597,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) spin_lock_init(&p->alloc_lock);
p->sigpending = 0;
- sigemptyset(&p->signal);
- p->sigqueue = NULL;
- p->sigqueue_tail = &p->sigqueue;
+ init_sigpending(&p->pending);
p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
@@ -664,7+668,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) p->tgid = retval;
INIT_LIST_HEAD(&p->thread_group);
write_lock_irq(&tasklist_lock);
- if (clone_flags & CLONE_THREAD) {
+ if (clone_flags & CLONE_SIGNAL) {
p->tgid = current->tgid;
list_add(&p->thread_group, ¤t->thread_group);
}
extern int console_loglevel;
extern void set_device_ro(kdev_t dev,int flag);
-#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
-extern long (*do_nfsservctl)(int, void *, void *);
-#endif
extern void *sys_call_table;
@@ -265,10+262,6 @@ EXPORT_SYMBOL(filemap_swapout); EXPORT_SYMBOL(filemap_sync);
EXPORT_SYMBOL(lock_page);
-#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
-EXPORT_SYMBOL(do_nfsservctl);
-#endif
-
/* device registration */
EXPORT_SYMBOL(register_chrdev);
EXPORT_SYMBOL(unregister_chrdev);
@@ -213,7+213,9 @@ static inline int preemption_goodness(struct task_struct * prev, struct task_str * This function must be inline as anything that saves and restores
* flags has to do so within the same register window on sparc (Anton)
*/
-static inline void reschedule_idle(struct task_struct * p, unsigned long flags)
+static FASTCALL(void reschedule_idle(struct task_struct * p));
+
+static void reschedule_idle(struct task_struct * p)
{
#ifdef CONFIG_SMP
int this_cpu = smp_processor_id();
@@ -284,7+286,6 @@ static inline void reschedule_idle(struct task_struct * p, unsigned long flags) goto preempt_now;
}
- spin_unlock_irqrestore(&runqueue_lock, flags);
return;
send_now_idle:
@@ -296,12+297,10 @@ send_now_idle: if ((tsk->processor != current->processor) && !tsk->need_resched)
smp_send_reschedule(tsk->processor);
tsk->need_resched = 1;
- spin_unlock_irqrestore(&runqueue_lock, flags);
return;
preempt_now:
tsk->need_resched = 1;
- spin_unlock_irqrestore(&runqueue_lock, flags);
/*
* the APIC stuff can go outside of the lock because
* it uses no task information, only CPU#.
@@ -316,7+315,6 @@ preempt_now: tsk = cpu_curr(this_cpu);
if (preemption_goodness(tsk, p, this_cpu) > 1)
tsk->need_resched = 1;
- spin_unlock_irqrestore(&runqueue_lock, flags);
#endif
}
@@ -365,9+363,7 @@ inline void wake_up_process(struct task_struct * p) if (task_on_runqueue(p))
goto out;
add_to_runqueue(p);
- reschedule_idle(p, flags); // spin_unlocks runqueue
-
- return;
+ reschedule_idle(p);
out:
spin_unlock_irqrestore(&runqueue_lock, flags);
}
@@ -480,10+476,9 @@ out_unlock: * current process as well.)
*/
running_again:
- if (prev == idle_task(smp_processor_id()))
- goto out_unlock;
- reschedule_idle(prev, flags); // spin_unlocks runqueue
- return;
+ if (prev != idle_task(smp_processor_id()))
+ reschedule_idle(prev);
+ goto out_unlock;
#endif /* CONFIG_SMP */
}
@@ -656,6+651,9 @@ still_running_back:
same_process:
reacquire_kernel_lock(current);
+ if (current->need_resched)
+ goto tq_scheduler_back;
+
return;
recalculate:
@@ -1142,13+1140,13 @@ static void show_task(struct task_struct * p) printk("\n");
{
- struct signal_queue *q;
+ struct sigqueue *q;
char s[sizeof(sigset_t)*2+1], b[sizeof(sigset_t)*2+1];
- render_sigset_t(&p->signal, s);
+ render_sigset_t(&p->pending.signal, s);
render_sigset_t(&p->blocked, b);
printk(" sig: %d %s %s :", signal_pending(p), s, b);
- for (q = p->sigqueue; q ; q = q->next)
+ for (q = p->pending.head; q ; q = q->next)
printk(" %d", q->info.si_signo);
printk(" X\n");
}
#define SIG_SLAB_DEBUG 0
#endif
-static kmem_cache_t *signal_queue_cachep;
+static kmem_cache_t *sigqueue_cachep;
atomic_t nr_queued_signals;
int max_queued_signals = 1024;
void __init signals_init(void)
{
- signal_queue_cachep =
- kmem_cache_create("signal_queue",
- sizeof(struct signal_queue),
- __alignof__(struct signal_queue),
+ sigqueue_cachep =
+ kmem_cache_create("sigqueue",
+ sizeof(struct sigqueue),
+ __alignof__(struct sigqueue),
SIG_SLAB_DEBUG, NULL, NULL);
- if (!signal_queue_cachep)
- panic("signals_init(): cannot create signal_queue SLAB cache");
+ if (!sigqueue_cachep)
+ panic("signals_init(): cannot create sigueue SLAB cache");
}
/* Given the mask, find the first available signal that should be serviced. */
static int
-next_signal(sigset_t *signal, sigset_t *mask)
+next_signal(struct task_struct *tsk, sigset_t *mask)
{
- unsigned long i, *s, *m, x;
+ unsigned long i, *s1, *s2, *m, x;
int sig = 0;
- s = signal->sig;
+ s1 = tsk->pending.signal.sig;
+ s2 = tsk->sig->pending.signal.sig;
m = mask->sig;
switch (_NSIG_WORDS) {
default:
- for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m)
- if ((x = *s &~ *m) != 0) {
+ for (i = 0; i < _NSIG_WORDS; ++i, ++s1, ++s2, ++m)
+ if ((x = (*s1 | *s2) &~ *m) != 0) {
sig = ffz(~x) + i*_NSIG_BPW + 1;
break;
}
break;
- case 2: if ((x = s[0] &~ m[0]) != 0)
+ case 2: if ((x = (s1[0] | s2[0]) &~ m[0]) != 0)
sig = 1;
- else if ((x = s[1] &~ m[1]) != 0)
+ else if ((x = (s1[1] | s2[1]) &~ m[1]) != 0)
sig = _NSIG_BPW + 1;
else
break;
sig += ffz(~x);
break;
- case 1: if ((x = *s &~ *m) != 0)
+ case 1: if ((x = (*s1 | *s2) &~ *m) != 0)
sig = ffz(~x) + 1;
break;
}
@@ -81,6+82,23 @@ next_signal(sigset_t *signal, sigset_t *mask) return sig;
}
+static void flush_sigqueue(struct sigpending *queue)
+{
+ struct sigqueue *q, *n;
+
+ sigemptyset(&queue->signal);
+ q = queue->head;
+ queue->head = NULL;
+ queue->tail = &queue->head;
+
+ while (q) {
+ n = q->next;
+ kmem_cache_free(sigqueue_cachep, q);
+ atomic_dec(&nr_queued_signals);
+ q = n;
+ }
+}
+
/*
* Flush all pending signals for a task.
*/
@@ -88,20+106,26 @@ next_signal(sigset_t *signal, sigset_t *mask) void
flush_signals(struct task_struct *t)
{
- struct signal_queue *q, *n;
-
t->sigpending = 0;
- sigemptyset(&t->signal);
- q = t->sigqueue;
- t->sigqueue = NULL;
- t->sigqueue_tail = &t->sigqueue;
+ flush_sigqueue(&t->pending);
+ flush_sigqueue(&t->pending);
+}
- while (q) {
- n = q->next;
- kmem_cache_free(signal_queue_cachep, q);
- atomic_dec(&nr_queued_signals);
- q = n;
+void exit_sighand(struct task_struct *tsk)
+{
+ struct signal_struct * sig = tsk->sig;
+
+ spin_lock_irq(&tsk->sigmask_lock);
+ if (sig) {
+ tsk->sig = NULL;
+ if (atomic_dec_and_test(&sig->count)) {
+ flush_sigqueue(&sig->pending);
+ kmem_cache_free(sigact_cachep, sig);
+ }
}
+ tsk->sigpending = 0;
+ flush_sigqueue(&tsk->pending);
+ spin_unlock_irq(&tsk->sigmask_lock);
}
/*
@@ -148,6+172,53 @@ unblock_all_signals(void) recalc_sigpending(current);
}
+static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+{
+ if (sigismember(&list->signal, sig)) {
+ /* Collect the siginfo appropriate to this signal. */
+ struct sigqueue *q, **pp;
+ pp = &list->head;
+ while ((q = *pp) != NULL) {
+ if (q->info.si_signo == sig)
+ goto found_it;
+ pp = &q->next;
+ }
+
+ /* Ok, it wasn't in the queue. We must have
+ been out of queue space. So zero out the
+ info. */
+ info->si_signo = sig;
+ info->si_errno = 0;
+ info->si_code = 0;
+ info->si_pid = 0;
+ info->si_uid = 0;
+ return 1;
+
+found_it:
+ if ((*pp = q->next) == NULL)
+ list->tail = pp;
+
+ /* Copy the sigqueue information and free the queue entry */
+ copy_siginfo(info, &q->info);
+ kmem_cache_free(sigqueue_cachep,q);
+ atomic_dec(&nr_queued_signals);
+
+ /* Non-RT signals can exist multiple times.. */
+ if (sig >= SIGRTMIN) {
+ while ((q = *pp) != NULL) {
+ if (q->info.si_signo == sig)
+ goto found_another;
+ pp = &q->next;
+ }
+ }
+
+ sigdelset(&list->signal, sig);
+found_another:
+ return 1;
+ }
+ return 0;
+}
+
/*
* Dequeue a signal and return the element to the caller, which is
* expected to free it.
@@ -165,7+236,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid, signal_pending(current));
#endif
- sig = next_signal(¤t->signal, mask);
+ sig = next_signal(current, mask);
if (current->notifier) {
sigset_t merged;
int i;
@@ -174,7+245,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid, for (i = 0; i < _NSIG_WORDS; i++)
merged.sig[i] = mask->sig[i]
| current->notifier_mask->sig[i];
- altsig = next_signal(¤t->signal, &merged);
+ altsig = next_signal(current, &merged);
if (sig != altsig) {
if (!(current->notifier)(current->notifier_data)) {
current->sigpending = 0;
@@ -184,63+255,14 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid, }
if (sig) {
- int reset = 1;
-
- /* Collect the siginfo appropriate to this signal. */
- struct signal_queue *q, **pp;
- pp = ¤t->sigqueue;
- q = current->sigqueue;
-
- /* Find the one we're interested in ... */
- for ( ; q ; pp = &q->next, q = q->next)
- if (q->info.si_signo == sig)
- break;
- if (q) {
- if ((*pp = q->next) == NULL)
- current->sigqueue_tail = pp;
- copy_siginfo(info, &q->info);
- kmem_cache_free(signal_queue_cachep,q);
- atomic_dec(&nr_queued_signals);
-
- /* Then see if this signal is still pending.
- (Non rt signals may not be queued twice.)
- */
- if (sig >= SIGRTMIN)
- for (q = *pp; q; q = q->next)
- if (q->info.si_signo == sig) {
- reset = 0;
- break;
- }
-
- } else {
- /* Ok, it wasn't in the queue. We must have
- been out of queue space. So zero out the
- info. */
- info->si_signo = sig;
- info->si_errno = 0;
- info->si_code = 0;
- info->si_pid = 0;
- info->si_uid = 0;
- }
-
- if (reset) {
- sigdelset(¤t->signal, sig);
- recalc_sigpending(current);
- }
-
+ if (!collect_signal(sig, ¤t->pending, info))
+ if (!collect_signal(sig, ¤t->sig->pending, info))
+ sig = 0;
+
/* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
we need to xchg out the timer overrun values. */
- } else {
- /* XXX: Once CLONE_PID is in to join those "threads" that are
- part of the same "process", look for signals sent to the
- "process" as well. */
-
- /* Sanity check... */
- if (mask == ¤t->blocked && signal_pending(current)) {
- printk(KERN_CRIT "SIG: sigpending lied\n");
- current->sigpending = 0;
- }
}
+ recalc_sigpending(current);
#if DEBUG_SIG
printk(" %d -> %d\n", signal_pending(current), sig);
@@ -249,44+271,42 @@ printk(" %d -> %d\n", signal_pending(current), sig); return sig;
}
-/*
- * Remove signal sig from queue and from t->signal.
- * Returns 1 if sig was found in t->signal.
- *
- * All callers must be holding t->sigmask_lock.
- */
-static int rm_sig_from_queue(int sig, struct task_struct *t)
+static int rm_from_queue(int sig, struct sigpending *s)
{
- struct signal_queue *q, **pp;
+ struct sigqueue *q, **pp;
- if (sig >= SIGRTMIN) {
- printk(KERN_CRIT "SIG: rm_sig_from_queue() doesn't support rt signals\n");
+ if (!sigismember(&s->signal, sig))
return 0;
- }
- if (!sigismember(&t->signal, sig))
- return 0;
-
- sigdelset(&t->signal, sig);
+ sigdelset(&s->signal, sig);
- pp = &t->sigqueue;
- q = t->sigqueue;
+ pp = &s->head;
- /* Find the one we're interested in ...
- It may appear only once. */
- for ( ; q ; pp = &q->next, q = q->next)
- if (q->info.si_signo == sig)
- break;
- if (q) {
- if ((*pp = q->next) == NULL)
- t->sigqueue_tail = pp;
- kmem_cache_free(signal_queue_cachep,q);
- atomic_dec(&nr_queued_signals);
+ while ((q = *pp) != NULL) {
+ if (q->info.si_signo == sig) {
+ if ((*pp = q->next) == NULL)
+ s->tail = pp;
+ kmem_cache_free(sigqueue_cachep,q);
+ atomic_dec(&nr_queued_signals);
+ continue;
+ }
+ pp = &q->next;
}
return 1;
}
/*
+ * Remove signal sig from t->pending.
+ * Returns 1 if sig was found.
+ *
+ * All callers must be holding t->sigmask_lock.
+ */
+static int rm_sig_from_queue(int sig, struct task_struct *t)
+{
+ return rm_from_queue(sig, &t->pending) | rm_from_queue(sig, &t->sig->pending);
+}
+
+/*
* Bad permissions for sending the signal
*/
int bad_signal(int sig, struct siginfo *info, struct task_struct *t)
@@ -299,6+319,46 @@ int bad_signal(int sig, struct siginfo *info, struct task_struct *t) }
/*
+ * Signal type:
+ * < 0 : global action (kill - spread to all non-blocked threads)
+ * = 0 : ignored
+ * > 0 : wake up.
+ */
+static int signal_type(int sig, struct signal_struct *signals)
+{
+ unsigned long handler;
+
+ if (!signals)
+ return 0;
+
+ handler = (unsigned long) signals->action[sig-1].sa.sa_handler;
+ if (handler > 1)
+ return 1;
+
+ /* "Ignore" handler.. Illogical, but that has an implicit handler for SIGCHLD */
+ if (handler == 1)
+ return sig == SIGCHLD;
+
+ /* Default handler. Normally lethal, but.. */
+ switch (sig) {
+
+ /* Ignored */
+ case SIGCONT: case SIGWINCH:
+ case SIGCHLD: case SIGURG:
+ return 0;
+
+ /* Implicit behaviour */
+ case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ return 1;
+
+ /* Implicit actions (kill or do special stuff) */
+ default:
+ return -1;
+ }
+}
+
+
+/*
* Determine whether a signal should be posted or not.
*
* Signals with SIG_IGN can be ignored, except for the
@@ -308,41+368,18 @@ int bad_signal(int sig, struct siginfo *info, struct task_struct *t) */
static int ignored_signal(int sig, struct task_struct *t)
{
- struct signal_struct *signals;
- struct k_sigaction *ka;
-
/* Don't ignore traced or blocked signals */
if ((t->ptrace & PT_PTRACED) || sigismember(&t->blocked, sig))
return 0;
-
- signals = t->sig;
- if (!signals)
- return 1;
-
- ka = &signals->action[sig-1];
- switch ((unsigned long) ka->sa.sa_handler) {
- case (unsigned long) SIG_DFL:
- if (sig == SIGCONT ||
- sig == SIGWINCH ||
- sig == SIGCHLD ||
- sig == SIGURG)
- break;
- return 0;
- case (unsigned long) SIG_IGN:
- if (sig != SIGCHLD)
- break;
- /* fallthrough */
- default:
- return 0;
- }
- return 1;
+ return signal_type(sig, t->sig) == 0;
}
/*
- * Handle TASK_STOPPED.
- * Also, return true for the unblockable signals that we
- * should deliver to all threads..
+ * Handle TASK_STOPPED cases etc implicit behaviour
+ * of certain magical signals.
+ *
+ * SIGKILL gets spread out to every thread.
*/
static void handle_stop_signal(int sig, struct task_struct *t)
{
@@ -352,24+389,23 @@ static void handle_stop_signal(int sig, struct task_struct *t) if (t->state == TASK_STOPPED)
wake_up_process(t);
t->exit_code = 0;
- if (rm_sig_from_queue(SIGSTOP, t) || rm_sig_from_queue(SIGTSTP, t) ||
- rm_sig_from_queue(SIGTTOU, t) || rm_sig_from_queue(SIGTTIN, t))
- recalc_sigpending(t);
+ rm_sig_from_queue(SIGSTOP, t);
+ rm_sig_from_queue(SIGTSTP, t);
+ rm_sig_from_queue(SIGTTOU, t);
+ rm_sig_from_queue(SIGTTIN, t);
break;
case SIGSTOP: case SIGTSTP:
case SIGTTIN: case SIGTTOU:
/* If we're stopping again, cancel SIGCONT */
- if (rm_sig_from_queue(SIGCONT, t))
- recalc_sigpending(t);
+ rm_sig_from_queue(SIGCONT, t);
break;
}
- return 0;
}
-static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t)
+static int send_signal(int sig, struct siginfo *info, struct sigpending *signals)
{
- struct signal_queue * q = NULL;
+ struct sigqueue * q = NULL;
/* Real-time signals must be queued if sent by sigqueue, or
some other real-time mechanism. It is implementation
@@ -380,14+416,14 @@ static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t) pass on the info struct. */
if (atomic_read(&nr_queued_signals) < max_queued_signals) {
- q = kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
+ q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
}
if (q) {
atomic_inc(&nr_queued_signals);
q->next = NULL;
- *t->sigqueue_tail = q;
- t->sigqueue_tail = &q->next;
+ *signals->tail = q;
+ signals->tail = &q->next;
switch ((unsigned long) info) {
case 0:
q->info.si_signo = sig;
@@ -416,46+452,57 @@ static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t) return -EAGAIN;
}
- sigaddset(&t->signal, sig);
- if (!sigismember(&t->blocked, sig)) {
- t->sigpending = 1;
-#ifdef CONFIG_SMP
- /*
- * If the task is running on a different CPU
- * force a reschedule on the other CPU - note that
- * the code below is a tad loose and might occasionally
- * kick the wrong CPU if we catch the process in the
- * process of changing - but no harm is done by that
- * other than doing an extra (lightweight) IPI interrupt.
- *
- * note that we rely on the previous spin_lock to
- * lock interrupts for us! No need to set need_resched
- * since signal event passing goes through ->blocked.
- */
- spin_lock(&runqueue_lock);
- if (t->has_cpu && t->processor != smp_processor_id())
- smp_send_reschedule(t->processor);
- spin_unlock(&runqueue_lock);
-#endif /* CONFIG_SMP */
- }
+ sigaddset(&signals->signal, sig);
return 0;
}
-
/*
- * Send a thread-group-wide signal.
+ * Tell a process that it has a new active signal..
*
- * Rule: SIGSTOP and SIGKILL get delivered to _everybody_.
+ * NOTE! we rely on the previous spin_lock to
+ * lock interrupts for us! We can only be called with
+ * "sigmask_lock" held, and the local interrupt must
+ * have been disabled when that got aquired!
*
- * Others get delivered to the thread that doesn't have them
- * blocked (just one such thread).
+ * No need to set need_resched since signal event passing
+ * goes through ->blocked
+ */
+static inline void signal_wake_up(struct task_struct *t)
+{
+ t->sigpending = 1;
+
+ if (t->state & TASK_INTERRUPTIBLE) {
+ wake_up_process(t);
+ return;
+ }
+
+#ifdef CONFIG_SMP
+ /*
+ * If the task is running on a different CPU
+ * force a reschedule on the other CPU to make
+ * it notice the new signal quickly.
+ *
+ * The code below is a tad loose and might occasionally
+ * kick the wrong CPU if we catch the process in the
+ * process of changing - but no harm is done by that
+ * other than doing an extra (lightweight) IPI interrupt.
+ */
+ spin_lock(&runqueue_lock);
+ if (t->has_cpu && t->processor != smp_processor_id())
+ smp_send_reschedule(t->processor);
+ spin_unlock(&runqueue_lock);
+#endif /* CONFIG_SMP */
+}
+
+/*
+ * Send a thread-group-wide signal.
*
- * If all threads have it blocked, it gets delievered to the
- * thread group leader.
+ * Just add it to the shared signal queue. And
+ * make sure to inform everybody.
*/
static int send_tg_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
- int retval = 0;
+ int retval, type;
struct task_struct *tsk;
if (sig < 0 || sig > _NSIG)
@@ -464,13+511,24 @@ static int send_tg_sig_info(int sig, struct siginfo *info, struct task_struct *p if (bad_signal(sig, info, p))
return -EPERM;
- if (!sig)
+ if (!sig || !p->sig)
return 0;
+ /* Have we already delivered this non-queued signal? */
+ if (sig < SIGRTMIN && sigismember(&p->sig->pending.signal, sig))
+ return 0;
+
+ /* Add the signal to the global queue */
+ retval = send_signal(sig, info, &p->sig->pending);
+ if (retval < 0)
+ return retval;
+
+ type = signal_type(sig, p->sig);
+
+ /* Inform all threads about it.. */
tsk = p;
do {
unsigned long flags;
- tsk = next_thread(tsk);
/* Zombie? Ignore */
if (!tsk->sig)
@@ -479,30+537,35 @@ static int send_tg_sig_info(int sig, struct siginfo *info, struct task_struct *p spin_lock_irqsave(&tsk->sigmask_lock, flags);
handle_stop_signal(sig, tsk);
- /* Is the signal ignored by this thread? */
- if (ignored_signal(sig, tsk))
+ /* Blocked? */
+ if (sigismember(&tsk->blocked, sig))
goto next;
- /* Have we already delivered this non-queued signal? */
- if (sig < SIGRTMIN && sigismember(&tsk->signal, sig))
+ /* Is the signal ignored by this thread? */
+ switch (type) {
+ case 0:
goto next;
-
- /* Not blocked? Go, girl, go! */
- if (tsk == p || !sigismember(&tsk->blocked, sig)) {
- retval = deliver_signal(sig, info, tsk);
-
- /* Signals other than SIGKILL and SIGSTOP have "once" semantics */
- if (sig != SIGKILL && sig != SIGSTOP)
- tsk = p;
+ case -1: /* affects all threads? */
+ sigaddset(&tsk->pending.signal, sig);
}
+
+ /* Go, girl, go! */
+ signal_wake_up(tsk);
next:
spin_unlock_irqrestore(&tsk->sigmask_lock, flags);
- if ((tsk->state & TASK_INTERRUPTIBLE) && signal_pending(tsk))
- wake_up_process(tsk);
- } while (tsk != p);
- return retval;
+ } while ((tsk = next_thread(tsk)) != p);
+ return 0;
}
+static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t)
+{
+ int retval = send_signal(sig, info, &t->pending);
+
+ if (!retval && !sigismember(&t->blocked, sig))
+ signal_wake_up(t);
+
+ return retval;
+}
int
send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
@@ -542,7+605,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig); /* Support queueing exactly one non-rt signal, so that we
can get more detailed information about the cause of
the signal. */
- if (sig < SIGRTMIN && sigismember(&t->signal, sig))
+ if (sig < SIGRTMIN && sigismember(&t->pending.signal, sig))
goto out;
ret = deliver_signal(sig, info, t);
@@ -669,9+732,11 @@ static int kill_tg_info(int sig, struct siginfo *info, pid_t pid) error = -ESRCH;
if (p) {
/* Is it the leader? Otherwise it degenerates into a per-thread thing */
- if (p->tgid == pid)
+ if (p->tgid == pid) {
+ spin_lock(&p->sig->siglock);
error = send_tg_sig_info(sig, info, p);
- else
+ spin_unlock(&p->sig->siglock);
+ } else
error = send_sig_info(sig, info, p);
}
read_unlock(&tasklist_lock);
@@ -921,7+986,8 @@ sys_rt_sigpending(sigset_t *set, size_t sigsetsize) goto out;
spin_lock_irq(¤t->sigmask_lock);
- sigandsets(&pending, ¤t->blocked, ¤t->signal);
+ sigorsets(&pending, ¤t->pending.signal, ¤t->sig->pending.signal);
+ sigandsets(&pending, ¤t->blocked, &pending);
spin_unlock_irq(¤t->sigmask_lock);
error = -EFAULT;
@@ -1032,7+1098,7 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) info.si_signo = sig;
/* POSIX.1b doesn't mention process groups. */
- return kill_proc_info(sig, &info, pid);
+ return kill_tg_info(sig, &info, pid);
}
int
@@ -1044,10+1110,12 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) (act && (sig == SIGKILL || sig == SIGSTOP)))
return -EINVAL;
- spin_lock_irq(¤t->sigmask_lock);
k = ¤t->sig->action[sig-1];
- if (oact) *oact = *k;
+ spin_lock(¤t->sig->siglock);
+
+ if (oact)
+ *oact = *k;
if (act) {
*k = *act;
@@ -1075,33+1143,14 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) && (sig == SIGCONT ||
sig == SIGCHLD ||
sig == SIGWINCH))) {
- /* So dequeue any that might be pending.
- XXX: process-wide signals? */
- if (sig >= SIGRTMIN &&
- sigismember(¤t->signal, sig)) {
- struct signal_queue *q, **pp;
- pp = ¤t->sigqueue;
- q = current->sigqueue;
- while (q) {
- if (q->info.si_signo != sig)
- pp = &q->next;
- else {
- if ((*pp = q->next) == NULL)
- current->sigqueue_tail = pp;
- kmem_cache_free(signal_queue_cachep, q);
- atomic_dec(&nr_queued_signals);
- }
- q = *pp;
- }
-
- }
- sigdelset(¤t->signal, sig);
- recalc_sigpending(current);
+ spin_lock_irq(¤t->sigmask_lock);
+ if (rm_sig_from_queue(sig, current))
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
}
}
- spin_unlock_irq(¤t->sigmask_lock);
-
+ spin_unlock(¤t->sig->siglock);
return 0;
}
@@ -1228,7+1277,7 @@ sys_sigpending(old_sigset_t *set) old_sigset_t pending;
spin_lock_irq(¤t->sigmask_lock);
- pending = current->blocked.sig[0] & current->signal.sig[0];
+ pending = current->blocked.sig[0] & (current->pending.signal.sig[0] | current->sig->pending.signal.sig[0]);
spin_unlock_irq(¤t->sigmask_lock);
error = -EFAULT;
@@ -1074,6+1074,13 @@ found_page: goto page_not_up_to_date;
generic_file_readahead(reada_ok, filp, inode, page);
page_ok:
+ /* If users can be writing to this page using arbitrary
+ * virtual addresses, take care about potential aliasing
+ * before reading the page on the kernel side.
+ */
+ if (page->mapping->i_mmap_shared != NULL)
+ flush_dcache_page(page);
+
/*
* Ok, we have the page, and it's up-to-date, so
* now we can copy it to user space...
@@ -924,33+924,9 @@ static void partial_clear(struct vm_area_struct *vma, unsigned long address) memclear_highpage_flush(page, offset, PAGE_SIZE - offset);
}
-/*
- * Handle all mappings that got truncated by a "truncate()"
- * system call.
- *
- * NOTE! We have to be ready to update the memory sharing
- * between the file and the memory map for a potential last
- * incomplete page. Ugly, but necessary.
- */
-void vmtruncate(struct inode * inode, loff_t offset)
+static void vmtruncate_list(struct vm_area_struct *mpnt,
+ unsigned long pgoff, unsigned long partial)
{
- unsigned long partial, pgoff;
- struct vm_area_struct * mpnt;
- struct address_space *mapping = inode->i_mapping;
- unsigned long limit;
-
- if (inode->i_size < offset)
- goto do_expand;
- inode->i_size = offset;
- truncate_inode_pages(mapping, offset);
- spin_lock(&mapping->i_shared_lock);
- if (!mapping->i_mmap)
- goto out_unlock;
-
- pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- partial = (unsigned long)offset & (PAGE_CACHE_SIZE - 1);
-
- mpnt = mapping->i_mmap;
do {
struct mm_struct *mm = mpnt->vm_mm;
unsigned long start = mpnt->vm_start;
@@ -983,6+959,39 @@ void vmtruncate(struct inode * inode, loff_t offset) zap_page_range(mm, start, len);
flush_tlb_range(mm, start, end);
} while ((mpnt = mpnt->vm_next_share) != NULL);
+}
+
+
+/*
+ * Handle all mappings that got truncated by a "truncate()"
+ * system call.
+ *
+ * NOTE! We have to be ready to update the memory sharing
+ * between the file and the memory map for a potential last
+ * incomplete page. Ugly, but necessary.
+ */
+void vmtruncate(struct inode * inode, loff_t offset)
+{
+ unsigned long partial, pgoff;
+ struct address_space *mapping = inode->i_mapping;
+ unsigned long limit;
+
+ if (inode->i_size < offset)
+ goto do_expand;
+ inode->i_size = offset;
+ truncate_inode_pages(mapping, offset);
+ spin_lock(&mapping->i_shared_lock);
+ if (!mapping->i_mmap && !mapping->i_mmap_shared)
+ goto out_unlock;
+
+ pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ partial = (unsigned long)offset & (PAGE_CACHE_SIZE - 1);
+
+ if (mapping->i_mmap != NULL)
+ vmtruncate_list(mapping->i_mmap, pgoff, partial);
+ if (mapping->i_mmap_shared != NULL)
+ vmtruncate_list(mapping->i_mmap_shared, pgoff, partial);
+
out_unlock:
spin_unlock(&mapping->i_shared_lock);
/* this should go into ->truncate */
@@ -1095,15+1104,12 @@ static int do_swap_page(struct mm_struct * mm, */
static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma, pte_t *page_table, int write_access, unsigned long addr)
{
- int high = 0;
struct page *page = NULL;
pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
if (write_access) {
page = alloc_page(GFP_HIGHUSER);
if (!page)
return -1;
- if (PageHighMem(page))
- high = 1;
clear_user_highpage(page, addr);
entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
mm->rss++;
@@ -906,15+906,21 @@ void insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp) if (file) {
struct inode * inode = file->f_dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
+ struct vm_area_struct **head;
+
if (vmp->vm_flags & VM_DENYWRITE)
atomic_dec(&inode->i_writecount);
+
+ head = &mapping->i_mmap;
+ if (vmp->vm_flags & VM_SHARED)
+ head = &mapping->i_mmap_shared;
/* insert vmp into inode's share list */
spin_lock(&mapping->i_shared_lock);
- if((vmp->vm_next_share = mapping->i_mmap) != NULL)
- mapping->i_mmap->vm_pprev_share = &vmp->vm_next_share;
- mapping->i_mmap = vmp;
- vmp->vm_pprev_share = &mapping->i_mmap;
+ if((vmp->vm_next_share = *head) != NULL)
+ (*head)->vm_pprev_share = &vmp->vm_next_share;
+ *head = vmp;
+ vmp->vm_pprev_share = head;
spin_unlock(&mapping->i_shared_lock);
}
}
@@ -646,7+646,7 @@ static int __init kswapd_init(void) {
printk("Starting kswapd v1.7\n");
swap_setup();
- kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
return 0;
}
@@ -155,7+155,10 @@ static ssize_t proc_mpc_read(struct file *file, char *buff, if (*pos >= length) length = 0;
else {
if ((count + *pos) > length) count = length - *pos;
- copy_to_user(buff, (char *)page , count);
+ if (copy_to_user(buff, (char *)page , count)) {
+ free_page(page);
+ return -EFAULT;
+ }
*pos += count;
}
@@ -198,7+201,7 @@ static ssize_t proc_mpc_write(struct file *file, const char *buff, *ppos += incoming;
page[incoming] = '\0';
- retval = parse_qos(buff, incoming);
+ retval = parse_qos(page, incoming);
if (retval == 0)
printk("mpoa: proc_mpc_write: could not parse '%s'\n", page);
* with only 6 digipeaters and sockaddr_ax25 in ax25_bind(),
* ax25_connect() and ax25_sendmsg()
* Joerg(DL1BKE) Added support for SO_BINDTODEVICE
+ * Arnaldo C. Melo s/suser/capable(CAP_NET_ADMIN)/, some more cleanups
*/
#include <linux/config.h>
@@ -817,10+818,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op if (put_user(length, optlen))
return -EFAULT;
- if (copy_to_user(optval, valptr, length))
- return -EFAULT;
-
- return 0;
+ return copy_to_user(optval, valptr, length) ? -EFAULT : 0;
}
static int ax25_listen(struct socket *sock, int backlog)
@@ -1070,7+1068,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL;
call = ax25_findbyuid(current->euid);
- if (call == NULL && ax25_uid_policy && !suser())
+ if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN))
return -EACCES;
if (call == NULL)
@@ -1584,9+1582,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
amount = 0;
- if (put_user(amount, (int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (int *)arg);
}
case TIOCINQ: {
@@ -1595,18+1591,14 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
amount = skb->len;
- if (put_user(amount, (int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (int *)arg);
}
case SIOCGSTAMP:
if (sk != NULL) {
if (sk->stamp.tv_sec == 0)
return -ENOENT;
- if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) : -EFAULT : 0;
}
return -EINVAL;
@@ -1621,7+1613,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCAX25NOUID: { /* Set the default policy (default/bar) */
long amount;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (get_user(amount, (long *)arg))
return -EFAULT;
@@ -1634,12+1626,12 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCADDRT:
case SIOCDELRT:
case SIOCAX25OPTRT:
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
return ax25_rt_ioctl(cmd, (void *)arg);
case SIOCAX25CTLCON:
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
return ax25_ctl_ioctl(cmd, (void *)arg);
@@ -1688,7+1680,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCAX25ADDFWD:
case SIOCAX25DELFWD: {
struct ax25_fwd_struct ax25_fwd;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd)))
return -EFAULT;
* Joerg(DL1BKE) Moved BPQ Ethernet driver to separate device.
* AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating.
* Jonathan(G4KLX) Support for packet forwarding.
+ * Arnaldo C. Melo s/suser/capable/
*/
#include <linux/config.h>
@@ -363,7+364,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) return -EHOSTUNREACH;
if ((call = ax25_findbyuid(current->euid)) == NULL) {
- if (ax25_uid_policy && !suser())
+ if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE))
return -EPERM;
call = (ax25_address *)ax25->ax25_dev->dev->dev_addr;
}
@@ -78,7+78,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) return -ENOENT;
case SIOCAX25ADDUID:
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (ax25_findbyuid(sax->sax25_uid))
return -EEXIST;
@@ -95,7+95,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) return 0;
case SIOCAX25DELUID:
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
* Patrick Caulfield: Fixes to delayed acceptance logic.
* David S. Miller: New socket locking
* Steve Whitehouse: Socket list hashing/locking
+ * Arnaldo C. Melo: use capable, not suser
*/
@@ -688,7+689,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (dn_ntohs(saddr->sdn_nodeaddrl) && (dn_ntohs(saddr->sdn_nodeaddrl) != 2))
return -EINVAL;
- if (saddr->sdn_objnum && !suser())
+ if (saddr->sdn_objnum && !capable(CAP_NET_BIND_SERVICE))
return -EPERM;
if (dn_ntohs(saddr->sdn_objnamel) > DN_MAXOBJL)
@@ -698,7+699,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL;
if (saddr->sdn_flags & SDF_WILD) {
- if (!suser())
+ if (!capable(CAP_NET_BIND_SERVICE))
return -EPERM;
} else {
if (dn_ntohs(saddr->sdn_nodeaddrl)) {
@@ -1101,7+1102,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
#if 0
case SIOCSIFADDR:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
if ((err = copy_from_user(devname, ioarg->devname, 5)) != 0)
break;
@@ -1143,7+1144,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
#if 0
case SIOCSNETADDR:
- if (!suser()) {
+ if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
break;
}
@@ -1174,7+1175,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break;
#endif
case OSIOCSNETADDR:
- if (!suser()) {
+ if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
break;
}
@@ -1189,8+1190,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break;
case OSIOCGNETADDR:
- if ((err = put_user(decnet_address, (unsigned short *)arg)) != 0)
- break;
+ err = put_user(decnet_address, (unsigned short *)arg);
break;
case SIOCGIFCONF:
case SIOCGIFFLAGS:
@@ -641,17+641,15 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void *arg) static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
- int err;
int pid;
switch(cmd)
{
case FIOSETOWN:
case SIOCSPGRP:
- err = get_user(pid, (int *) arg);
- if (err)
- return err;
- if (current->pid != pid && current->pgrp != -pid && !suser())
+ if (get_user(pid, (int *) arg))
+ return -EFAULT;
+ if (current->pid != pid && current->pgrp != -pid && !capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
return(0);
@@ -661,10+659,7 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg case SIOCGSTAMP:
if(sk->stamp.tv_sec==0)
return -ENOENT;
- err = -EFAULT;
- if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
- err = 0;
- return err;
+ return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
case SIOCGIFFLAGS:
case SIOCSIFFLAGS:
case SIOCGIFCONF:
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_minisocks.c,v 1.1 2000/08/09 11:59:04 davem Exp $
+ * Version: $Id: tcp_minisocks.c,v 1.2 2000/08/28 04:32:52 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -742,7+742,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, /* Back to base struct sock members. */
newsk->err = 0;
newsk->priority = 0;
- atomic_set(&newsk->refcnt, 1);
+ atomic_set(&newsk->refcnt, 2);
#ifdef INET_REFCNT_DEBUG
atomic_inc(&inet_sock_nr);
#endif
@@ -966,5+966,6 @@ int tcp_child_process(struct sock *parent, struct sock *child, }
bh_unlock_sock(child);
+ sock_put(child);
return ret;
}
* Jonathan(G4KLX) Removed hdrincl.
* NET/ROM 007 Jonathan(G4KLX) New timer architecture.
* Impmented Idle timer.
+ * Arnaldo C. Melo s/suser/capable/, micro cleanups
*/
#include <linux/config.h>
@@ -437,10+438,7 @@ static int nr_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen))
return -EFAULT;
- if (copy_to_user(optval, &val, len))
- return -EFAULT;
-
- return 0;
+ return copy_to_user(optval, &val, len) ? -EFAULT : 0;
}
static int nr_listen(struct socket *sock, int backlog)
@@ -616,7+614,7 @@ full_sockaddr_ax25)) * Only the super user can set an arbitrary user callsign.
*/
if (addr->fsa_ax25.sax25_ndigis == 1) {
- if (!suser())
+ if (!capable(CAP_NET_BIND_SERVICE))
return -EACCES;
sk->protinfo.nr->user_addr = addr->fsa_digipeater[0];
sk->protinfo.nr->source_addr = addr->fsa_ax25.sax25_call;
@@ -624,7+622,7 @@ full_sockaddr_ax25)) source = &addr->fsa_ax25.sax25_call;
if ((user = ax25_findbyuid(current->euid)) == NULL) {
- if (ax25_uid_policy && !suser())
+ if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE))
return -EPERM;
user = source;
}
@@ -680,7+678,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, source = (ax25_address *)dev->dev_addr;
if ((user = ax25_findbyuid(current->euid)) == NULL) {
- if (ax25_uid_policy && !suser())
+ if (ax25_uid_policy && !capable(CAP_NET_ADMIN))
return -EPERM;
user = source;
}
@@ -1111,9+1109,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
amount = 0;
- if (put_user(amount, (int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (int *)arg);
}
case TIOCINQ: {
@@ -1122,18+1118,14 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
amount = skb->len;
- if (put_user(amount, (int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (int *)arg);
}
case SIOCGSTAMP:
if (sk != NULL) {
if (sk->stamp.tv_sec == 0)
return -ENOENT;
- if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
}
return -EINVAL;
@@ -1152,7+1144,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCADDRT:
case SIOCDELRT:
case SIOCNRDECOBS:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
return nr_rt_ioctl(cmd, (void *)arg);
default:
*
* PACKET - implements raw packet sockets.
*
- * Version: $Id: af_packet.c,v 1.41 2000/08/10 01:21:14 davem Exp $
+ * Version: $Id: af_packet.c,v 1.42 2000/08/29 03:44:56 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Implemented idle timer.
* Added use count to neighbour.
* Tomi(OH2BNS) Fixed rose_getname().
+ * Arnaldo C. Melo s/suser/capable/ + micro cleanups
*/
#include <linux/config.h>
@@ -510,10+511,7 @@ static int rose_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen))
return -EFAULT;
- if (copy_to_user(optval, &val, len))
- return -EFAULT;
-
- return 0;
+ return copy_to_user(optval, &val, len) ? -EFAULT : 0;
}
static int rose_listen(struct socket *sock, int backlog)
@@ -695,7+693,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) source = &addr->srose_call;
if ((user = ax25_findbyuid(current->euid)) == NULL) {
- if (ax25_uid_policy && !suser())
+ if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE))
return -EACCES;
user = source;
}
@@ -1236,9+1234,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
amount = 0;
- if (put_user(amount, (unsigned int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (unsigned int *)arg);
}
case TIOCINQ: {
@@ -1247,18+1243,14 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
amount = skb->len;
- if (put_user(amount, (unsigned int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (unsigned int *)arg);
}
case SIOCGSTAMP:
if (sk != NULL) {
if (sk->stamp.tv_sec == 0)
return -ENOENT;
- if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
}
return -EINVAL;
@@ -1284,9+1276,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) struct rose_cause_struct rose_cause;
rose_cause.cause = sk->protinfo.rose->cause;
rose_cause.diagnostic = sk->protinfo.rose->diagnostic;
- if (copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &rose_cause, sizeof(struct rose_cause_struct)) ? -EFAULT : 0;
}
case SIOCRSSCAUSE: {
@@ -1299,7+1289,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) }
case SIOCRSSL2CALL:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
ax25_listen_release(&rose_callsign, NULL);
if (copy_from_user(&rose_callsign, (void *)arg, sizeof(ax25_address)))
@@ -1309,9+1299,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return 0;
case SIOCRSGL2CALL:
- if (copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &rose_callsign, sizeof(ax25_address)) ? -EFAULT : 0;
case SIOCRSACCEPT:
if (sk->protinfo.rose->state == ROSE_STATE_5) {
* 2000-22-03 Daniela Squassoni Allowed disabling/enabling of
* facilities negotiation and increased
* the throughput upper limit.
+ * 2000-27-08 Arnaldo C. Melo s/suser/capable/ + micro cleanups
*/
#include <linux/config.h>
@@ -402,10+403,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, if (put_user(len, optlen))
return -EFAULT;
- if (copy_to_user(optval, &val, len))
- return -EFAULT;
-
- return 0;
+ return copy_to_user(optval, &val, len) ? -EFAULT : 0;
}
static int x25_listen(struct socket *sock, int backlog)
@@ -1067,9+1065,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
amount = 0;
- if (put_user(amount, (unsigned int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (unsigned int *)arg);
}
case TIOCINQ: {
@@ -1078,18+1074,14 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
amount = skb->len;
- if (put_user(amount, (unsigned int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (unsigned int *)arg);
}
case SIOCGSTAMP:
if (sk != NULL) {
if (sk->stamp.tv_sec == 0)
return -ENOENT;
- if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
}
return -EINVAL;
@@ -1114,15+1106,13 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return x25_subscr_ioctl(cmd, (void *)arg);
case SIOCX25SSUBSCRIP:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
return x25_subscr_ioctl(cmd, (void *)arg);
case SIOCX25GFACILITIES: {
struct x25_facilities facilities;
facilities = sk->protinfo.x25->facilities;
- if (copy_to_user((void *)arg, &facilities, sizeof(facilities)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &facilities, sizeof(facilities)) ? -EFAULT : 0;
}
case SIOCX25SFACILITIES: {
@@ -1148,9+1138,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25GCALLUSERDATA: {
struct x25_calluserdata calluserdata;
calluserdata = sk->protinfo.x25->calluserdata;
- if (copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)) ? -EFAULT : 0;
}
case SIOCX25SCALLUSERDATA: {
@@ -1166,9+1154,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25GCAUSEDIAG: {
struct x25_causediag causediag;
causediag = sk->protinfo.x25->causediag;
- if (copy_to_user((void *)arg, &causediag, sizeof(causediag)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &causediag, sizeof(causediag)) ? -EFAULT : 0;
}
default: