N: Cort Dougan
E: cort@cs.nmt.edu
W: http://www.cs.nmt.edu/~cort/
-D: PowerPC PReP port
+D: PowerPC
S: Computer Science Department
S: New Mexico Tech
S: Socorro, New Mexico 87801
LINUX FOR POWERPC (PREP)
P: Cort Dougan
M: cort@cs.nmt.edu
-W: http://www.cs.nmt.edu/~linuxppc/
+W: http://linuxppc.cs.nmt.edu/
S: Maintained
LINUX FOR POWER MACINTOSH
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
+ .long SYMBOL_NAME(sys_mrecow) /* 190 */
/*
* NOTE!! This doesn' thave to be exact - we just have
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
- .rept NR_syscalls-189
+ .rept NR_syscalls-190
.long SYMBOL_NAME(sys_ni_syscall)
.endr
-/* $Id: entry.S,v 1.152 1998/07/29 16:32:24 jj Exp $
+/* $Id: entry.S,v 1.153 1998/11/11 15:12:33 jj Exp $
* arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
patch_handler_irq:
call C_LABEL(handler_irq)
add %sp, REGWIN_SZ, %o1 ! pt_regs ptr
- wr %l0, PSR_ET, %psr
+ or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq
+ wr %g2, PSR_ET, %psr ! keep ET up
WRITE_PAUSE
RESTORE_ALL
-/* $Id: sparc_ksyms.c,v 1.72 1998/10/22 15:15:08 ecd Exp $
+/* $Id: sparc_ksyms.c,v 1.73 1998/11/06 13:49:54 jj Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
#endif
#include <asm/a.out.h>
#include <asm/spinlock.h>
+#include <asm/io-unit.h>
struct poll {
int fd;
EXPORT_SYMBOL(sparc_alloc_io);
EXPORT_SYMBOL(sparc_free_io);
EXPORT_SYMBOL(io_remap_page_range);
+EXPORT_SYMBOL(iounit_map_dma_init);
+EXPORT_SYMBOL(iounit_map_dma_page);
/* Btfixup stuff cannot have versions, it would be complicated too much */
#ifndef __SMP__
printk("Entering SMP Mode...\n");
- smp_penguin_ctable.which_io = 0;
- smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
- smp_penguin_ctable.reg_size = 0;
-
for (i = 0; i < NR_CPUS; i++)
cpu_offset[i] = (char *)&cpu_data[i] - (char *)&cpu_data;
for (no = 0; no < linux_num_cpus; no++)
if (linux_cpus[no].mid == i)
break;
-
+
+ /*
+ * Initialize the contexts table
+ * Since the call to prom_startcpu() trashes the structure,
+ * we need to re-initialize it for each cpu
+ */
+ smp_penguin_ctable.which_io = 0;
+ smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
+ smp_penguin_ctable.reg_size = 0;
+
/* whirrr, whirrr, whirrrrrrrrr... */
SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, linux_cpus[no].prom_node));
local_flush_cache_all();
SMP_PRINTK(("prom_startcpu returned :)\n"));
/* wheee... it's going... */
- for(timeout = 0; timeout < 5000000; timeout++) {
+ for(timeout = 0; timeout < 10000; timeout++) {
if(cpu_callin_map[i])
break;
- udelay(100);
+ udelay(200);
}
if(cpu_callin_map[i]) {
printk("Entering SMP Mode...\n");
- smp_penguin_ctable.which_io = 0;
- smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
- smp_penguin_ctable.reg_size = 0;
-
for (i = 0; i < NR_CPUS; i++)
cpu_offset[i] = (char *)&cpu_data[i] - (char *)&cpu_data;
/* See trampoline.S for details... */
entry += ((i-1) * 3);
+ /*
+ * Initialize the contexts table
+ * Since the call to prom_startcpu() trashes the structure,
+ * we need to re-initialize it for each cpu
+ */
+ smp_penguin_ctable.which_io = 0;
+ smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
+ smp_penguin_ctable.reg_size = 0;
+
/* whirrr, whirrr, whirrrrrrrrr... */
printk("Starting CPU %d at %p\n", i, entry);
mid_xlate[i] = (linux_cpus[i].mid & ~8);
&smp_penguin_ctable, 0, (char *)entry);
/* wheee... it's going... */
- for(timeout = 0; timeout < 5000000; timeout++) {
+ for(timeout = 0; timeout < 10000; timeout++) {
if(cpu_callin_map[i])
break;
- udelay(100);
+ udelay(200);
}
if(cpu_callin_map[i]) {
/* Another "Red Snapper". */
-/* $Id: fault.c,v 1.95 1998/09/18 19:50:32 davem Exp $
+/* $Id: fault.c,v 1.96 1998/11/08 11:13:56 davem Exp $
* fault.c: Page fault handlers for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
- handle_mm_fault(current, vma, address, write);
+ if (!handle_mm_fault(current, vma, address, write))
+ goto do_sigbus;
up(&mm->mmap_sem);
return;
/*
bad_area:
up(&mm->mmap_sem);
/* Is this in ex_table? */
-
+do_kernel_fault:
g2 = regs->u_regs[UREG_G2];
if (!from_user && (fixup = search_exception_table (regs->pc, &g2))) {
if (fixup > 10) { /* Values below are reserved for other things */
return;
}
unhandled_fault (address, tsk, regs);
+ return;
+
+do_sigbus:
+ up(&mm->mmap_sem);
+ tsk->tss.sig_address = address;
+ tsk->tss.sig_desc = SUBSIG_MISCERROR;
+ force_sig(SIGBUS, tsk);
+ if (! from_user)
+ goto do_kernel_fault;
}
asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
else
if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
- handle_mm_fault(current, vma, address, write);
+ if (!handle_mm_fault(current, vma, address, write))
+ goto do_sigbus;
up(&mm->mmap_sem);
return;
bad_area:
tsk->tss.sig_desc = SUBSIG_NOMAPPING;
send_sig(SIGSEGV, tsk, 1);
return;
+
+do_sigbus:
+ up(&mm->mmap_sem);
+ tsk->tss.sig_address = address;
+ tsk->tss.sig_desc = SUBSIG_MISCERROR;
+ force_sig(SIGBUS, tsk);
}
void window_overflow_fault(void)
-/* $Id: generic.c,v 1.5 1996/12/18 06:43:23 tridge Exp $
+/* $Id: generic.c,v 1.6 1998/10/27 23:28:00 davem Exp $
* generic.c: Generic Sparc mm routines that are not dependent upon
* MMU type but are Sparc specific.
*
unsigned long addr = pte_page(page);
if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr)))
return;
- free_page(addr);
- if (current->mm->rss <= 0)
- return;
- current->mm->rss--;
+ /*
+ * free_page() used to be able to clear swap cache
+ * entries. We may now have to do it manually.
+ */
+ free_page_and_swap_cache(addr);
return;
}
swap_free(pte_val(page));
-/* $Id: io-unit.c,v 1.11 1998/04/13 07:26:37 davem Exp $
+/* $Id: io-unit.c,v 1.13 1998/11/08 11:13:57 davem Exp $
* io-unit.c: IO-UNIT specific routines for memory management.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM);
#endif
}
+
+__u32 iounit_map_dma_init(struct linux_sbus *sbus, int size)
+{
+ int i, j, k, npages;
+ unsigned long rotor, scan, limit;
+ unsigned long flags;
+ __u32 ret;
+ struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+
+ npages = (size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
+ i = 0x0213;
+ spin_lock_irqsave(&iounit->lock, flags);
+next: j = (i & 15);
+ rotor = iounit->rotor[j - 1];
+ limit = iounit->limit[j];
+ scan = rotor;
+nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
+ if (scan + npages > limit) {
+ if (limit != rotor) {
+ limit = rotor;
+ scan = iounit->limit[j - 1];
+ goto nexti;
+ }
+ i >>= 4;
+ if (!(i & 15))
+ panic("iounit_map_dma_init: Couldn't find free iopte slots for %d bytes\n", size);
+ goto next;
+ }
+ for (k = 1, scan++; k < npages; k++)
+ if (test_bit(scan++, iounit->bmap))
+ goto nexti;
+ iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
+ scan -= npages;
+ ret = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT);
+ for (k = 0; k < npages; k++, scan++)
+ set_bit(scan, iounit->bmap);
+ spin_unlock_irqrestore(&iounit->lock, flags);
+ return ret;
+}
+
+__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct linux_sbus *sbus)
+{
+ int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
+ struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+
+ iounit->page_table[scan] = MKIOPTE(mmu_v2p(((unsigned long)addr) & PAGE_MASK));
+ return vaddr + (((unsigned long)addr) & ~PAGE_MASK);
+}
tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
if [ "$CONFIG_PCI" = "y" ]; then
tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
- tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
+# Turned off until updated 3c59x.c driver
+# gets approved by Linus... --DAVEM
+#
+# tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
fi
# bool 'FDDI driver support' CONFIG_FDDI
# if [ "$CONFIG_FDDI" = "y" ]; then
# CONFIG_AIC7XXX_PROC_STATS is not set
CONFIG_AIC7XXX_RESET_DELAY=5
CONFIG_SCSI_NCR53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4
CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
CONFIG_SCSI_NCR53C8XX_SYNC=10
# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-/* $Id: ioctl32.c,v 1.53 1998/10/26 08:01:01 jj Exp $
+/* $Id: ioctl32.c,v 1.54 1998/11/11 17:09:04 jj Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
#include <linux/tty.h>
#include <linux/vt_kern.h>
#include <linux/fb.h>
+#include <linux/ext2_fs.h>
#include <scsi/scsi.h>
/* Ugly hack. */
__ret; \
})
+/* Aiee. Someone does not find a difference between int and long */
+#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int)
+#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int)
+#define EXT2_IOC32_GETVERSION _IOR('v', 1, int)
+#define EXT2_IOC32_SETVERSION _IOW('v', 2, int)
+
extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
return -EFAULT;
return err;
}
+
+static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ /* These are just misnamed, they actually get/put from/to user an int */
+ switch (cmd) {
+ case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
+ case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
+ case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
+ case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
+ }
+ return sys_ioctl(fd, cmd, arg);
+}
struct timeval32 {
int tv_sec;
error = do_kdfontop_ioctl(filp, (struct console_font_op32 *)arg);
goto out;
+ case EXT2_IOC32_GETFLAGS:
+ case EXT2_IOC32_SETFLAGS:
+ case EXT2_IOC32_GETVERSION:
+ case EXT2_IOC32_SETVERSION:
+ error = do_ext2_ioctl(fd, cmd, arg);
+ goto out;
+
/* List here exlicitly which ioctl's are known to have
* compatable types passed or none at all...
*/
case AUTOFS_IOC_CATATONIC:
case AUTOFS_IOC_PROTOVER:
case AUTOFS_IOC_EXPIRE:
-
+
error = sys_ioctl (fd, cmd, arg);
goto out;
-/* $Id: psycho.c,v 1.65 1998/10/20 14:41:28 ecd Exp $
+/* $Id: psycho.c,v 1.66 1998/11/02 22:27:45 davem Exp $
* psycho.c: Ultra/AX U2P PCI controller support.
*
* Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
dprintf("REG_FIXUP[%04x,%04x]: ", pdev->vendor, pdev->device);
for(preg = 0; preg < 6; preg++) {
if(pdev->base_address[preg] != 0)
- prom_printf("%d[%016lx] ", preg, pdev->base_address[preg]);
+ dprintf("%d[%016lx] ", preg, pdev->base_address[preg]);
}
- prom_printf("\n");
+ dprintf("\n");
#endif
}
out_of_range(struct linux_pbm_info *pbm, unsigned char bus, unsigned char devfn)
{
return ((pbm->parent == 0) ||
- ((pbm == &pbm->parent->pbm_B) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 4) ||
- ((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 6) ||
+ ((pbm == &pbm->parent->pbm_B) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8) ||
+ ((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8) ||
(pci_probe_enable == 0));
}
-/* $Id: rtrap.S,v 1.44 1998/10/21 22:27:22 davem Exp $
+/* $Id: rtrap.S,v 1.45 1998/11/09 15:33:29 davem Exp $
* rtrap.S: Preparing for return from trap on Sparc V9.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
wrpr %l7, PSTATE_IE, %pstate
call update_perfctrs
nop
- ba,a,pt %xcc, check_user_wins
+ wrpr %l7, 0x0, %pstate
+ lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
+ brz,pt %o2, 1f
+ sethi %hi(TSTATE_PEF), %l6
+ wrpr %l7, PSTATE_IE, %pstate
+ call fault_in_user_windows
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
1:
andcc %l1, %l6, %g0
-/* $Id: sparc64_ksyms.c,v 1.48 1998/10/20 03:09:08 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.49 1998/10/28 08:11:28 jj Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
EXPORT_SYMBOL(prom_cpu_nodes);
EXPORT_SYMBOL(sys_ioctl);
EXPORT_SYMBOL(sys32_ioctl);
+EXPORT_SYMBOL(get_unmapped_area);
+EXPORT_SYMBOL(move_addr_to_kernel);
+EXPORT_SYMBOL(move_addr_to_user);
#endif
/* Special internal versions of library functions. */
-/* $Id: sys32.S,v 1.7 1998/09/11 10:39:46 jj Exp $
+/* $Id: sys32.S,v 1.8 1998/10/28 08:10:37 jj Exp $
* sys32.S: I-cache tricks for 32-bit compatability layer simple
* conversions.
*
.align 32
.globl sys32_mmap
sys32_mmap:
- srl %o0, 0, %o0 ! IEU0 Group
- sethi %hi(0xffffffff), %g2 ! IEU1
- srl %o1, 0, %o1 ! IEU0 Group
- or %g2, %lo(0xffffffff), %g2 ! IEU1
- srl %o2, 0, %o2 ! IEU0 Group
- sethi %hi(sys_mmap), %g1 ! IEU1
- and %o3, %g2, %o3 ! IEU0 Group
- and %o4, %g2, %o4 ! IEU1
- jmpl %g1 + %lo(sys_mmap), %g0 ! CTI Group brk forced
- and %o5, %g2, %o5 ! IEU0
+ srl %o4, 0, %o4
+ sethi %hi(sys_mmap), %g1
+ jmpl %g1 + %lo(sys_mmap), %g0
+ srl %o5, 0, %o5
.align 32
.globl sys32_lseek
sethi %hi(0xffff), %g2
sethi %hi(sys_chmod), %g1
orcc %g2, %lo(0xffff), %g2
- srl %o0, 0, %o0
jmpl %g1 + %lo(sys_chmod), %g0
and %o1, %g2, %o1
sys32_chown:
sethi %hi(0xffff), %g2
sethi %hi(sys_chown), %g1
orcc %g2, %lo(0xffff), %g2
- srl %o0, 0, %o0
and %o1, %g2, %o1
jmpl %g1 + %lo(sys_chown), %g0
and %o2, %g2, %o2
sethi %hi(0xffff), %g2
sethi %hi(sys_lchown), %g1
orcc %g2, %lo(0xffff), %g2
- srl %o0, 0, %o0
and %o1, %g2, %o1
jmpl %g1 + %lo(sys_lchown), %g0
and %o2, %g2, %o2
sethi %hi(0xffff), %g2
sethi %hi(sys_mknod), %g1
orcc %g2, %lo(0xffff), %g2
- srl %o0, 0, %o0
jmpl %g1 + %lo(sys_mknod), %g0
and %o2, %g2, %o2
.align 32
.globl sys32_sendto, sys32_recvfrom, sys32_getsockopt
sys32_sendto:
- srl %o1, 0, %o1
sethi %hi(sys_sendto), %g1
- srl %o2, 0, %o2
jmpl %g1 + %lo(sys_sendto), %g0
srl %o4, 0, %o4
sys32_recvfrom:
- srl %o1, 0, %o1
- sethi %hi(sys_recvfrom), %g1
- srl %o2, 0, %o2
srl %o4, 0, %o4
+ sethi %hi(sys_recvfrom), %g1
jmpl %g1 + %lo(sys_recvfrom), %g0
srl %o5, 0, %o5
sys32_getsockopt:
- srl %o3, 0, %o3
sethi %hi(sys_getsockopt), %g1
jmpl %g1 + %lo(sys_getsockopt), %g0
srl %o4, 0, %o4
-/* $Id: sys_sparc32.c,v 1.98 1998/10/26 20:01:11 davem Exp $
+/* $Id: sys_sparc32.c,v 1.100 1998/11/08 11:14:00 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
{
fd_set_buffer *fds;
struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
- unsigned long timeout, nn;
+ unsigned long nn;
+ long timeout;
int ret;
- timeout = ~0UL;
+ timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
time_t sec, usec;
timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
timeout += sec * HZ;
- if (timeout)
- timeout += jiffies + 1;
}
ret = -ENOMEM;
zero_fd_set(n, fds->res_out);
zero_fd_set(n, fds->res_ex);
- ret = do_select(n, fds, timeout);
+ ret = do_select(n, fds, &timeout);
if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
- unsigned long timeout = current->timeout - jiffies - 1;
time_t sec = 0, usec = 0;
- if ((long) timeout > 0) {
+ if (timeout) {
sec = timeout / HZ;
usec = timeout % HZ;
usec *= (1000000/HZ);
put_user(sec, &tvp->tv_sec);
put_user(usec, &tvp->tv_usec);
}
- current->timeout = 0;
if (ret < 0)
goto out;
typedef __kernel_ssize_t32 ssize_t32;
asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
- __kernel_size_t32 count, u32 pos)
+ __kernel_size_t32 count, u32 poshi, u32 poslo)
{
- return sys_pread(fd, ubuf, count, pos);
+ return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
}
asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
- __kernel_size_t32 count, u32 pos)
+ __kernel_size_t32 count, u32 poshi, u32 poslo)
{
- return sys_pwrite(fd, ubuf, count, pos);
+ return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
}
-/* $Id: fault.c,v 1.25 1998/10/19 21:52:26 davem Exp $
+/* $Id: fault.c,v 1.26 1998/11/08 11:14:03 davem Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
goto bad_area;
}
current->mm->segments = (void *) (address & PAGE_SIZE);
- handle_mm_fault(current, vma, address, write);
+ if (!handle_mm_fault(current, vma, address, write))
+ goto do_sigbus;
up(&mm->mmap_sem);
return;
/*
bad_area:
up(&mm->mmap_sem);
+do_kernel_fault:
{
unsigned long g2 = regs->u_regs[UREG_G2];
}
unhandled_fault (address, current, regs);
}
+ return;
+
+do_sigbus:
+ up(&mm->mmap_sem);
+ current->tss.sig_address = address;
+ current->tss.sig_desc = SUBSIG_MISCERROR;
+ force_sig(SIGBUS, current);
+ if (regs->tstate & TSTATE_PRIV)
+ goto do_kernel_fault;
}
-/* $Id: generic.c,v 1.2 1997/07/01 09:11:42 jj Exp $
+/* $Id: generic.c,v 1.3 1998/10/27 23:28:07 davem Exp $
* generic.c: Generic Sparc mm routines that are not dependent upon
* MMU type but are Sparc specific.
*
unsigned long addr = pte_page(page);
if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr)))
return;
- free_page(addr);
- if (current->mm->rss <= 0)
- return;
- current->mm->rss--;
+ /*
+ * free_page() used to be able to clear swap cache
+ * entries. We may now have to do it manually.
+ */
+ free_page_and_swap_cache(addr);
return;
}
swap_free(pte_val(page));
-/* $Id: ultra.S,v 1.29 1998/10/22 03:05:51 davem Exp $
+/* $Id: ultra.S,v 1.31 1998/11/07 06:39:21 davem Exp $
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
and %o4, 0x3ff, %o5
cmp %o5, %o0
bne,pt %icc, 2f
- andn %o4, 0x3ff, %o4
-/*IC6*/ cmp %o4, %o1
+/*IC6*/ andn %o4, 0x3ff, %o4
+ cmp %o4, %o1
blu,pt %xcc, 2f
cmp %o4, %o3
blu,pn %xcc, 4f
2: ldxa [%g2] ASI_DTLB_TAG_READ, %o4
and %o4, 0x3ff, %o5
cmp %o5, %o0
- andn %o4, 0x3ff, %o4
-/*IC7*/ bne,pt %icc, 3f
+/*IC7*/ andn %o4, 0x3ff, %o4
+ bne,pt %icc, 3f
cmp %o4, %o1
blu,pt %xcc, 3f
cmp %o4, %o3
blu,pn %xcc, 5f
nop
3: brnz,pt %g2, 1b
- sub %g2, (1 << 3), %g2
-/*IC8*/ retl
+/*IC8*/ sub %g2, (1 << 3), %g2
+ retl
wrpr %g1, 0x0, %pstate
4: stxa %g0, [%g3] ASI_IMMU
stxa %g0, [%g2] ASI_ITLB_DATA_ACCESS
ba,pt %xcc, 2b
flush %g6
5: stxa %g0, [%g3] ASI_DMMU
- stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS
+/*IC9*/ stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS
ba,pt %xcc, 3b
flush %g6
+
+ .align 32
__flush_tlb_mm_slow:
-/*IC9*/ rdpr %pstate, %g1
+/*IC10*/rdpr %pstate, %g1
wrpr %g1, PSTATE_IE, %pstate
stxa %o0, [%o1] ASI_DMMU
stxa %g0, [%g3] ASI_DMMU_DEMAP
flush %g6
stxa %g2, [%o1] ASI_DMMU
flush %g6
-/*IC10*/retl
+/*IC11*/retl
wrpr %g1, 0, %pstate
+
+ .align 32
__flush_tlb_page_slow:
- rdpr %pstate, %g1
+/*IC12*/rdpr %pstate, %g1
wrpr %g1, PSTATE_IE, %pstate
stxa %o0, [%o2] ASI_DMMU
stxa %g0, [%g3] ASI_DMMU_DEMAP
stxa %g0, [%g3] ASI_IMMU_DEMAP
flush %g6
-/*IC11*/stxa %g2, [%o2] ASI_DMMU
+ stxa %g2, [%o2] ASI_DMMU
flush %g6
- retl
+/*IC13*/retl
wrpr %g1, 0, %pstate
+
+ .align 32
__flush_tlb_range_pbp_slow:
- rdpr %pstate, %g1
+/*IC13*/rdpr %pstate, %g1
wrpr %g1, PSTATE_IE, %pstate
stxa %o0, [%o2] ASI_DMMU
2: stxa %g0, [%g5 + %o5] ASI_DMMU_DEMAP
brnz,pt %o5, 2b
sub %o5, %o4, %o5
flush %g6
-/*IC13*/stxa %g2, [%o2] ASI_DMMU
+/*IC14*/stxa %g2, [%o2] ASI_DMMU
flush %g6
retl
wrpr %g1, 0x0, %pstate
.align 32
.globl flush_icache_page
flush_icache_page: /* %o0 = phys_page */
- sethi %hi(1 << 13), %o2 ! I-cache valid/set bit
+ sethi %hi(1 << 13), %o2 ! IC_set bit
+ mov 1, %g1
srlx %o0, 5, %o0 ! phys-addr comparitor
- clr %o1 ! I-cache address
+ clr %o1 ! IC_addr
+ sllx %g1, 36, %g1
+ sub %g1, 1, %g2
+ andn %g2, 0xff, %g2 ! IC_tag mask
+ nop
+
1: ldda [%o1] ASI_IC_TAG, %o4
- andcc %o5, %o2, %g0
- be,pn %xcc, 2f
- andn %o5, %o2, %o5
+ and %o5, %g2, %o5
cmp %o5, %o0
-
be,pn %xcc, iflush1
-2: ldda [%o1 + %o2] ASI_IC_TAG, %o4
-4: andcc %o5, %o2, %g0
- be,pn %xcc, 3f
- andn %o5, %o2, %o5
+ nop
+2: ldda [%o1 + %o2] ASI_IC_TAG, %o4
+ and %o5, %g2, %o5
cmp %o5, %o0
+
be,pn %xcc, iflush2
nop
-
3: add %o1, 0x20, %o1
cmp %o1, %o2
bne,pt %xcc, 1b
retl
nop
iflush1:stxa %g0, [%o1] ASI_IC_TAG
- membar #Sync
- ba,a,pt %xcc, 4b
+ ba,pt %xcc, 2b
+ flush %g6
iflush2:stxa %g0, [%o1 + %o2] ASI_IC_TAG
- membar #Sync
- ba,a,pt %xcc, 3b
+ ba,pt %xcc, 3b
+ flush %g6
#ifdef __SMP__
/* These are all called by the slaves of a cross call, at
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := solaris.o
-O_OBJS := entry64.o fs.o misc.o signal.o systbl.o ioctl.o ipc.o socksys.o timod.o
+O_OBJS := entry64.o fs.o misc.o signal.o systbl.o socket.o ioctl.o ipc.o socksys.o timod.o
ifeq ($(CONFIG_SOLARIS_EMUL),m)
M_OBJS := $(O_TARGET)
CPPFLAGS = $(MODFLAGS)
-/* $Id: fs.c,v 1.10 1998/05/09 06:15:45 davem Exp $
+/* $Id: fs.c,v 1.11 1998/10/28 08:12:04 jj Exp $
* fs.c: fs related syscall emulation for Solaris
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
#include <linux/types.h>
s32 st_pad4[8]; /* expansion area */
};
+struct sol_stat64 {
+ u32 st_dev;
+ s32 st_pad1[3]; /* network id */
+ u64 st_ino;
+ u32 st_mode;
+ u32 st_nlink;
+ u32 st_uid;
+ u32 st_gid;
+ u32 st_rdev;
+ s32 st_pad2[2];
+ s64 st_size;
+ timestruct_t st_atime;
+ timestruct_t st_mtime;
+ timestruct_t st_ctime;
+ s64 st_blksize;
+ s32 st_blocks;
+ char st_fstype[16];
+ s32 st_pad4[4]; /* expansion area */
+};
+
#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
return 0;
}
+static inline int putstat64(struct sol_stat64 *ubuf, struct stat *kbuf)
+{
+ if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev) ||
+ __put_user (kbuf->st_ino, &ubuf->st_ino) ||
+ __put_user (kbuf->st_mode, &ubuf->st_mode) ||
+ __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
+ __put_user (kbuf->st_uid, &ubuf->st_uid) ||
+ __put_user (kbuf->st_gid, &ubuf->st_gid) ||
+ __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev) ||
+ __put_user (kbuf->st_size, &ubuf->st_size) ||
+ __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
+ __put_user (0, &ubuf->st_atime.tv_nsec) ||
+ __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
+ __put_user (0, &ubuf->st_mtime.tv_nsec) ||
+ __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
+ __put_user (0, &ubuf->st_ctime.tv_nsec) ||
+ __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
+ __put_user (kbuf->st_blocks, &ubuf->st_blocks) ||
+ __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
+ return -EFAULT;
+ return 0;
+}
+
asmlinkage int solaris_stat(u32 filename, u32 statbuf)
{
int ret;
return solaris_stat(filename, statbuf);
}
+asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ char *filenam;
+ mm_segment_t old_fs = get_fs();
+ int (*sys_newstat)(char *,struct stat *) =
+ (int (*)(char *,struct stat *))SYS(stat);
+
+ filenam = getname32 (filename);
+ ret = PTR_ERR(filenam);
+ if (!IS_ERR(filenam)) {
+ set_fs (KERNEL_DS);
+ ret = sys_newstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
+ return -EFAULT;
+ }
+ return ret;
+}
+
asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
{
int ret;
return solaris_lstat(filename, statbuf);
}
+asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ char *filenam;
+ mm_segment_t old_fs = get_fs();
+ int (*sys_newlstat)(char *,struct stat *) =
+ (int (*)(char *,struct stat *))SYS(lstat);
+
+ filenam = getname32 (filename);
+ ret = PTR_ERR(filenam);
+ if (!IS_ERR(filenam)) {
+ set_fs (KERNEL_DS);
+ ret = sys_newlstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
+ return -EFAULT;
+ }
+ return ret;
+}
+
asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
{
int ret;
return solaris_fstat(fd, statbuf);
}
+asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ mm_segment_t old_fs = get_fs();
+ int (*sys_newfstat)(unsigned,struct stat *) =
+ (int (*)(unsigned,struct stat *))SYS(fstat);
+
+ set_fs (KERNEL_DS);
+ ret = sys_newfstat(fd, &s);
+ set_fs (old_fs);
+ if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
+ return -EFAULT;
+ return ret;
+}
+
asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev)
{
int (*sys_mknod)(const char *,int,dev_t) =
return solaris_mknod(path, mode, dev);
}
+asmlinkage int solaris_getdents64(unsigned int fd, void *dirent, unsigned int count)
+{
+ int (*sys_getdents)(unsigned int, void *, unsigned int) =
+ (int (*)(unsigned int, void *, unsigned int))SYS(getdents);
+
+ return sys_getdents(fd, dirent, count);
+}
+
/* This statfs thingie probably will go in the near future, but... */
struct sol_statfs {
u32 f_filler[16];
};
+struct sol_statvfs64 {
+ u32 f_bsize;
+ u32 f_frsize;
+ u64 f_blocks;
+ u64 f_bfree;
+ u64 f_bavail;
+ u64 f_files;
+ u64 f_ffree;
+ u64 f_favail;
+ u32 f_fsid;
+ char f_basetype[16];
+ u32 f_flag;
+ u32 f_namemax;
+ char f_fstr[32];
+ u32 f_filler[16];
+};
+
static int report_statvfs(struct inode *inode, u32 buf)
{
struct statfs s;
return error;
}
+static int report_statvfs64(struct inode *inode, u32 buf)
+{
+ struct statfs s;
+ mm_segment_t old_fs = get_fs();
+ int error;
+ struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf);
+
+ set_fs (KERNEL_DS);
+ error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs));
+ set_fs (old_fs);
+ if (!error) {
+ const char *p = inode->i_sb->s_type->name;
+ int i = 0;
+ int j = strlen (p);
+
+ if (j > 15) j = 15;
+ if (IS_RDONLY(inode)) i = 1;
+ if (IS_NOSUID(inode)) i |= 2;
+ if (put_user (s.f_bsize, &ss->f_bsize) ||
+ __put_user (0, &ss->f_frsize) ||
+ __put_user (s.f_blocks, &ss->f_blocks) ||
+ __put_user (s.f_bfree, &ss->f_bfree) ||
+ __put_user (s.f_bavail, &ss->f_bavail) ||
+ __put_user (s.f_files, &ss->f_files) ||
+ __put_user (s.f_ffree, &ss->f_ffree) ||
+ __put_user (s.f_ffree, &ss->f_favail) ||
+ __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
+ __copy_to_user (ss->f_basetype,p,j) ||
+ __put_user (0, (char *)&ss->f_basetype[j]) ||
+ __put_user (s.f_namelen, &ss->f_namemax) ||
+ __put_user (i, &ss->f_flag) ||
+ __clear_user (&ss->f_fstr, 32))
+ return -EFAULT;
+ }
+ return error;
+}
+
asmlinkage int solaris_statvfs(u32 path, u32 buf)
{
struct dentry * dentry;
return error;
}
+asmlinkage int solaris_statvfs64(u32 path, u32 buf)
+{
+ struct dentry * dentry;
+ int error;
+
+ lock_kernel();
+ dentry = namei((const char *)A(path));
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+
+ error = -ENOSYS;
+ if (inode->i_sb->s_op->statfs)
+ error = report_statvfs64(inode, buf);
+ dput(dentry);
+ }
+ unlock_kernel();
+ return error;
+}
+
+asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
+{
+ struct inode * inode;
+ struct dentry * dentry;
+ struct file * file;
+ int error;
+
+ lock_kernel();
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ if (!(dentry = file->f_dentry))
+ error = -ENOENT;
+ else if (!(inode = dentry->d_inode))
+ error = -ENOENT;
+ else if (!inode->i_sb)
+ error = -ENODEV;
+ else if (!inode->i_sb->s_op->statfs)
+ error = -ENOSYS;
+ else
+ error = report_statvfs64(inode, buf);
+ fput(file);
+out:
+ unlock_kernel();
+ return error;
+}
+
asmlinkage int solaris_open(u32 filename, int flags, u32 mode)
{
int (*sys_open)(const char *,int,int) =
(int (*)(const char *,int,int))SYS(open);
int fl = flags & 0xf;
-
+
+/* if (flags & 0x2000) - allow LFS */
if (flags & 0x8050) fl |= O_SYNC;
if (flags & 0x80) fl |= O_NONBLOCK;
if (flags & 0x100) fl |= O_CREAT;
return -ENOSYS;
}
-asmlinkage int solaris_pread(int fd, u32 buf, u32 nbyte, s32 offset)
+asmlinkage int solaris_pread(unsigned int fd, char *buf, u32 count, u32 pos)
{
- off_t temp;
- int retval;
- struct file * file;
- long (*sys_read)(unsigned int, char *, unsigned long) =
- (long (*)(unsigned int, char *, unsigned long))SYS(read);
- long (*sys_lseek)(unsigned int, off_t, unsigned int) =
- (long (*)(unsigned int, off_t, unsigned int))SYS(lseek);
-
- lock_kernel();
- retval = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad;
-
- temp = file->f_pos;
- if (temp != offset) {
- retval = sys_lseek(fd, offset, 0);
- if (retval < 0)
- goto out_putf;
- }
- retval = sys_read(fd, (char *)A(buf), nbyte);
- if (file->f_pos != temp) {
- if (!retval)
- retval = sys_lseek(fd, temp, 0);
- else
- sys_lseek(fd, temp, 0);
- }
-
-out_putf:
- fput(file);
-bad:
- unlock_kernel();
- return retval;
+ ssize_t (*sys_pread)(unsigned int, char *, size_t, loff_t) =
+ (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pread);
+
+ return sys_pread(fd, buf, count, (loff_t)pos);
}
-asmlinkage int solaris_pwrite(int fd, u32 buf, u32 nbyte, s32 offset)
+asmlinkage int solaris_pwrite(unsigned int fd, char *buf, u32 count, u32 pos)
{
- off_t temp;
- int retval;
- struct file * file;
- long (*sys_write)(unsigned int, char *, unsigned long) =
- (long (*)(unsigned int, char *, unsigned long))SYS(read);
- long (*sys_lseek)(unsigned int, off_t, unsigned int) =
- (long (*)(unsigned int, off_t, unsigned int))SYS(lseek);
-
- lock_kernel();
- retval = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad;
-
- temp = file->f_pos;
- if (temp != offset) {
- retval = sys_lseek(fd, offset, 0);
- if (retval < 0)
- goto out_putf;
- }
- retval = sys_write(fd, (char *)A(buf), nbyte);
- if (file->f_pos != temp) {
- if (!retval)
- retval = sys_lseek(fd, temp, 0);
- else
- sys_lseek(fd, temp, 0);
- }
-
-out_putf:
- fput(file);
-bad:
- unlock_kernel();
- return retval;
+ ssize_t (*sys_pwrite)(unsigned int, char *, size_t, loff_t) =
+ (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pwrite);
+
+ return sys_pwrite(fd, buf, count, (loff_t)pos);
}
/* POSIX.1 names */
-/* $Id: misc.c,v 1.12 1998/06/16 04:37:08 davem Exp $
+/* $Id: misc.c,v 1.13 1998/10/28 08:11:58 jj Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
#include <linux/module.h>
#include <linux/limits.h>
#include <linux/mm.h>
#include <linux/smp.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/timex.h>
#include <asm/uaccess.h>
#include <asm/string.h>
/* 120 */ 22, 22, 88, 86, 85, 22, 22,
};
+#define SOLARIS_NR_OPEN 256
+
+static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off)
+{
+ struct file *file = NULL;
+ unsigned long retval, ret_type;
+
+ lock_kernel();
+ current->personality |= PER_SVR4;
+ if (flags & MAP_NORESERVE) {
+ static int cnt = 0;
+
+ if (cnt < 5) {
+ printk("%s: unimplemented Solaris MAP_NORESERVE mmap() flag\n",
+ current->comm);
+ cnt++;
+ }
+ flags &= ~MAP_NORESERVE;
+ }
+ retval = -EBADF;
+ if(!(flags & MAP_ANONYMOUS)) {
+ if(fd >= SOLARIS_NR_OPEN)
+ goto out;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ if (file->f_dentry && file->f_dentry->d_inode) {
+ struct inode * inode = file->f_dentry->d_inode;
+ if(MAJOR(inode->i_rdev) == MEM_MAJOR &&
+ MINOR(inode->i_rdev) == 5) {
+ flags |= MAP_ANONYMOUS;
+ fput(file);
+ file = NULL;
+ }
+ }
+ }
+
+ retval = -ENOMEM;
+ if(!(flags & MAP_FIXED) && !addr) {
+ unsigned long attempt = get_unmapped_area(addr, len);
+ if(!attempt || (attempt >= 0xf0000000UL))
+ goto out_putf;
+ addr = (u32) attempt;
+ }
+ if(!(flags & MAP_FIXED))
+ addr = 0;
+ ret_type = flags & _MAP_NEW;
+ flags &= ~_MAP_NEW;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ retval = do_mmap(file,
+ (unsigned long) addr, (unsigned long) len,
+ (unsigned long) prot, (unsigned long) flags, off);
+ if(!ret_type)
+ retval = ((retval < 0xf0000000) ? 0 : retval);
+out_putf:
+ if (file)
+ fput(file);
+out:
+ unlock_kernel();
+ return (u32) retval;
+}
+
asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
{
- u32 (*sunos_mmap)(u32,u32,u32,u32,u32,u32) =
- (u32 (*)(u32,u32,u32,u32,u32,u32))SUNOS(71);
- u32 ret;
+ return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off);
+}
+
+asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi)
+{
+ u32 offlo;
- ret = sunos_mmap(addr,len,prot,flags,fd,off);
- /* sunos_mmap sets personality to PER_BSD */
- current->personality = PER_SVR4;
- return ret;
+ if (regs->u_regs[UREG_G1]) {
+ if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
+ return -EFAULT;
+ } else {
+ if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x60)))
+ return -EFAULT;
+ }
+ return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo);
}
asmlinkage int solaris_brk(u32 brk)
}
}
+asmlinkage int solaris_setreuid(s32 ruid, s32 euid)
+{
+ int (*sys_setreuid)(uid_t, uid_t) = (int (*)(uid_t, uid_t))SYS(setreuid);
+ return sys_setreuid(ruid, euid);
+}
+
+asmlinkage int solaris_setregid(s32 rgid, s32 egid)
+{
+ int (*sys_setregid)(gid_t, gid_t) = (int (*)(gid_t, gid_t))SYS(setregid);
+ return sys_setregid(rgid, egid);
+}
+
asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
{
int ret;
return sys_gettimeofday((struct timeval *)(u64)tim, NULL);
}
+#define RLIM_SOL_INFINITY32 0x7fffffff
+#define RLIM_SOL_SAVED_MAX32 0x7ffffffe
+#define RLIM_SOL_SAVED_CUR32 0x7ffffffd
+#define RLIM_SOL_INFINITY ((u64)-3)
+#define RLIM_SOL_SAVED_MAX ((u64)-2)
+#define RLIM_SOL_SAVED_CUR ((u64)-1)
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+#define RLIMIT_SOL_NOFILE 5
+#define RLIMIT_SOL_VMEM 6
+
+struct rlimit32 {
+ s32 rlim_cur;
+ s32 rlim_max;
+};
+
+asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+ struct rlimit r;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &r);
+ set_fs (old_fs);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_INFINITY)
+ r.rlim_cur = RLIM_SOL_INFINITY32;
+ else if ((u64)r.rlim_cur > RLIM_SOL_INFINITY32)
+ r.rlim_cur = RLIM_SOL_SAVED_CUR32;
+ if (r.rlim_max == RLIM_INFINITY)
+ r.rlim_max = RLIM_SOL_INFINITY32;
+ else if ((u64)r.rlim_max > RLIM_SOL_INFINITY32)
+ r.rlim_max = RLIM_SOL_SAVED_MAX32;
+ ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+ ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+ }
+ return ret;
+}
+
+asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+ struct rlimit r, rold;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+ int (*sys_setrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+ __get_user (r.rlim_max, &rlim->rlim_max))
+ return -EFAULT;
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &rold);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_SOL_INFINITY32)
+ r.rlim_cur = RLIM_INFINITY;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_CUR32)
+ r.rlim_cur = rold.rlim_cur;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_MAX32)
+ r.rlim_cur = rold.rlim_max;
+ if (r.rlim_max == RLIM_SOL_INFINITY32)
+ r.rlim_max = RLIM_INFINITY;
+ else if (r.rlim_max == RLIM_SOL_SAVED_CUR32)
+ r.rlim_max = rold.rlim_cur;
+ else if (r.rlim_max == RLIM_SOL_SAVED_MAX32)
+ r.rlim_max = rold.rlim_max;
+ ret = sys_setrlimit(resource, &r);
+ }
+ set_fs (old_fs);
+ return ret;
+}
+
+asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit *rlim)
+{
+ struct rlimit r;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &r);
+ set_fs (old_fs);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_INFINITY)
+ r.rlim_cur = RLIM_SOL_INFINITY;
+ if (r.rlim_max == RLIM_INFINITY)
+ r.rlim_max = RLIM_SOL_INFINITY;
+ ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+ ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+ }
+ return ret;
+}
+
+asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit *rlim)
+{
+ struct rlimit r, rold;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+ int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+ int (*sys_setrlimit)(unsigned int, struct rlimit *) =
+ (int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
+
+ if (resource > RLIMIT_SOL_VMEM)
+ return -EINVAL;
+ switch (resource) {
+ case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+ case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+ default: break;
+ }
+ if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+ __get_user (r.rlim_max, &rlim->rlim_max))
+ return -EFAULT;
+ set_fs (KERNEL_DS);
+ ret = sys_getrlimit(resource, &rold);
+ if (!ret) {
+ if (r.rlim_cur == RLIM_SOL_INFINITY)
+ r.rlim_cur = RLIM_INFINITY;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_CUR)
+ r.rlim_cur = rold.rlim_cur;
+ else if (r.rlim_cur == RLIM_SOL_SAVED_MAX)
+ r.rlim_cur = rold.rlim_max;
+ if (r.rlim_max == RLIM_SOL_INFINITY)
+ r.rlim_max = RLIM_INFINITY;
+ else if (r.rlim_max == RLIM_SOL_SAVED_CUR)
+ r.rlim_max = rold.rlim_cur;
+ else if (r.rlim_max == RLIM_SOL_SAVED_MAX)
+ r.rlim_max = rold.rlim_max;
+ ret = sys_setrlimit(resource, &r);
+ }
+ set_fs (old_fs);
+ return ret;
+}
+
+struct timeval32 {
+ int tv_sec, tv_usec;
+};
+
+struct sol_ntptimeval {
+ struct timeval32 time;
+ s32 maxerror;
+ s32 esterror;
+};
+
+struct sol_timex {
+ u32 modes;
+ s32 offset;
+ s32 freq;
+ s32 maxerror;
+ s32 esterror;
+ s32 status;
+ s32 constant;
+ s32 precision;
+ s32 tolerance;
+ s32 ppsfreq;
+ s32 jitter;
+ s32 shift;
+ s32 stabil;
+ s32 jitcnt;
+ s32 calcnt;
+ s32 errcnt;
+ s32 stbcnt;
+};
+
+asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval *ntp)
+{
+ int (*sys_adjtimex)(struct timex *) =
+ (int (*)(struct timex *))SYS(adjtimex);
+ struct timex t;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ t.modes = 0;
+ ret = sys_adjtimex(&t);
+ set_fs(old_fs);
+ if (ret < 0)
+ return ret;
+ ret = put_user (t.time.tv_sec, &ntp->time.tv_sec);
+ ret |= __put_user (t.time.tv_usec, &ntp->time.tv_usec);
+ ret |= __put_user (t.maxerror, &ntp->maxerror);
+ ret |= __put_user (t.esterror, &ntp->esterror);
+ return ret;
+}
+
+asmlinkage int solaris_ntp_adjtime(struct sol_timex *txp)
+{
+ int (*sys_adjtimex)(struct timex *) =
+ (int (*)(struct timex *))SYS(adjtimex);
+ struct timex t;
+ int ret, err;
+ mm_segment_t old_fs = get_fs();
+
+ ret = get_user (t.modes, &txp->modes);
+ ret |= __get_user (t.offset, &txp->offset);
+ ret |= __get_user (t.freq, &txp->freq);
+ ret |= __get_user (t.maxerror, &txp->maxerror);
+ ret |= __get_user (t.esterror, &txp->esterror);
+ ret |= __get_user (t.status, &txp->status);
+ ret |= __get_user (t.constant, &txp->constant);
+ set_fs(KERNEL_DS);
+ ret = sys_adjtimex(&t);
+ set_fs(old_fs);
+ if (ret < 0)
+ return ret;
+ err = put_user (t.offset, &txp->offset);
+ err |= __put_user (t.freq, &txp->freq);
+ err |= __put_user (t.maxerror, &txp->maxerror);
+ err |= __put_user (t.esterror, &txp->esterror);
+ err |= __put_user (t.status, &txp->status);
+ err |= __put_user (t.constant, &txp->constant);
+ err |= __put_user (t.precision, &txp->precision);
+ err |= __put_user (t.tolerance, &txp->tolerance);
+ err |= __put_user (t.ppsfreq, &txp->ppsfreq);
+ err |= __put_user (t.jitter, &txp->jitter);
+ err |= __put_user (t.shift, &txp->shift);
+ err |= __put_user (t.stabil, &txp->stabil);
+ err |= __put_user (t.jitcnt, &txp->jitcnt);
+ err |= __put_user (t.calcnt, &txp->calcnt);
+ err |= __put_user (t.errcnt, &txp->errcnt);
+ err |= __put_user (t.stbcnt, &txp->stbcnt);
+ if (err)
+ return -EFAULT;
+ return ret;
+}
+
asmlinkage int do_sol_unimplemented(struct pt_regs *regs)
{
printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n",
--- /dev/null
+/* $Id: socket.c,v 1.1 1998/10/28 08:12:11 jj Exp $
+ * socket.c: Socket syscall emulation for Solaris 2.6+
+ *
+ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <linux/types.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/socket.h>
+#include <linux/file.h>
+
+#include <asm/uaccess.h>
+#include <asm/string.h>
+#include <asm/oplib.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+
+#include "conv.h"
+
+#define SOCK_SOL_STREAM 2
+#define SOCK_SOL_DGRAM 1
+#define SOCK_SOL_RAW 4
+#define SOCK_SOL_RDM 5
+#define SOCK_SOL_SEQPACKET 6
+
+static int socket_check(int family, int type)
+{
+ if (family != PF_UNIX && family != PF_INET)
+ return -ESOCKTNOSUPPORT;
+ switch (type) {
+ case SOCK_SOL_STREAM: type = SOCK_STREAM; break;
+ case SOCK_SOL_DGRAM: type = SOCK_DGRAM; break;
+ case SOCK_SOL_RAW: type = SOCK_RAW; break;
+ case SOCK_SOL_RDM: type = SOCK_RDM; break;
+ case SOCK_SOL_SEQPACKET: type = SOCK_SEQPACKET; break;
+ default: return -EINVAL;
+ }
+ return type;
+}
+
+asmlinkage int solaris_socket(int family, int type, int protocol)
+{
+ int (*sys_socket)(int, int, int) =
+ (int (*)(int, int, int))SYS(socket);
+
+ type = socket_check (family, type);
+ if (type < 0) return type;
+ return sys_socket(family, type, protocol);
+}
+
+asmlinkage int solaris_socketpair(int family, int type, int protocol, int *usockvec)
+{
+ int (*sys_socketpair)(int, int, int, int *) =
+ (int (*)(int, int, int, int *))SYS(socketpair);
+
+ type = socket_check (family, type);
+ if (type < 0) return type;
+ return sys_socketpair(family, type, protocol, usockvec);
+}
+
+asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen)
+{
+ int (*sys_bind)(int, struct sockaddr *, int) =
+ (int (*)(int, struct sockaddr *, int))SUNOS(104);
+
+ return sys_bind(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int optlen)
+{
+ int (*sunos_setsockopt)(int, int, int, u32, int) =
+ (int (*)(int, int, int, u32, int))SUNOS(105);
+
+ return sunos_setsockopt(fd, level, optname, optval, optlen);
+}
+
+asmlinkage int solaris_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen)
+{
+ int (*sunos_getsockopt)(int, int, int, u32, u32) =
+ (int (*)(int, int, int, u32, u32))SUNOS(118);
+
+ return sunos_getsockopt(fd, level, optname, optval, optlen);
+}
+
+asmlinkage int solaris_connect(int fd, struct sockaddr *addr, int addrlen)
+{
+ int (*sys_connect)(int, struct sockaddr *, int) =
+ (int (*)(int, struct sockaddr *, int))SYS(connect);
+
+ return sys_connect(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_accept(int fd, struct sockaddr *addr, int *addrlen)
+{
+ int (*sys_accept)(int, struct sockaddr *, int *) =
+ (int (*)(int, struct sockaddr *, int *))SYS(accept);
+
+ return sys_accept(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_listen(int fd, int backlog)
+{
+ int (*sys_listen)(int, int) =
+ (int (*)(int, int))SUNOS(106);
+
+ return sys_listen(fd, backlog);
+}
+
+asmlinkage int solaris_shutdown(int fd, int how)
+{
+ int (*sys_shutdown)(int, int) =
+ (int (*)(int, int))SYS(shutdown);
+
+ return sys_shutdown(fd, how);
+}
+
+#define MSG_SOL_OOB 0x1
+#define MSG_SOL_PEEK 0x2
+#define MSG_SOL_DONTROUTE 0x4
+#define MSG_SOL_EOR 0x8
+#define MSG_SOL_CTRUNC 0x10
+#define MSG_SOL_TRUNC 0x20
+#define MSG_SOL_WAITALL 0x40
+#define MSG_SOL_DONTWAIT 0x80
+
+static int solaris_to_linux_msgflags(int flags)
+{
+ int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+
+ if (flags & MSG_SOL_EOR) fl |= MSG_EOR;
+ if (flags & MSG_SOL_CTRUNC) fl |= MSG_CTRUNC;
+ if (flags & MSG_SOL_TRUNC) fl |= MSG_TRUNC;
+ if (flags & MSG_SOL_WAITALL) fl |= MSG_WAITALL;
+ if (flags & MSG_SOL_DONTWAIT) fl |= MSG_DONTWAIT;
+ return fl;
+}
+
+static int linux_to_solaris_msgflags(int flags)
+{
+ int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+
+ if (flags & MSG_EOR) fl |= MSG_SOL_EOR;
+ if (flags & MSG_CTRUNC) fl |= MSG_SOL_CTRUNC;
+ if (flags & MSG_TRUNC) fl |= MSG_SOL_TRUNC;
+ if (flags & MSG_WAITALL) fl |= MSG_SOL_WAITALL;
+ if (flags & MSG_DONTWAIT) fl |= MSG_SOL_DONTWAIT;
+ return fl;
+}
+
+asmlinkage int solaris_recvfrom(int s, char *buf, int len, int flags, u32 from, u32 fromlen)
+{
+ int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);
+
+ return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), (struct sockaddr *)A(from), (int *)A(fromlen));
+}
+
+asmlinkage int solaris_recv(int s, char *buf, int len, int flags)
+{
+ int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);
+
+ return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+}
+
+asmlinkage int solaris_sendto(int s, char *buf, int len, int flags, u32 to, u32 tolen)
+{
+ int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto);
+
+ return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), (struct sockaddr *)A(to), (int *)A(tolen));
+}
+
+asmlinkage int solaris_send(int s, char *buf, int len, int flags)
+{
+ int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+ (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto);
+
+ return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+}
+
+asmlinkage int solaris_getpeername(int fd, struct sockaddr *addr, int *addrlen)
+{
+ int (*sys_getpeername)(int, struct sockaddr *, int *) =
+ (int (*)(int, struct sockaddr *, int *))SYS(getpeername);
+
+ return sys_getpeername(fd, addr, addrlen);
+}
+
+asmlinkage int solaris_getsockname(int fd, struct sockaddr *addr, int *addrlen)
+{
+ int (*sys_getsockname)(int, struct sockaddr *, int *) =
+ (int (*)(int, struct sockaddr *, int *))SYS(getsockname);
+
+ return sys_getsockname(fd, addr, addrlen);
+}
+
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
+ 16 for IP, 16 for IPX,
+ 24 for IPv6,
+ about 80 for AX.25 */
+
+/* XXX These as well... */
+extern __inline__ struct socket *socki_lookup(struct inode *inode)
+{
+ return &inode->u.socket_i;
+}
+
+extern __inline__ struct socket *sockfd_lookup(int fd, int *err)
+{
+ struct file *file;
+ struct inode *inode;
+
+ if (!(file = fget(fd))) {
+ *err = -EBADF;
+ return NULL;
+ }
+
+ inode = file->f_dentry->d_inode;
+ if (!inode || !inode->i_sock || !socki_lookup(inode)) {
+ *err = -ENOTSOCK;
+ fput(file);
+ return NULL;
+ }
+
+ return socki_lookup(inode);
+}
+
+extern __inline__ void sockfd_put(struct socket *sock)
+{
+ fput(sock->file);
+}
+
+struct sol_nmsghdr {
+ u32 msg_name;
+ int msg_namelen;
+ u32 msg_iov;
+ u32 msg_iovlen;
+ u32 msg_control;
+ u32 msg_controllen;
+ u32 msg_flags;
+};
+
+struct sol_cmsghdr {
+ u32 cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+ unsigned char cmsg_data[0];
+};
+
+struct iovec32 {
+ u32 iov_base;
+ u32 iov_len;
+};
+
+static inline int iov_from_user32_to_kern(struct iovec *kiov,
+ struct iovec32 *uiov32,
+ int niov)
+{
+ int tot_len = 0;
+
+ while(niov > 0) {
+ u32 len, buf;
+
+ if(get_user(len, &uiov32->iov_len) ||
+ get_user(buf, &uiov32->iov_base)) {
+ tot_len = -EFAULT;
+ break;
+ }
+ tot_len += len;
+ kiov->iov_base = (void *)A(buf);
+ kiov->iov_len = (__kernel_size_t) len;
+ uiov32++;
+ kiov++;
+ niov--;
+ }
+ return tot_len;
+}
+
+static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
+ struct sol_nmsghdr *umsg)
+{
+ u32 tmp1, tmp2, tmp3;
+ int err;
+
+ err = get_user(tmp1, &umsg->msg_name);
+ err |= __get_user(tmp2, &umsg->msg_iov);
+ err |= __get_user(tmp3, &umsg->msg_control);
+ if (err)
+ return -EFAULT;
+
+ kmsg->msg_name = (void *)A(tmp1);
+ kmsg->msg_iov = (struct iovec *)A(tmp2);
+ kmsg->msg_control = (void *)A(tmp3);
+
+ err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+ err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+ err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+
+ kmsg->msg_flags = solaris_to_linux_msgflags(kmsg->msg_flags);
+
+ return err;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
+ char *kern_address, int mode)
+{
+ int tot_len;
+
+ if(kern_msg->msg_namelen) {
+ if(mode==VERIFY_READ) {
+ int err = move_addr_to_kernel(kern_msg->msg_name,
+ kern_msg->msg_namelen,
+ kern_address);
+ if(err < 0)
+ return err;
+ }
+ kern_msg->msg_name = kern_address;
+ } else
+ kern_msg->msg_name = NULL;
+
+ if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+ kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+ GFP_KERNEL);
+ if(!kern_iov)
+ return -ENOMEM;
+ }
+
+ tot_len = iov_from_user32_to_kern(kern_iov,
+ (struct iovec32 *)kern_msg->msg_iov,
+ kern_msg->msg_iovlen);
+ if(tot_len >= 0)
+ kern_msg->msg_iov = kern_iov;
+ else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+ kfree(kern_iov);
+
+ return tot_len;
+}
+
+asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned user_flags)
+{
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ struct iovec iov[UIO_FASTIOV];
+ unsigned char ctl[sizeof(struct cmsghdr) + 20];
+ unsigned char *ctl_buf = ctl;
+ struct msghdr kern_msg;
+ int err, total_len;
+
+ if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+ return -EFAULT;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;
+ err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+ if (err < 0)
+ goto out;
+ total_len = err;
+
+ if(kern_msg.msg_controllen) {
+ struct sol_cmsghdr *ucmsg = (struct sol_cmsghdr *)kern_msg.msg_control;
+ unsigned long *kcmsg;
+ __kernel_size_t32 cmlen;
+
+ if(kern_msg.msg_controllen > sizeof(ctl) &&
+ kern_msg.msg_controllen <= 256) {
+ err = -ENOBUFS;
+ ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
+ if(!ctl_buf)
+ goto out_freeiov;
+ }
+ __get_user(cmlen, &ucmsg->cmsg_len);
+ kcmsg = (unsigned long *) ctl_buf;
+ *kcmsg++ = (unsigned long)cmlen;
+ err = -EFAULT;
+ if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
+ kern_msg.msg_controllen - sizeof(__kernel_size_t32)))
+ goto out_freectl;
+ kern_msg.msg_control = ctl_buf;
+ }
+ kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags);
+
+ lock_kernel();
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ if (sock->file->f_flags & O_NONBLOCK)
+ kern_msg.msg_flags |= MSG_DONTWAIT;
+ err = sock_sendmsg(sock, &kern_msg, total_len);
+ sockfd_put(sock);
+ }
+ unlock_kernel();
+
+out_freectl:
+ /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
+ if(ctl_buf != ctl)
+ kfree(ctl_buf);
+out_freeiov:
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+out:
+ return err;
+}
+
+asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr *user_msg, unsigned int user_flags)
+{
+ struct iovec iovstack[UIO_FASTIOV];
+ struct msghdr kern_msg;
+ char addr[MAX_SOCK_ADDR];
+ struct socket *sock;
+ struct iovec *iov = iovstack;
+ struct sockaddr *uaddr;
+ int *uaddr_len;
+ unsigned long cmsg_ptr;
+ int err, total_len, len = 0;
+
+ if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+ return -EFAULT;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;
+
+ uaddr = kern_msg.msg_name;
+ uaddr_len = &user_msg->msg_namelen;
+ err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+ if (err < 0)
+ goto out;
+ total_len = err;
+
+ cmsg_ptr = (unsigned long) kern_msg.msg_control;
+ kern_msg.msg_flags = 0;
+
+ lock_kernel();
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ if (sock->file->f_flags & O_NONBLOCK)
+ user_flags |= MSG_DONTWAIT;
+ err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
+ if(err >= 0)
+ len = err;
+ sockfd_put(sock);
+ }
+ unlock_kernel();
+
+ if(uaddr != NULL && err >= 0)
+ err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
+ if(err >= 0) {
+ err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags);
+ if(!err) {
+ /* XXX Convert cmsg back into userspace 32-bit format... */
+ err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
+ &user_msg->msg_controllen);
+ }
+ }
+
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+out:
+ if(err < 0)
+ return err;
+ return len;
+}
-/* $Id: systbl.S,v 1.6 1998/03/26 08:46:08 jj Exp $
+/* $Id: systbl.S,v 1.7 1998/10/28 08:11:49 jj Exp $
* systbl.S: System call entry point table for Solaris compatibility.
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
*/
.word solaris_fxstat /* fxstat ddx 125 */
.word solaris_xmknod /* xmknod dsox 126 */
.word solaris_unimplemented /* syslocal d 127 */
- .word solaris_unimplemented /* setrlimit 128 */
- .word solaris_unimplemented /* getrlimit 129 */
+ .word solaris_setrlimit /* setrlimit dp 128 */
+ .word solaris_getrlimit /* getrlimit dp 129 */
.word CHAIN(chown) /* lchown sdd 130 */
.word solaris_unimplemented /* memcntl 131 */
.word solaris_getpmsg /* getpmsg dxxxx 132 */
.word CHAIN(nanosleep) /* nanosleep dd 199 */
.word solaris_facl /* facl dddp 200 */
.word solaris_unimplemented /* 201 */
- .word solaris_unimplemented /* 202 */
- .word solaris_unimplemented /* 203 */
+ .word solaris_setreuid /* setreuid dd 202 */
+ .word solaris_setregid /* setregid dd 203 */
.word solaris_unimplemented /* 204 */
.word solaris_unimplemented /* 205 */
.word solaris_unimplemented /* 206 */
.word solaris_unimplemented /* 210 */
.word solaris_unimplemented /* 211 */
.word solaris_unimplemented /* 212 */
- .word solaris_unimplemented /* 213 */
- .word solaris_unimplemented /* 214 */
- .word solaris_unimplemented /* 215 */
- .word solaris_unimplemented /* 216 */
- .word solaris_unimplemented /* 217 */
- .word solaris_unimplemented /* 218 */
- .word solaris_unimplemented /* 219 */
- .word solaris_unimplemented /* 220 */
- .word solaris_unimplemented /* 221 */
- .word solaris_unimplemented /* 222 */
- .word solaris_unimplemented /* 223 */
- .word solaris_unimplemented /* 224 */
- .word solaris_unimplemented /* 225 */
+ .word solaris_getdents64 /* getdents64 dpd 213 */
+ .word REGS(solaris_mmap64) /* mmap64 xxxxdX 214 */
+ .word solaris_stat64 /* stat64 sP 215 */
+ .word solaris_lstat64 /* lstat64 sP 216 */
+ .word solaris_fstat64 /* fstat64 dP 217 */
+ .word solaris_statvfs64 /* statvfs64 sP 218 */
+ .word solaris_fstatvfs64 /* fstatvfs64 dP 219 */
+ .word solaris_setrlimit64 /* setrlimit64 dP 220 */
+ .word solaris_getrlimit64 /* getrlimit64 dP 221 */
+ .word CHAIN(pread) /* pread64 dpdD 222 */
+ .word CHAIN(pwrite) /* pwrite64 dpdD 223 */
+ .word CHAIN(creat) /* creat64 so 224 */
+ .word solaris_open /* open64 soo 225 */
.word solaris_unimplemented /* 226 */
.word solaris_unimplemented /* 227 */
.word solaris_unimplemented /* 228 */
.word solaris_unimplemented /* 229 */
- .word solaris_unimplemented /* 230 */
- .word solaris_unimplemented /* 231 */
- .word solaris_unimplemented /* 232 */
- .word solaris_unimplemented /* 233 */
- .word solaris_unimplemented /* 234 */
- .word solaris_unimplemented /* 235 */
- .word solaris_unimplemented /* 236 */
- .word solaris_unimplemented /* 237 */
- .word solaris_unimplemented /* 238 */
- .word solaris_unimplemented /* 239 */
- .word solaris_unimplemented /* 240 */
- .word solaris_unimplemented /* 241 */
- .word solaris_unimplemented /* 242 */
- .word solaris_unimplemented /* 243 */
- .word solaris_unimplemented /* 244 */
- .word solaris_unimplemented /* 245 */
- .word solaris_unimplemented /* 246 */
+ .word solaris_socket /* socket ddd 230 */
+ .word solaris_socketpair /* socketpair dddp 231 */
+ .word solaris_bind /* bind dpd 232 */
+ .word solaris_listen /* listen dd 233 */
+ .word solaris_accept /* accept dpp 234 */
+ .word solaris_connect /* connect dpd 235 */
+ .word solaris_shutdown /* shutdown dd 236 */
+ .word solaris_recv /* recv dpdd 237 */
+ .word solaris_recvfrom /* recvfrom dpddpp 238 */
+ .word solaris_recvmsg /* recvmsg dpd 239 */
+ .word solaris_send /* send dpdd 240 */
+ .word solaris_sendmsg /* sendmsg dpd 241 */
+ .word solaris_sendto /* sendto dpddpd 242 */
+ .word solaris_getpeername /* getpeername dpp 243 */
+ .word solaris_getsockname /* getsockname dpp 244 */
+ .word solaris_getsockopt /* getsockopt dddpp 245 */
+ .word solaris_setsockopt /* setsockopt dddpp 246 */
.word solaris_unimplemented /* 247 */
- .word solaris_unimplemented /* 248 */
- .word solaris_unimplemented /* 249 */
+ .word solaris_ntp_gettime /* ntp_gettime p 248 */
+ .word solaris_ntp_adjtime /* ntp_adjtime p 249 */
.word solaris_unimplemented /* 250 */
.word solaris_unimplemented /* 251 */
.word solaris_unimplemented /* 252 */
fi
fi
if [ "$CONFIG_PPC" = "y" ]; then
- bool ' WInbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
+ bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
fi
fi
if [ "$CONFIG_PMAC" = "y" ]; then
extern int scsi_dev_init(void);
extern int net_dev_init(void);
+#ifdef CONFIG_PPC
+extern void note_bootable_part(kdev_t dev, int part);
+#endif
+
/*
* disk_name() is used by genhd.c and md.c.
* It formats the devicename of the indicated disk
int blk, blocks_in_map;
int dev_bsize, dev_pos, pos;
unsigned secsize;
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
int first_bootable = 1;
#endif
struct mac_partition *part;
fsec + be32_to_cpu(part->start_block) * (secsize/512),
be32_to_cpu(part->block_count) * (secsize/512));
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
/*
* If this is the first bootable partition, tell the
* setup code, in case it wants to make this the root.
*/
- if (first_bootable
+ if ( (_machine == _MACH_Pmac) && first_bootable
&& (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
&& strcasecmp(part->processor, "powerpc") == 0) {
note_bootable_part(dev, blk);
first_bootable = 0;
}
-#endif /* CONFIG_PMAC */
+#endif /* CONFIG_PPC */
++current_minor;
}
static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned int bit, new, *old = (unsigned int *) hwif->select_data;
+ unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
struct pci_dev *dev = hwif->pci_dev;
unsigned long flags;
__cli(); /* local CPU only */
new = *old;
- /* adjust IRQ enable bit */
+ /* Adjust IRQ enable bit */
bit = 1 << (8 + hwif->channel);
new = drive->present ? (new & ~bit) : (new | bit);
- /* select PIO or DMA */
- bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
- new = use_dma ? (new | bit) : (new & ~bit);
+ /* Select PIO or DMA, DMA may only be selected for one drive/channel. */
+ bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1));
+ other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
+ new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
if (new != *old) {
- if (use_dma) {
- bit = (1 << (5 + drive->select.b.unit));
- outb((inb(hwif->dma_base+2) & 0x60) | bit,
- hwif->dma_base+2);
- }
-
*old = new;
(void) pci_write_config_dword(dev, 0x40, new);
}
+
__restore_flags(flags); /* local CPU only */
}
struct pci_dev *dev = hwif->pci_dev;
unsigned int ctrl, using_inta;
byte progif;
+#ifdef __sparc_v9__
+ int timeout;
+ byte stat;
+#endif
/*
* We cannot probe for IRQ: both ports share common IRQ on INTA.
pci_write_config_byte(dev, 0x55, 0xee);
#ifdef __sparc_v9__
-{
- int timeout;
- byte stat;
- /*
- * Put reasonable values in the timing registers
- * for DMA2 mode performance.
- */
- pci_write_config_byte(dev, 0x44, 0xfe);
- pci_write_config_byte(dev, 0x45, 0xfe);
- pci_write_config_byte(dev, 0x48, 0xfe);
- pci_write_config_byte(dev, 0x49, 0xfe);
- pci_write_config_byte(dev, 0x4c, 0xfe);
- pci_write_config_byte(dev, 0x4d, 0xfe);
- pci_write_config_byte(dev, 0x50, 0xfe);
- pci_write_config_byte(dev, 0x51, 0xfe);
-
/*
* XXX: Reset the device, if we don't it will not respond
* to SELECT_DRIVE() properly during first probe_hwif().
if (stat == 0xff)
break;
} while ((stat & BUSY_STAT) && --timeout);
-}
#endif
}
+
+ outb(0x60, hwif->dma_base + 2);
+
if (!using_inta)
hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */
else if (!hwif->irq && hwif->mate && hwif->mate->irq)
endif
endif
-ifeq ($(CONFIG_MACMOUSE),y)
-L_OBJS += macmouse.o
+ifeq ($(CONFIG_ADBMOUSE),y)
+L_OBJS += adbmouse.o
else
- ifeq ($(CONFIG_MACMOUSE),m)
- M_OBJS += macmouse.o
+ ifeq ($(CONFIG_ADBMOUSE),m)
+ M_OBJS += adbmouse.o
endif
endif
#define BLOCKMOVE
#define Z_WAKE
static char rcsid[] =
-"$Revision: 2.2.1.7 $$Date: 1998/09/03 12:07:28 $";
+"$Revision: 2.2.1.8 $$Date: 1998/11/13 12:46:20 $";
/*
* linux/drivers/char/cyclades.c
* void cleanup_module(void);
*
* $Log: cyclades.c,v $
+ * Revision 2.2.1.8 1998/11/13 12:46:20 ivan
+ * cy_close function now resets (correctly) the tty->closing flag;
+ * JIFFIES_DIFF macro fixed.
+ *
* Revision 2.2.1.7 1998/09/03 12:07:28 ivan
* Fixed bug in cy_close function, which was not informing HW of
* which port should have the reception disabled before doing so;
#define STD_COM_FLAGS (0)
-#define JIFFIES_DIFF(n, j) ((n) - (j))
+#define JIFFIES_DIFF(n, j) ((j) - (n))
static DECLARE_TASK_QUEUE(tq_cyclades);
tty->driver.flush_buffer(tty);
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
info->event = 0;
info->tty = 0;
if (info->blocked_open) {
#ifdef CONFIG_MDA_CONSOLE
extern void mda_console_init(void);
#endif
+#if defined(CONFIG_PPC) || defined(CONFIG_MAC)
+extern void adbdev_init(void);
+#endif
static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
const char * buf, size_t count, loff_t *ppos)
case 3:
filp->f_op = &null_fops;
break;
+#ifndef CONFIG_PPC
case 4:
filp->f_op = &port_fops;
break;
+#endif
case 5:
filp->f_op = &zero_fops;
break;
#ifdef CONFIG_VIDEO_BT848
i2c_init();
#endif
+#if defined(CONFIG_PPC) || defined(CONFIG_MAC)
+ adbdev_init();
+#endif
#ifdef CONFIG_VIDEO_DEV
videodev_init();
#endif
#define DYNAMIC_MINORS 64 /* like dynamic majors */
static unsigned char misc_minors[DYNAMIC_MINORS / 8];
-extern int adbdev_init(void);
extern int bus_mouse_init(void);
extern int qpmouse_init(void);
extern int ms_bus_mouse_init(void);
extern int atixl_busmouse_init(void);
extern int amiga_mouse_init(void);
extern int atari_mouse_init(void);
-extern int mac_mouse_init(void);
extern int sun_mouse_init(void);
extern int adb_mouse_init(void);
extern void watchdog_init(void);
if (proc_misc)
proc_misc->read_proc = misc_read_proc;
#endif /* PROC_FS */
-#ifdef CONFIG_MAC
- adbdev_init();
-#endif
#ifdef CONFIG_BUSMOUSE
bus_mouse_init();
#endif
#ifdef CONFIG_ATARIMOUSE
atari_mouse_init();
#endif
-#ifdef CONFIG_MACMOUSE
- mac_mouse_init();
-#endif
#ifdef CONFIG_SUN_MOUSE
sun_mouse_init();
#endif
-#ifdef CONFIG_MACMOUSE
+#ifdef CONFIG_ADBMOUSE
adb_mouse_init();
#endif
#ifdef CONFIG_PC110_PAD
-/* $Id: parport_ax.c,v 1.12 1998/07/26 03:03:31 davem Exp $
+/* $Id: parport_ax.c,v 1.13 1998/10/26 20:01:59 davem Exp $
* Parallel-port routines for Sun Ultra/AX architecture
*
* Author: Eddie C. Dost <ecd@skynet.be>
#include <linux/if_arp.h>
#include <linux/if_ltalk.h>
#include <linux/rtnetlink.h>
+#include <net/neighbour.h>
/* The network devices currently exist only in the socket namespace, so these
entries are unused. The only ones that make sense are
hippi_setup(tmp_dev);
return tmp_dev;
}
+
+static int hippi_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+{
+ /* Never send broadcast/multicast ARP messages */
+ p->mcast_probes = 0;
+
+ /* In IPv6 unicast probes are valid even on NBMA,
+ * because they are encapsulated in normal IPv6 protocol.
+ * Should be a generic flag.
+ */
+ if (p->tbl->family != AF_INET6)
+ p->ucast_probes = 0;
+ return 0;
+}
+
#endif
void ether_setup(struct device *dev)
dev->hard_header_parse = NULL;
dev->hard_header_cache = NULL;
dev->header_cache_update = NULL;
+ dev->neigh_setup = hippi_neigh_setup_dev;
/*
* We don't support HIPPI `ARP' for the time being, and probably
dev->tx_queue_len = 25 /* 5 */;
memset(dev->broadcast, 0xFF, HIPPI_ALEN);
- /* New-style flags. */
- dev->flags = IFF_NODYNARP; /*
- * HIPPI doesn't support
- * broadcast+multicast and we only
- * use static ARP tables.
- */
+
+ /*
+ * HIPPI doesn't support broadcast+multicast and we only use
+ * static ARP tables. ARP is disabled by hippi_neigh_setup_dev.
+ */
+ dev->flags = 0;
+
dev_init_buffers(dev);
}
#endif
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: sgiseeq.c,v 1.5 1998/05/01 01:35:40 ralf Exp $
+ * $Id: sgiseeq.c,v 1.6 1998/10/14 17:29:44 ralf Exp $
*/
#include <linux/kernel.h>
/* Ptrs to the descriptors in KSEG1 uncached space. */
struct sgiseeq_rx_desc *rx_desc;
struct sgiseeq_tx_desc *tx_desc;
- unsigned long _padding[14]; /* Pad out to largest cache line size. */
+ unsigned long _padding[30]; /* Pad out to largest cache line size. */
struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS];
struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS];
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
+#ifndef __sparc_v9__
+#include <asm/io-unit.h>
+#endif
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
(RXFLAG_OWN |
((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
(u32)virt_to_bus((volatile void *)skb->data));
- } else {
+ } else
+#endif
+#ifndef __sparc_v9__
+ if (sparc_cpu_model == sun4d) {
+ __u32 va = (__u32)hp->sun4d_buffers + i * PAGE_SIZE;
+
+ hb->happy_meal_rxd[i].rx_addr =
+ iounit_map_dma_page(va, skb->data, hp->happy_sbus_dev->my_bus);
+ hb->happy_meal_rxd[i].rx_flags =
+ (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
+ } else
#endif
+ {
hb->happy_meal_rxd[i].rx_addr = (u32)((unsigned long) skb->data);
hb->happy_meal_rxd[i].rx_flags =
(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
-#ifdef CONFIG_PCI
}
-#endif
skb_reserve(skb, RX_OFFSET);
}
HMD(("done\n"));
}
+#ifndef __sparc_v9__
static void sun4c_happy_meal_init_rings(struct happy_meal *hp)
{
struct hmeal_init_block *hb = hp->happy_block;
hb->happy_meal_txd[i].tx_flags = 0;
HMD(("done\n"));
}
+#endif
static void happy_meal_begin_auto_negotiation(struct happy_meal *hp,
struct hmeal_tcvregs *tregs)
/* Alloc and reset the tx/rx descriptor chains. */
HMD(("happy_meal_init: to happy_meal_init_rings\n"));
+#ifndef __sparc_v9__
if(sparc_cpu_model == sun4c)
sun4c_happy_meal_init_rings(hp);
else
+#endif
happy_meal_init_rings(hp, from_irq);
/* Shut up the MIF. */
: "=r" (flags)
: "r" (&this->tx_flags), "i" (ASI_PL));
#else
- flush_cache_all();
flags = flip_dword(this->tx_flags);
#endif
if(flags & TXFLAG_OWN)
}
#endif
+#ifndef __sparc_v9__
static inline void sun4c_happy_meal_tx(struct happy_meal *hp)
{
struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0];
hp->tx_old = elem;
TXD((">"));
}
+#endif
#ifdef RXDEBUG
#define RXD(x) printk x
: "=r" (flags)
: "r" (&this->rx_flags), "i" (ASI_PL));
#else
- flush_cache_all();
flags = flip_dword(this->rx_flags); /* FIXME */
#endif
while(!(flags & RXFLAG_OWN)) {
: "=r" (flags)
: "r" (&this->rx_flags), "i" (ASI_PL));
#else
- flush_cache_all();
flags = flip_dword(this->rx_flags); /* FIXME */
#endif
}
}
#endif
+#ifndef __sparc_v9__
static inline void sun4c_happy_meal_rx(struct happy_meal *hp, struct device *dev,
struct hmeal_gregs *gregs)
{
RXD((">"));
}
+static inline void sun4d_happy_meal_rx(struct happy_meal *hp, struct device *dev,
+ struct hmeal_gregs *gregs)
+{
+ struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
+ struct happy_meal_rxd *this;
+ int elem = hp->rx_new, drops = 0;
+ __u32 va;
+
+ RXD(("RX<"));
+ this = &rxbase[elem];
+ while(!(this->rx_flags & RXFLAG_OWN)) {
+ struct sk_buff *skb;
+ unsigned int flags = this->rx_flags;
+ int len = flags >> 16;
+ u16 csum = flags & RXFLAG_CSUM;
+
+ RXD(("[%d ", elem));
+
+ /* Check for errors. */
+ if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
+ RXD(("ERR(%08x)]", flags));
+ hp->net_stats.rx_errors++;
+ if(len < ETH_ZLEN)
+ hp->net_stats.rx_length_errors++;
+ if(len & (RXFLAG_OVERFLOW >> 16)) {
+ hp->net_stats.rx_over_errors++;
+ hp->net_stats.rx_fifo_errors++;
+ }
+
+ /* Return it to the Happy meal. */
+ drop_it:
+ hp->net_stats.rx_dropped++;
+ va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE;
+ this->rx_addr = iounit_map_dma_page(va, hp->rx_skbs[elem]->data,
+ hp->happy_sbus_dev->my_bus);
+ this->rx_flags =
+ (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
+ goto next;
+ }
+ skb = hp->rx_skbs[elem];
+ if(len > RX_COPY_THRESHOLD) {
+ struct sk_buff *new_skb;
+
+ /* Now refill the entry, if we can. */
+ new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC);
+ if(!new_skb) {
+ drops++;
+ goto drop_it;
+ }
+
+ hp->rx_skbs[elem] = new_skb;
+ new_skb->dev = dev;
+ skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
+ va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE;
+ rxbase[elem].rx_addr = iounit_map_dma_page(va, new_skb->data,
+ hp->happy_sbus_dev->my_bus);
+
+ skb_reserve(new_skb, RX_OFFSET);
+ rxbase[elem].rx_flags =
+ (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
+
+ /* Trim the original skb for the netif. */
+ skb_trim(skb, len);
+ } else {
+ struct sk_buff *copy_skb = dev_alloc_skb(len+2);
+
+ if(!copy_skb) {
+ drops++;
+ goto drop_it;
+ }
+
+ copy_skb->dev = dev;
+ skb_reserve(copy_skb, 2);
+ skb_put(copy_skb, len);
+ memcpy(copy_skb->data, skb->data, len);
+
+ /* Reuse original ring buffer. */
+ va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE;
+ rxbase[elem].rx_addr = iounit_map_dma_page(va, skb->data,
+ hp->happy_sbus_dev->my_bus);
+ rxbase[elem].rx_flags =
+ (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
+
+ skb = copy_skb;
+ }
+
+ /* This card is _fucking_ hot... */
+ if(!(csum ^ 0xffff))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ RXD(("len=%d csum=%4x]", len, csum));
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+
+ hp->net_stats.rx_packets++;
+ hp->net_stats.rx_bytes+=len;
+ next:
+ elem = NEXT_RX(elem);
+ this = &rxbase[elem];
+ }
+ hp->rx_new = elem;
+ if(drops)
+ printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name);
+ RXD((">"));
+}
+#endif
+
static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *) dev_id;
dev->interrupt = 0;
HMD(("done\n"));
}
+
+static void sun4d_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct device *dev = (struct device *) dev_id;
+ struct happy_meal *hp = (struct happy_meal *) dev->priv;
+ struct hmeal_gregs *gregs = hp->gregs;
+ struct hmeal_tcvregs *tregs = hp->tcvregs;
+ unsigned int happy_status = hme_read32(hp, &gregs->stat);
+
+ HMD(("happy_meal_interrupt: status=%08x ", happy_status));
+
+ dev->interrupt = 1;
+
+ if(happy_status & GREG_STAT_ERRORS) {
+ HMD(("ERRORS "));
+ if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) {
+ dev->interrupt = 0;
+ return;
+ }
+ }
+
+ if(happy_status & GREG_STAT_MIFIRQ) {
+ HMD(("MIFIRQ "));
+ happy_meal_mif_interrupt(hp, gregs, tregs);
+ }
+
+ if(happy_status & GREG_STAT_TXALL) {
+ HMD(("TXALL "));
+ happy_meal_tx(hp);
+ }
+
+ if(happy_status & GREG_STAT_RXTOHOST) {
+ HMD(("RXTOHOST "));
+ sun4d_happy_meal_rx(hp, dev, gregs);
+ }
+
+ if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) {
+ hp->dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+
+ dev->interrupt = 0;
+ HMD(("done\n"));
+}
#endif
static int happy_meal_open(struct device *dev)
printk("happy meal: Can't order irq %d to go.\n", dev->irq);
return -EAGAIN;
}
+ } else if (sparc_cpu_model == sun4d) {
+ if(request_irq(dev->irq, &sun4d_happy_meal_interrupt,
+ SA_SHIRQ, "HAPPY MEAL", (void *) dev)) {
+ HMD(("EAGAIN\n"));
+ printk("happy_meal(SBUS): Can't order irq %s to go.\n",
+ __irq_itoa(dev->irq));
+ return -EAGAIN;
+ }
} else
#endif
#ifdef CONFIG_PCI
}
#endif
+#ifndef __sparc_v9__
static int sun4c_happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
{
struct happy_meal *hp = (struct happy_meal *) dev->priv;
return 0;
}
+static int sun4d_happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct happy_meal *hp = (struct happy_meal *) dev->priv;
+ int len, entry;
+ __u32 va;
+
+ if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+ int tickssofar = jiffies - dev->trans_start;
+
+ if (tickssofar >= 40) {
+ printk ("%s: transmit timed out, resetting\n", dev->name);
+ hp->net_stats.tx_errors++;
+ tx_dump_log();
+ printk ("%s: Happy Status %08x TX[%08x:%08x]\n", dev->name,
+ hme_read32(hp, &hp->gregs->stat),
+ hme_read32(hp, &hp->etxregs->cfg),
+ hme_read32(hp, &hp->bigmacregs->tx_cfg));
+ happy_meal_init(hp, 0);
+ dev->tbusy = 0;
+ dev->trans_start = jiffies;
+ } else
+ tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0);
+ return 1;
+ }
+
+ if(!TX_BUFFS_AVAIL(hp)) {
+ tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0);
+ return 1;
+ }
+ len = skb->len;
+ entry = hp->tx_new;
+
+ SXD(("SX<l[%d]e[%d]>", len, entry));
+ hp->tx_skbs[entry] = skb;
+ va = (__u32)hp->sun4d_buffers + (RX_RING_SIZE + entry) * PAGE_SIZE;
+ hp->happy_block->happy_meal_txd[entry].tx_addr =
+ iounit_map_dma_page(va, skb->data, hp->happy_sbus_dev->my_bus);
+ hp->happy_block->happy_meal_txd[entry].tx_flags =
+ (TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE));
+ hp->tx_new = NEXT_TX(entry);
+
+ /* Get it going. */
+ dev->trans_start = jiffies;
+ hme_write32(hp, &hp->etxregs->tx_pnding, ETX_TP_DMAWAKEUP);
+
+ if(TX_BUFFS_AVAIL(hp))
+ dev->tbusy = 0;
+
+ tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
+ return 0;
+}
+#endif
+
static struct net_device_stats *happy_meal_get_stats(struct device *dev)
{
struct happy_meal *hp = (struct happy_meal *) dev->priv;
sparc_dvma_malloc(PAGE_SIZE, "Happy Meal Init Block",
&hp->hblock_dvma);
+#ifndef __sparc_v9__
if(sparc_cpu_model == sun4c)
hp->sun4c_buffers = (struct hmeal_buffers *)
sparc_dvma_malloc(sizeof(struct hmeal_buffers), "Happy Meal Bufs",
&hp->s4c_buf_dvma);
+ else if (sparc_cpu_model == sun4d)
+ hp->sun4d_buffers = (struct hmeal_buffers *)
+ iounit_map_dma_init(hp->happy_sbus_dev->my_bus,
+ (RX_RING_SIZE + TX_RING_SIZE) * PAGE_SIZE);
else
+#endif
hp->sun4c_buffers = 0;
/* Force check of the link first time we are brought up. */
hp->dev = dev;
dev->open = &happy_meal_open;
dev->stop = &happy_meal_close;
+#ifndef __sparc_v9__
if(sparc_cpu_model == sun4c)
dev->hard_start_xmit = &sun4c_happy_meal_start_xmit;
+ else if (sparc_cpu_model == sun4d)
+ dev->hard_start_xmit = &sun4d_happy_meal_start_xmit;
else
+#endif
dev->hard_start_xmit = &happy_meal_start_xmit;
dev->get_stats = &happy_meal_get_stats;
dev->set_multicast_list = &happy_meal_set_multicast;
}
hp->hblock_dvma = (u32) virt_to_bus(hp->happy_block);
+#ifndef __sparc_v9__
+ /* This case we currently need to use 'sparc_alloc_io' */
+ hp->happy_block = sparc_alloc_io (hp->hblock_dvma, NULL,
+ PAGE_SIZE, "sunhme", 0, 0);
+#endif
hp->sun4c_buffers = 0;
hp->linkcheck = 0;
sparc_free_io(hp->erxregs, sizeof(struct hmeal_erxregs));
sparc_free_io(hp->bigmacregs, sizeof(struct hmeal_bigmacregs));
sparc_free_io(hp->tcvregs, sizeof(struct hmeal_tcvregs));
+#ifndef __sparc_v9__
+ if (sparc_cpu_model == sun4d)
+ iounit_map_dma_finish(hp->happy_sbus_dev->my_bus,
+ (__u32)hp->sun4d_buffers, (RX_RING_SIZE + TX_RING_SIZE) * PAGE_SIZE);
+#endif
unregister_netdev(hp->dev);
kfree(hp->dev);
root_happy_dev = sunshine;
/* We may use this for Ultra as well, will have to see, maybe not. */
struct hmeal_buffers *sun4c_buffers; /* CPU visible address. */
+#define sun4d_buffers sun4c_buffers /* No need to make this a separate. */
__u32 s4c_buf_dvma; /* DVMA visible address. */
unsigned int happy_flags; /* Driver state flags */
{
rp->rx_addr = flip_dword(addr);
rp->rx_flags = flip_dword(flags);
- flush_cache_all();
}
extern inline void pcihme_write_txd(struct happy_meal_txd *tp,
{
tp->tx_addr = flip_dword(addr);
tp->tx_flags = flip_dword(flags);
- flush_cache_all();
}
#endif /* def __sparc_v9__ */
ifeq ($(CONFIG_SPARCAUDIO_DBRI),y)
SBUS_AUDIO=y
-O_OBJS += dbri.o
+OX_OBJS += dbri.o
else
ifeq ($(CONFIG_SPARCAUDIO_DBRI),m)
SBUS_AUDIO_MODULE=y
- M_OBJS += dbri.o
+ MX_OBJS += dbri.o
endif
endif
*
* Thanks to the AMD engineer who was able to get us the AMD79C30
* databook which has all the programming information and gain tables.
+ *
+ * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
+ * SparcStation 1+. The chip provides microphone and speaker interfaces
+ * which provide mono-channel audio at 8K samples per second via either
+ * 8-bit A-law or 8-bit mu-law encoding. Also, the chip features an
+ * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
+ * which performs basic D channel LAPD processing and provides raw
+ * B channel data. The digital audio channel, the two ISDN B channels,
+ * and two 64 Kbps channels to the microprocessor are all interconnected
+ * via a multiplexer.
+ *
+ * This driver interfaces to the Linux HiSax ISDN driver, which performs
+ * all high-level Q.921 and Q.931 ISDN functions. The file is not
+ * itself a hardware driver; rather it uses functions exported by
+ * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
+ * allowing the chip to be simultaneously used for both audio and ISDN data.
+ * The hardware driver does _no_ buffering, but provides several callbacks
+ * which are called during interrupt service and should therefore run quickly.
+ *
+ * D channel transmission is performed by passing the hardware driver the
+ * address and size of an skb's data area, then waiting for a callback
+ * to signal successful transmission of the packet. A task is then
+ * queued to notify the HiSax driver that another packet may be transmitted.
+ *
+ * D channel reception is quite simple, mainly because of:
+ * 1) the slow speed of the D channel - 16 kbps, and
+ * 2) the presence of an 8- or 32-byte (depending on chip version) FIFO
+ * to buffer the D channel data on the chip
+ * Worst case scenario of back-to-back packets with the 8 byte buffer
+ * at 16 kbps yields an service time of 4 ms - long enough to preclude
+ * the need for fancy buffering. We queue a background task that copies
+ * data out of the receive buffer into an skb, and the hardware driver
+ * simply does nothing until we're done with the receive buffer and
+ * reset it for a new packet.
+ *
+ * B channel processing is more complex, because of:
+ * 1) the faster speed - 64 kbps,
+ * 2) the lack of any on-chip buffering (it interrupts for every byte), and
+ * 3) the lack of any chip support for HDLC encapsulation
+ *
+ * The HiSax driver can put each B channel into one of three modes -
+ * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
+ * and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
+ * L1_MODE_HDLC is the most common, used for almost all "pure" digital
+ * data sessions. L1_MODE_TRANS is used for ISDN audio.
+ *
+ * HDLC B channel transmission is performed via a large buffer into
+ * which the skb is copied while performing HDLC bit-stuffing. A CRC
+ * is computed and attached to the end of the buffer, which is then
+ * passed to the low-level routines for raw transmission. Once
+ * transmission is complete, the hardware driver is set to enter HDLC
+ * idle by successive transmission of mark (all 1) bytes, waiting for
+ * the ISDN driver to prepare another packet for transmission and
+ * deliver it.
+ *
+ * HDLC B channel reception is performed via an X-byte ring buffer
+ * divided into N sections of X/N bytes each. Defaults: X=256 bytes, N=4.
+ * As the hardware driver notifies us that each section is full, we
+ * hand it the next section and schedule a background task to peruse
+ * the received section, bit-by-bit, with an HDLC decoder. As
+ * packets are detected, they are copied into a large buffer while
+ * decoding HDLC bit-stuffing. The ending CRC is verified, and if
+ * it is correct, we alloc a new skb of the correct length (which we
+ * now know), copy the packet into it, and hand it to the upper layers.
+ * Optimization: for large packets, we hand the buffer (which also
+ * happens to be an skb) directly to the upper layer after an skb_trim,
+ * and alloc a new large buffer for future packets, thus avoiding a copy.
+ * Then we return to HDLC processing; state is saved between calls.
*/
#include <linux/module.h>
#include <asm/audioio.h>
#include "amd7930.h"
+#include "../../isdn/hisax/hisax.h"
+#include "../../isdn/hisax/isdnl1.h"
+#include "../../isdn/hisax/foreign.h"
+
#define MAX_DRIVERS 1
static struct sparcaudio_driver drivers[MAX_DRIVERS];
* driver, since D.output_callback_arg is assumed to be a certain struct ptr
*/
-#include "../../isdn/hisax/hisax.h"
-#include "../../isdn/hisax/isdnl1.h"
-
#ifdef L2FRAME_DEBUG
inline void debug_info(struct amd7930_info *info, char c) {
*/
-int amd7930_get_irqnum(int dev)
+static int amd7930_get_irqnum(int dev)
{
struct amd7930_info *info;
return info->irq;
}
-int amd7930_get_liu_state(int dev)
+static int amd7930_get_liu_state(int dev)
{
struct amd7930_info *info;
return info->liu_state;
}
-void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
+static void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
{
struct amd7930_info *info;
register unsigned long flags;
restore_flags(flags);
}
-void amd7930_liu_activate(int dev, int priority)
+static void amd7930_liu_activate(int dev, int priority)
{
struct amd7930_info *info;
register unsigned long flags;
restore_flags(flags);
}
-void amd7930_liu_deactivate(int dev)
+static void amd7930_liu_deactivate(int dev)
{
struct amd7930_info *info;
register unsigned long flags;
restore_flags(flags);
}
-void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
- void (*callback)(void *, int), void *callback_arg)
+static void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
+ void (*callback)(void *, int), void *callback_arg)
{
struct amd7930_info *info;
register unsigned long flags;
restore_flags(flags);
}
-void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
- void (*callback)(void *, int, unsigned int),
- void *callback_arg)
+static void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
+ void (*callback)(void *, int, unsigned int),
+ void *callback_arg)
{
struct amd7930_info *info;
register unsigned long flags;
restore_flags(flags);
}
-int amd7930_bopen(int dev, int chan, u_char xmit_idle_char)
+static int amd7930_bopen(int dev, unsigned int chan,
+ int mode, u_char xmit_idle_char)
{
struct amd7930_info *info;
register unsigned long flags;
return -1;
}
+ if (mode == L1_MODE_HDLC) {
+ return -1;
+ }
+
info = (struct amd7930_info *) drivers[dev].private;
save_and_cli(flags);
return 0;
}
-void amd7930_bclose(int dev, int chan)
+static void amd7930_bclose(int dev, unsigned int chan)
{
struct amd7930_info *info;
register unsigned long flags;
restore_flags(flags);
}
-void amd7930_bxmit(int dev, int chan, __u8 * buffer, unsigned long count,
- void (*callback)(void *), void *callback_arg)
+static void amd7930_bxmit(int dev, unsigned int chan,
+ __u8 * buffer, unsigned long count,
+ void (*callback)(void *, int), void *callback_arg)
{
struct amd7930_info *info;
struct amd7930_channel *Bchan;
}
}
-void amd7930_brecv(int dev, int chan, __u8 * buffer, unsigned long size,
- void (*callback)(void *), void *callback_arg)
+static void amd7930_brecv(int dev, unsigned int chan,
+ __u8 * buffer, unsigned long size,
+ void (*callback)(void *, int, unsigned int),
+ void *callback_arg)
{
struct amd7930_info *info;
struct amd7930_channel *Bchan;
}
}
-EXPORT_SYMBOL(amd7930_get_irqnum);
-EXPORT_SYMBOL(amd7930_get_liu_state);
-EXPORT_SYMBOL(amd7930_liu_init);
-EXPORT_SYMBOL(amd7930_liu_activate);
-EXPORT_SYMBOL(amd7930_liu_deactivate);
-EXPORT_SYMBOL(amd7930_dxmit);
-EXPORT_SYMBOL(amd7930_drecv);
-EXPORT_SYMBOL(amd7930_bopen);
-EXPORT_SYMBOL(amd7930_bclose);
-EXPORT_SYMBOL(amd7930_bxmit);
-EXPORT_SYMBOL(amd7930_brecv);
+struct foreign_interface amd7930_foreign_interface = {
+ amd7930_get_irqnum,
+ amd7930_get_liu_state,
+ amd7930_liu_init,
+ amd7930_liu_activate,
+ amd7930_liu_deactivate,
+ amd7930_dxmit,
+ amd7930_drecv,
+ amd7930_bopen,
+ amd7930_bclose,
+ amd7930_bxmit,
+ amd7930_brecv
+};
+EXPORT_SYMBOL(amd7930_foreign_interface);
/*
#include <linux/types.h>
-/* Exported ISDN functions */
-
-int amd7930_get_irqnum(int dev);
-int amd7930_get_liu_state(int dev);
-void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg);
-void amd7930_liu_activate(int dev, int priority);
-void amd7930_liu_deactivate(int dev);
-void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
- void (*callback)(void *, int), void *callback_arg);
-void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
- void (*callback)(void *, int, unsigned int),
- void *callback_arg);
-int amd7930_bopen(int dev, int chan, u_char xmit_idle_char);
-void amd7930_bclose(int dev, int chan);
-void amd7930_bxmit(int dev, int chan, __u8 * buffer, unsigned long count,
- void (*callback)(void *), void *callback_arg);
-void amd7930_brecv(int dev, int chan, __u8 * buffer, unsigned long size,
- void (*callback)(void *), void *callback_arg);
-
-
/* Register interface presented to the CPU by the amd7930. */
struct amd7930
{
sparcaudio_ioctl,
NULL, /* sparcaudio_mmap */
sparcaudio_open,
+ NULL, /* sparcaudio_flush */
sparcaudio_release
};
cs4231_chip->playlen = cs4231_chip->output_size;
if (cs4231_chip->output_dma_handle) {
- mmu_release_scsi_one((char *)cs4231_chip->output_dma_handle,
+ mmu_release_scsi_one((u32)((unsigned long)cs4231_chip->output_dma_handle),
4096, drv->dev->my_bus);
cs4231_chip->output_dma_handle = 0;
}
}
if (cs4231_chip->output_ptr && cs4231_chip->output_size > 0) {
- cs4231_chip->output_next_dma_handle =
- mmu_get_scsi_one((char *) cs4231_chip->output_ptr, 4096,
- drv->dev->my_bus);
- cs4231_chip->regs->dmapnva = cs4231_chip->output_next_dma_handle;
+ cs4231_chip->output_next_dma_handle = (u32 *)(unsigned long)
+ mmu_get_scsi_one((char *) cs4231_chip->output_ptr,
+ 4096, drv->dev->my_bus);
+ cs4231_chip->regs->dmapnva = (u32) (unsigned long)
+ cs4231_chip->output_next_dma_handle;
cs4231_chip->regs->dmapnc = cs4231_chip->output_size;
cs4231_chip->output_size = 0;
cs4231_chip->output_ptr = NULL;
cs4231_disable_rec(drv);
}
if (cs4231_chip->input_ptr) {
- cs4231_chip->regs->dmacnva = (__u32) cs4231_chip->input_ptr;
+ cs4231_chip->regs->dmacnva = (__u32) ((unsigned long)cs4231_chip->input_ptr);
cs4231_chip->regs->dmacnc = cs4231_chip->input_size;
cs4231_chip->input_ptr = NULL;
cs4231_chip->input_size = 0;
cs4231_chip->output_ptr = NULL;
cs4231_chip->output_size = 0;
if (cs4231_chip->output_dma_handle) {
- mmu_release_scsi_one((char *)cs4231_chip->output_dma_handle,
+ mmu_release_scsi_one((u32)((unsigned long)cs4231_chip->output_dma_handle),
4096, drv->dev->my_bus);
cs4231_chip->output_dma_handle = 0;
}
if (cs4231_chip->output_next_dma_handle) {
- mmu_release_scsi_one((char *)cs4231_chip->output_next_dma_handle,
+ mmu_release_scsi_one((u32)((unsigned long)cs4231_chip->output_next_dma_handle),
4096, drv->dev->my_bus);
cs4231_chip->output_next_dma_handle = 0;
}
/* Current buffer that the driver is playing. */
volatile __u8 * output_ptr;
volatile unsigned long output_size;
- volatile __u32 * output_dma_handle, output_next_dma_handle;
+ volatile __u32 * output_dma_handle, * output_next_dma_handle;
/* Current record buffer. */
volatile __u8 * input_ptr;
#include <asm/audioio.h>
#include "dbri.h"
+#include "../../isdn/hisax/hisax.h"
+#include "../../isdn/hisax/isdnl1.h"
+#include "../../isdn/hisax/foreign.h"
-#define DBRI_DEBUG
+/* #define DBRI_DEBUG */
#ifdef DBRI_DEBUG
static struct sparcaudio_driver drivers[MAX_DRIVERS];
static char drv_name[] = "DBRI/audio";
-static int num_drivers;
-static int dbri_cmdlocked = 0;
+static int num_drivers = 0;
static void * output_callback_arg;
/*
- * Make sure, that we can send a command to the dbri
+ * Commands are sent to the DBRI by building a list of them in memory,
+ * then writing the address of the first list item to DBRI register 8.
+ * The list is terminated with a WAIT command, which can generate a
+ * CPU interrupt if required.
+ *
+ * Since the DBRI can run asynchronously to the CPU, several means of
+ * synchronization present themselves. The original scheme (Rudolf's)
+ * was to set a flag when we "cmdlock"ed the DBRI, clear the flag when
+ * an interrupt signaled completion, and wait on a wait_queue if a routine
+ * attempted to cmdlock while the flag was set. The problems arose when
+ * we tried to cmdlock from inside an interrupt handler, which might
+ * cause scheduling in an interrupt (if we waited), etc, etc
+ *
+ * A more sophisticated scheme might involve a circular command buffer
+ * or an array of command buffers. A routine could fill one with
+ * commands and link it onto a list. When a interrupt signaled
+ * completion of the current command buffer, look on the list for
+ * the next one.
+ *
+ * I've decided to implement something much simpler - after each command,
+ * the CPU waits for the DBRI to finish the command by polling the P bit
+ * in DBRI register 0. I've tried to implement this in such a way
+ * that might make implementing a more sophisticated scheme easier.
+ *
+ * Every time a routine wants to write commands to the DBRI, it
+ * must first call dbri_cmdlock() and get an initial index into dbri->cmd
+ * (currently always 0) in return. After the commands have been
+ * write (index incremented after each one), dbri_cmdsend() is called
+ * with the final index value.
*/
+
static int dbri_cmdlock(struct dbri *dbri)
{
- unsigned long flags;
- int was_sleeping = 0;
+ return 0;
+}
- save_flags(flags);
- cli();
+static void dbri_cmdsend(struct dbri *dbri, int n)
+{
+ int maxloops = 1000000;
- if(dbri_cmdlocked) {
- interruptible_sleep_on(&dbri->wait);
- was_sleeping = 1;
- }
- if(dbri_cmdlocked)
- return -EINTR;
- dbri_cmdlocked = 1;
+ dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, WAIT_INTR1);
+ dbri->regs->reg8 = (int)dbri->cmd;
- restore_flags(flags);
+ while (maxloops > 0 && (dbri->regs->reg0 & D_P));
- if(was_sleeping)
- dprintk(D_INT, ("DBRI: Just woke up\n"));
- return 0;
+ if (maxloops == 0) {
+ printk("DBRI: Maxloops exceeded in dbri_cmdsend\n");
+ }
}
static void dbri_reset(struct sparcaudio_driver *drv)
/*
* Set up the interrupt queue
*/
- (void)dbri_cmdlock(dbri);
+ n = dbri_cmdlock(dbri);
- n = 0;
dbri->cmd[n++] = DBRI_CMD(D_IIQ, 0, 0);
dbri->cmd[n++] = (int)(dbri->intr);
- dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
- dbri->regs->reg8 = (int)dbri->cmd;
+
+ dbri_cmdsend(dbri, n);
}
static void mmcodec_init_data(struct dbri *dbri)
{
- int val, n = 0;
+ int val, n;
- dbri_cmdlock(dbri);
+ n = dbri_cmdlock(dbri);
/*
* Data mode:
/* CHI: Slave mode; enable interrupts */
dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0) | D_CHI_IR | D_CHI_EN);
- dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, WAIT_INTR1);
-
- dbri->regs->reg8 = (int)dbri->cmd;
+ dbri_cmdsend(dbri, n);
}
*/
static void mmcodec_setctrl(struct dbri *dbri)
{
- int n = 0, val;
+ int n, val;
/*
* Enable Control mode: Set DBRI's PIO3 (4215's D/~C) to 0, then wait
* by eight clock cycles. Anybody know why?
*/
- dbri_cmdlock(dbri);
+ n = dbri_cmdlock(dbri);
/*
* Control mode:
dbri->cmd[n++] = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN);
dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0);
- dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
- dbri->regs->reg8 = (int)dbri->cmd;
-
-
- /* Wait for the data from the CS4215 */
- interruptible_sleep_on(&dbri->int_wait);
+ /* Wait for the command to complete */
+ dbri_cmdsend(dbri, n);
/* Switch CS4215 to data mode - data sheet says
* "Set CLB=1 and send two more frames of valid control info"
*/
- dbri_cmdlock(dbri);
+ n = dbri_cmdlock(dbri);
- n = 0;
dbri->mm.ctrl[0] |= CS4215_CLB;
dbri->cmd[n++] = DBRI_CMD(D_SSP, 0, D_PIPE(D_P_17));
dbri->cmd[n++] = reverse_bytes(*(int *)dbri->mm.ctrl, 4);
- dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
- dbri->regs->reg8 = (int)dbri->cmd;
-
- dbri_cmdlock(dbri);
+ dbri_cmdsend(dbri, n);
/* Two frames of control info @ 8kHz frame rate = 250 us delay */
udelay(250);
- n = 0;
+ n = dbri_cmdlock(dbri);
/* Now switch back to data mode */
/* Reset CHI Anchor: Stop Send/Receive */
dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0x16);
- dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
- dbri->regs->reg8 = (int)dbri->cmd;
-
/* Wait for command to complete */
- dbri_cmdlock(dbri);
- n = 0;
- dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
- dbri->regs->reg8 = (int)dbri->cmd;
-
+ dbri_cmdsend(dbri, n);
/* Switch CS4215 to data mode - set PIO3 to 1 */
dbri->regs->reg2 = D_ENPIO | D_PIO1 | D_PIO3 |
return 0;
}
+void dbri_isdn_init(struct dbri *dbri)
+{
+ int n, val;
+
+ /* Pipe 0: Receive D channel
+ * Pipe 8: Receive B1 channel
+ * Pipe 9: Receive B2 channel
+ * Pipe 1: Transmit D channel
+ * Pipe 10: Transmit B1 channel
+ * Pipe 11: Transmit B2 channel
+ */
+
+ n = dbri_cmdlock(dbri);
+
+ /* Pipe 0: SDP */
+ val = D_SDP_HDLC|D_SDP_FROM_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_0);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 8: SDP */
+ val = D_SDP_HDLC|D_SDP_FROM_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_8);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 9: SDP */
+ val = D_SDP_HDLC|D_SDP_FROM_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_9);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 1: SDP */
+ val = D_SDP_HDLC_D|D_SDP_TO_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_1);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 10: SDP */
+ val = D_SDP_HDLC|D_SDP_TO_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_10);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 11: SDP */
+ val = D_SDP_HDLC|D_SDP_TO_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_11);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+
+ dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0);
+
+ /* Pipe 0: DTS */
+ val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_0) | D_PIPE(D_P_0);
+ dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+ dbri->cmd[n++] = D_TS_LEN(2) | D_TS_CYCLE(17)| D_TS_NEXT(D_P_0);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 8: DTS */
+ val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_0) | D_PIPE(D_P_8);
+ dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+ dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(0)| D_TS_NEXT(D_P_0);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 9: DTS */
+ val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_8) | D_PIPE(D_P_9);
+ dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+ dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_0);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 1: DTS */
+ val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_1) | D_PIPE(D_P_1);
+ dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+ dbri->cmd[n++] = 0;
+ dbri->cmd[n++] = D_TS_LEN(2) | D_TS_CYCLE(17)| D_TS_NEXT(D_P_1);
+
+ /* Pipe 10: DTS */
+ val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_1) | D_PIPE(D_P_10);
+ dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+ dbri->cmd[n++] = 0;
+ dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(0)| D_TS_NEXT(D_P_1);
+
+ /* Pipe 11: DTS */
+ val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_10) | D_PIPE(D_P_11);
+ dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+ dbri->cmd[n++] = 0;
+ dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_1);
+
+
+ /* Wait for command to complete */
+ dbri_cmdsend(dbri, n);
+}
+
+
void dbri_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
val = D_INTR_GETVAL(x);
+ if (D_INTR_GETCODE(x) == D_INTR_SBRI) {
+ int liu_states[] = {1, 0, 8, 3, 4, 5, 6, 7};
+ dbri->liu_state = liu_states[val & 0x7];
+ if (dbri->liu_callback)
+ dbri->liu_callback(dbri->liu_callback_arg);
+ }
+
switch(D_INTR_GETCHAN(x)) {
case D_INTR_CMD:
+#if 0
if(D_INTR_GETCMD(x) == D_WAIT)
if(val == WAIT_INTR1) {
dbri_cmdlocked = 0;
}
if(val == WAIT_INTR2)
wake_up(&dbri->int_wait);
+#endif
break;
+
+ case D_P_0:
+ /* Pipe 0 - D channel receive */
+ if (D_INTR_GETCODE(x) == D_INTR_BRDY &&
+ dbri->D.input_callback) {
+ dbri->D.input_callback(dbri->D.input_callback_arg,
+ DBRI_RD_STATUS(dbri->D.rd.flags),
+ DBRI_RD_CNT(dbri->D.rd.flags)-2);
+ }
+ break;
+
+ case D_P_1:
+ /* Pipe 1 - D channel transmit */
+ if (D_INTR_GETCODE(x) == D_INTR_XCMP &&
+ dbri->D.output_callback) {
+ dbri->D.output_callback(dbri->D.output_callback_arg,
+ DBRI_TD_STATUS(dbri->D.rd.flags)&0xe);
+ }
+ break;
+
case D_P_4:
+ /* Pipe 4 - audio transmit */
if (D_INTR_GETCODE(x) == D_INTR_XCMP) {
sparcaudio_output_done(output_callback_arg, 1);
}
break;
+ case D_P_8:
+ /* Pipe 8 - B1 channel receive */
+ if (D_INTR_GETCODE(x) == D_INTR_BRDY &&
+ dbri->B[0].input_callback) {
+ dbri->B[0].input_callback(dbri->B[0].input_callback_arg,
+ DBRI_RD_STATUS(dbri->B[0].rd.flags),
+ DBRI_RD_CNT(dbri->B[0].rd.flags)-2);
+ }
+ break;
+
+ case D_P_9:
+ /* Pipe 9 - B2 channel receive */
+ if (D_INTR_GETCODE(x) == D_INTR_BRDY &&
+ dbri->B[1].input_callback) {
+ dbri->B[1].input_callback(dbri->B[1].input_callback_arg,
+ DBRI_RD_STATUS(dbri->B[1].rd.flags),
+ DBRI_RD_CNT(dbri->B[1].rd.flags)-2);
+ }
+ break;
+
+ case D_P_10:
+ /* Pipe 10 - B1 channel transmit */
+ if (D_INTR_GETCODE(x) == D_INTR_XCMP &&
+ dbri->B[0].output_callback) {
+ dbri->B[0].output_callback(dbri->B[0].output_callback_arg,
+ DBRI_TD_STATUS(dbri->B[0].rd.flags)&0xfe);
+ }
+ break;
+
+ case D_P_11:
+ /* Pipe 11 - B2 channel transmit */
+ if (D_INTR_GETCODE(x) == D_INTR_XCMP &&
+ dbri->B[1].output_callback) {
+ dbri->B[1].output_callback(dbri->B[1].output_callback_arg,
+ DBRI_TD_STATUS(dbri->B[1].rd.flags)&0xfe);
+ }
+ break;
+
case D_P_18:
+ /* Pipe 18 - receive CS4215 status */
if(val != 0) {
x = reverse_bytes(val,2)&CS4215_12_MASK;
-printk("Comparing int: %x with hi(%x)\n", x, *(int *)dbri->mm.ctrl);
- if(x == (*(int *)dbri->mm.ctrl >> 16))
-{
-printk("Comp ok\n");
+ printk("Comparing int: %x with hi(%x)\n", x, *(int *)dbri->mm.ctrl);
+ if(x == (*(int *)dbri->mm.ctrl >> 16)) {
+ printk("Comp ok\n");
wake_up(&dbri->int_wait);
-}
+ }
}
break;
case D_P_19:
+ /* Pipe 19 - receive CS4215 version */
if(val != 0) {
dbri->mm.version =
reverse_bytes(val, 1) & 0xf;
__u8 * buffer, unsigned long count)
{
struct dbri *dbri = (struct dbri *)drv->private;
- int val, n = 0;
+ int val, n;
- /* XXX - This routine can be called via interrupt. If DBRI
- * was cmdlocked, that would cause a sleep, which would be
- * scheduling in an interrupt, and that's not allowed
- *
- * Fortunately, there's nothing else talking to our DBRI (yet),
- * so this isn't a problem (yet)
- */
+ if (count > (1 << 14) - 1) {
+ printk("dbri_start_output called with count=%d; truncated", count);
+ count = (1 << 14) - 1;
+ }
- dbri_cmdlock(dbri);
+ n = dbri_cmdlock(dbri);
dbri->mm.td.flags = DBRI_TD_F | DBRI_TD_B | DBRI_TD_D | DBRI_TD_CNT(count);
dbri->mm.td.ba = (__u32) buffer;
dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
dbri->cmd[n++] = (__u32)&dbri->mm.td;
- dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, WAIT_INTR1);
-
- dbri->regs->reg8 = (int)dbri->cmd;
-
output_callback_arg = drv;
+
+ dbri_cmdsend(dbri, n);
}
static void dbri_stop_output(struct sparcaudio_driver *drv)
};
+/*
+****************************************************************************
+************************** ISDN (Hisax) Interface **************************
+****************************************************************************
+*/
+
+
+int dbri_get_irqnum(int dev)
+{
+ struct dbri *dbri;
+
+ if (dev >= num_drivers) {
+ return(0);
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ /* On the sparc, the cpu's irq number is only part of the "irq" */
+ return (dbri->irq & NR_IRQS);
+}
+
+int dbri_get_liu_state(int dev)
+{
+ struct dbri *dbri;
+
+ if (dev >= num_drivers) {
+ return(0);
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ return dbri->liu_state;
+}
+
+void dbri_liu_init(int dev, void (*callback)(void *), void *callback_arg)
+{
+ struct dbri *dbri;
+
+ if (dev >= num_drivers) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ /* Set callback for LIU state change */
+ dbri->liu_callback = callback;
+ dbri->liu_callback_arg = callback_arg;
+
+ dbri_isdn_init(dbri);
+}
+
+void dbri_liu_activate(int dev, int priority)
+{
+ struct dbri *dbri;
+ int n, val;
+
+ if (dev >= num_drivers) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ n = dbri_cmdlock(dbri);
+
+ /* Turn on the ISDN TE interface and request activation */
+ val = D_NT_IRM_IMM | D_NT_IRM_EN | D_NT_ACT;
+ dbri->cmd[n++] = DBRI_CMD(D_TE, 0, val);
+
+ dbri_cmdsend(dbri, n);
+
+ /* Activate the interface */
+ dbri->regs->reg0 |= D_T;
+}
+
+void dbri_liu_deactivate(int dev)
+{
+ struct dbri *dbri;
+
+ if (dev >= num_drivers) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ /* Turn off the ISDN TE interface */
+ dbri->regs->reg0 &= ~D_T;
+}
+
+void dbri_dxmit(int dev, __u8 *buffer, unsigned int count,
+ void (*callback)(void *, int), void *callback_arg)
+{
+ struct dbri *dbri;
+ int n, val;
+
+ if (dev >= num_drivers) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ if (count > (1 << 14) - 1) {
+ printk("dbri_dxmit called with count=%d; truncated", count);
+ count = (1 << 14) - 1;
+ }
+
+ n = dbri_cmdlock(dbri);
+
+ /* XXX - Shouldn't I check to make sure D.td isn't is use? */
+
+ dbri->D.td.flags = DBRI_TD_F | DBRI_TD_B | DBRI_TD_CNT(count) | DBRI_TD_I;
+ dbri->D.td.ba = (__u32) buffer;
+ dbri->D.td.nda = 0;
+ dbri->D.td.status = 0;
+
+ /* Pipe 1 is D channel transmit */
+ val = D_SDP_HDLC_D|D_SDP_TO_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_1);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = (__u32)&dbri->D.td;
+
+ dbri->D.output_callback = callback;
+ dbri->D.output_callback_arg = callback_arg;
+
+ dbri_cmdsend(dbri, n);
+}
+
+void dbri_drecv(int dev, __u8 *buffer, unsigned int size,
+ void (*callback)(void *, int, unsigned int),
+ void *callback_arg)
+{
+ struct dbri *dbri;
+ int n, val;
+
+ if (dev >= num_drivers) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ if (size > (1 << 14) - 1) {
+ printk("dbri_drecv called with size=%d; truncated", size);
+ size = (1 << 14) - 1;
+ }
+
+ /* Make sure size is a multiple of four */
+ size &= ~3;
+
+ n = dbri_cmdlock(dbri);
+
+ /* XXX - Shouldn't I check to make sure D.rd isn't is use? */
+
+ dbri->D.rd.flags = 0;
+ dbri->D.rd.ba = (__u32) buffer;
+ dbri->D.rd.nda = 0;
+ dbri->D.rd.status = DBRI_RD_B | DBRI_RD_BCNT(size);
+
+ /* Pipe 0 is D channel receive */
+ val = D_SDP_HDLC|D_SDP_FROM_SER|D_SDP_C|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_0);
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = (__u32)&dbri->D.rd;
+
+ dbri_cmdsend(dbri, n);
+
+ dbri->D.input_callback = callback;
+ dbri->D.input_callback_arg = callback_arg;
+}
+
+int dbri_bopen(int dev, unsigned int chan,
+ int hdlcmode, u_char xmit_idle_char)
+{
+ struct dbri *dbri;
+ int n, val;
+
+ if (dev >= num_drivers || chan > 1) {
+ return -1;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ if (hdlcmode) {
+
+ return -1;
+
+ /* Pipe 8/9: receive B1/B2 channel */
+ dbri->B[chan].recvSDP = D_SDP_HDLC|D_SDP_FROM_SER|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_8+chan);
+
+ /* Pipe 10/11: transmit B1/B2 channel */
+ dbri->B[chan].xmitSDP = D_SDP_HDLC|D_SDP_TO_SER|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_10+chan);
+
+ } else { /* !hdlcmode means transparent */
+
+ /* Pipe 8/9: receive B1/B2 channel */
+ dbri->B[chan].recvSDP = D_SDP_MEM|D_SDP_FROM_SER|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_8+chan);
+
+ /* Pipe 10/11: transmit B1/B2 channel */
+ dbri->B[chan].xmitSDP = D_SDP_MEM|D_SDP_TO_SER|D_SDP_P|D_SDP_LSB|D_PIPE(D_P_10+chan);
+
+ }
+
+ n = dbri_cmdlock(dbri);
+
+ /* Pipe 8/9: receive B1/B2 channel */
+ val = dbri->B[chan].recvSDP | D_SDP_C;
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+ /* Pipe 10/11: transmit B1/B2 channel */
+ val = dbri->B[chan].xmitSDP | D_SDP_C;
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = 0;
+
+ dbri->B[chan].output_callback = NULL;
+ dbri->B[chan].input_callback = NULL;
+
+ dbri_cmdsend(dbri, n);
+
+ return 0;
+}
+
+void dbri_bclose(int dev, unsigned int chan)
+{
+ struct dbri *dbri;
+
+ if (dev >= num_drivers || chan > 1) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ dbri->B[chan].output_callback = NULL;
+ dbri->B[chan].input_callback = NULL;
+}
+
+void dbri_bxmit(int dev, unsigned int chan,
+ __u8 *buffer, unsigned long count,
+ void (*callback)(void *, int),
+ void *callback_arg)
+{
+ struct dbri *dbri;
+ int n, val;
+
+ if (dev >= num_drivers || chan > 1) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ if (count > (1 << 14) - 1) {
+ printk("dbri_bxmit called with count=%ld; truncated", count);
+ count = (1 << 14) - 1;
+ }
+
+ n = dbri_cmdlock(dbri);
+
+ /* XXX - Shouldn't I check to make sure td isn't is use? */
+
+ dbri->B[chan].td.flags = DBRI_TD_F | DBRI_TD_B | DBRI_TD_CNT(count);
+ dbri->B[chan].td.ba = (__u32) buffer;
+ dbri->B[chan].td.nda = 0;
+ dbri->B[chan].td.status = 0;
+
+ /* Pipe 10/11 is B1/B2 channel transmit */
+ val = dbri->B[chan].xmitSDP;
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = (__u32)&dbri->B[chan].td;
+
+ dbri->B[chan].output_callback = callback;
+ dbri->B[chan].output_callback_arg = callback_arg;
+
+ dbri_cmdsend(dbri, n);
+}
+
+void dbri_brecv(int dev, unsigned int chan,
+ __u8 *buffer, unsigned long size,
+ void (*callback)(void *, int, unsigned int),
+ void *callback_arg)
+{
+ struct dbri *dbri;
+ int n, val;
+
+ if (dev >= num_drivers || chan > 1) {
+ return;
+ }
+
+ dbri = (struct dbri *) drivers[dev].private;
+
+ if (size > (1 << 14) - 1) {
+ printk("dbri_brecv called with size=%ld; truncated", size);
+ size = (1 << 14) - 1;
+ }
+
+ /* Make sure size is a multiple of four */
+ size &= ~3;
+
+ n = dbri_cmdlock(dbri);
+
+ /* XXX - Shouldn't I check to make sure RD isn't is use? */
+
+ dbri->B[chan].rd.flags = 0;
+ dbri->B[chan].rd.ba = (__u32) buffer;
+ dbri->B[chan].rd.nda = 0;
+ dbri->B[chan].rd.status = DBRI_RD_B | DBRI_RD_BCNT(size);
+
+ /* Pipe 8/9 is B1/B2 channel receive */
+ val = dbri->B[chan].recvSDP;
+ dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+ dbri->cmd[n++] = (__u32)&dbri->B[chan].rd;
+
+ dbri_cmdsend(dbri, n);
+
+ dbri->B[chan].input_callback = callback;
+ dbri->B[chan].input_callback_arg = callback_arg;
+}
+
+struct foreign_interface dbri_foreign_interface = {
+ dbri_get_irqnum,
+ dbri_get_liu_state,
+ dbri_liu_init,
+ dbri_liu_activate,
+ dbri_liu_deactivate,
+ dbri_dxmit,
+ dbri_drecv,
+ dbri_bopen,
+ dbri_bclose,
+ dbri_bxmit,
+ dbri_brecv
+};
+EXPORT_SYMBOL(dbri_foreign_interface);
+
+/*
+****************************************************************************
+**************************** Initialization ********************************
+****************************************************************************
+*/
+
+
static int dbri_attach(struct sparcaudio_driver *drv,
struct linux_sbus_device *sdev)
{
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
- * c-indent-level: 4
+ * c-indent-level: 8
* c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
__u32 status;
};
+struct dbri_channel {
+ struct dbri_mem td;
+ struct dbri_mem rd;
+ unsigned int recvSDP;
+ unsigned int xmitSDP;
+ void (*output_callback)(void *, int);
+ void *output_callback_arg;
+ void (*input_callback)(void *, int, unsigned int);
+ void *input_callback_arg;
+};
+
#include "cs4215.h"
/* This structure holds the information for both chips (DBRI & CS4215) */
struct wait_queue *wait, *int_wait; /* Where to sleep if busy */
struct audio_info perchip_info;
+
+ /* Track ISDN LIU and notify changes */
+ int liu_state;
+ void (*liu_callback)(void *);
+ void *liu_callback_arg;
+
+ /* Callback routines and descriptors for ISDN channels */
+ struct dbri_channel D;
+ struct dbri_channel B[2];
};
/* Special bits for some commands */
-#define D_PIPE(v) (v<<0) /* Pipe Nr: 0-15 long, 16-21 short */
+#define D_PIPE(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */
/* Setup Data Pipe */
/* IRM */
#define D_DTS_VO (1<<16) /* Valid Output Time-Slot Descriptor */
#define D_DTS_INS (1<<15) /* Insert Time Slot */
#define D_DTS_DEL (0<<15) /* Delete Time Slot */
-#define D_DTS_PRVIN(v) (v<<10) /* Previous In Pipe */
-#define D_DTS_PRVOUT(v) (v<<5) /* Previous Out Pipe */
+#define D_DTS_PRVIN(v) ((v)<<10) /* Previous In Pipe */
+#define D_DTS_PRVOUT(v) ((v)<<5) /* Previous Out Pipe */
/* Time Slot defines */
#define D_TS_LEN(v) (v<<24) /* Number of bits in this time slot */
#define D_TS_MONITOR (2<<10) /* Monitor pipe */
#define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */
#define D_TS_ANCHOR (7<<10) /* Starting short pipes */
-#define D_TS_MON(v) (v<<5) /* Monitor Pipe */
-#define D_TS_NEXT(v) (v<<0) /* Pipe Nr: 0-15 long, 16-21 short */
+#define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */
+#define D_TS_NEXT(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */
/* Concentration Highway Interface Modes */
#define D_CHI_CHICM(v) (v<<16) /* Clock mode */
#define DBRI_TD_UNR (1<<3) /* Underrun: transmitter is out of data */
#define DBRI_TD_ABT (1<<2) /* Abort: frame aborted */
#define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */
+#define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */
/* Receive descriptor defines */
#define DBRI_RD_F (1<<31) /* End of Frame */
#define DBRI_RD_C (1<<30) /* Completed buffer */
#define DBRI_RD_B (1<<15) /* Final interrupt */
#define DBRI_RD_M (1<<14) /* Marker interrupt */
-#define DBRI_RD_CNT(v) (v<<16) /* Number of valid bytes in the buffer */
#define DBRI_RD_BCNT(v) v /* Buffer size */
#define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */
#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte recieved */
#define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */
#define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */
+#define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */
+#define DBRI_RD_CNT(v) ((v>>16)&0x1fff) /* Number of valid bytes in the buffer */
#endif /* _DBRI_H_ */
else # !eq($(ARCH),sparc64)
ifeq ($(CONFIG_PCI),y)
-O_OBJS += su32.o pcikbd.o
+O_OBJS += su.o pcikbd.o
endif
endif # !eq($(ARCH),sparc64)
-/* $Id: envctrl.c,v 1.8 1998/08/26 10:29:40 davem Exp $
+/* $Id: envctrl.c,v 1.9 1998/11/06 07:38:20 ecd Exp $
* envctrl.c: Temperature and Fan monitoring on Machines providing it.
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
unsigned char dummy;
unsigned char stat;
int error = -ENODEV;
- int count = -1;
-
- if (len == 0)
- return 0;
+ int count = 0;
i2c->data = (dev << 1) | I2C_READ;
if (stat & STATUS_LRB)
goto stop;
+
error = 0;
- if (count == (len - 2))
- goto final;
+ if (len == 0) {
+ count--;
+ break;
+ }
- if (++count > 0) {
+ if (count == (len - 1))
+ break;
+
+ if (count++ > 0) {
error = PUT_DATA(&i2c->data, buffer++, user);
if (error)
- goto final;
+ break;
} else
dummy = i2c->data;
} while (1);
-final:
i2c->csr = CONTROL_ES0;
- if (!error && (++count > 0))
+ if (!error && (count++ > 0))
error = PUT_DATA(&i2c->data, buffer++, user);
else
dummy = i2c->data;
stop:
i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
- if (!error && (++count > 0))
+ if (!error && (count++ > 0))
error = PUT_DATA(&i2c->data, buffer++, user);
else
dummy = i2c->data;
if (error)
return error;
- return count;
+ return count - 1;
}
static int
udelay(1);
if (stat & STATUS_LRB)
- goto stop;
+ break;
+
error = count;
if (count == len)
- goto stop;
+ break;
error = GET_DATA(&i2c->data, buffer++, user);
if (error)
- goto stop;
+ break;
count++;
} while (1);
-stop:
i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
return error;
}
int count = 0;
for (dev = 1; dev < 128; dev++) {
- if (i2c_write(dev, 0, 0, 0) == 0) {
+ if (i2c_read(dev, 0, 0, 0) == 0) {
#ifdef DEBUG_BUS_SCAN
int i;
for (i = 0; i < NR_DEVMAP; i++)
count++;
}
}
- return count ? 0 : -ENODEV;
+ if (!count) {
+ printk("%s: no devices found\n", __FUNCTION__);
+ return -ENODEV;
+ }
+ return 0;
}
static loff_t
#ifdef CONFIG_PCI
struct linux_ebus *ebus;
struct linux_ebus_device *edev = 0;
+ int err;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
}
}
ebus_done:
- if (!edev)
+ if (!edev) {
+ printk("%s: ebus device not found\n", __FUNCTION__);
return -ENODEV;
+ }
if (check_region(edev->base_address[0], sizeof(*i2c))) {
printk("%s: Can't get region %lx, %d\n",
release_region((unsigned long)i2c, sizeof(*i2c));
}
- return i2c_scan_bus();
+ err = i2c_scan_bus();
+ if (err)
+ release_region((unsigned long)i2c, sizeof(*i2c));
+ return err;
#else
return -ENODEV;
#endif
-/* $Id: pcikbd.c,v 1.23 1998/10/07 11:35:24 jj Exp $
+/* $Id: pcikbd.c,v 1.24 1998/11/08 11:15:24 davem Exp $
* pcikbd.c: Ultra/AX PC keyboard support.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
== AUX_STAT_OBF)
pcimouse_inb(pcimouse_iobase + KBD_DATA_REG);
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout((5*HZ + 99)/100);
+ schedule_timeout((5*HZ + 99) / 100);
retries++;
}
return (retries < MAX_RETRIES);
-/* $Id: sab82532.c,v 1.26 1998/10/25 06:46:41 ecd Exp $
+/* $Id: sab82532.c,v 1.27 1998/11/08 11:15:25 davem Exp $
* sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
__initfunc(static inline void show_serial_version(void))
{
- char *revision = "$Revision: 1.26 $";
+ char *revision = "$Revision: 1.27 $";
char *version, *p;
version = strchr(revision, ' ');
-/* $Id: su.c,v 1.12 1998/10/25 04:24:52 ecd Exp $
+/* $Id: su.c,v 1.16 1998/11/14 23:02:54 ecd Exp $
* su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
kdevname(tty->device), (info->flags), serial_refcount, \
info->count,tty->count,s); \
-} while (0);
+} while (0)
#else
#define DBG_CNT(s)
#endif
};
static char *serial_name = "PCIO serial driver";
-static char *serial_version = "1.1";
+static char serial_version[16];
static DECLARE_TASK_QUEUE(tq_serial);
/*
* MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are
* connected with a gate then go to SlavIO. When IRQ4 goes tristated
- * gate gives logical one. Since we use level triggered interrupts
+ * gate outputs a logical one. Since we use level triggered interrupts
* we have lockup and watchdog reset. We cannot mask IRQ because
- * keyboard shares IRQ with us (Bob Smelik: I would not hire you).
- * P3: Assure that OUT2 never goes down.
+ * keyboard shares IRQ with us (Word has it as Bob Smelik's design).
+ * This problem is similar to what Alpha people suffer, see serial.c.
*/
if (offset == UART_MCR) value |= UART_MCR_OUT2;
*(volatile unsigned char *)(info->port + offset) = value;
icount = &info->icount;
do {
ch = serial_inp(info, UART_RX);
-
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
break;
*tty->flip.char_buf_ptr = ch;
icount->rx++;
#ifdef SERIAL_DEBUG_INTR
- printk("DR%02x:%02x...", ch, *status);
+ printk("D%02x:%02x.", ch, *status);
#endif
*tty->flip.flag_buf_ptr = 0;
if (*status & (UART_LSR_BI | UART_LSR_PE |
* should be ignored.
*/
if (*status & info->ignore_status_mask) {
- if (++ignored > 100)
+ if (++ignored > 100) {
+#ifdef SERIAL_DEBUG_INTR
+ printk("ign100..");
+#endif
break;
+ }
goto ignore_char;
}
*status &= info->read_status_mask;
ignore_char:
*status = serial_inp(info, UART_LSR);
} while (*status & UART_LSR_DR);
+#ifdef SERIAL_DEBUG_INTR
+ printk("E%02x.R%d", *status, tty->flip.count);
+#endif
tty_flip_buffer_push(tty);
}
su_sched_event(info, RS_EVENT_WRITE_WAKEUP);
#ifdef SERIAL_DEBUG_INTR
- printk("THRE...");
+ printk("T%d...", info->xmit_cnt);
#endif
if (intr_done)
*intr_done = 0;
unsigned char status;
#ifdef SERIAL_DEBUG_INTR
- printk("su_interrupt(%s)...", __irq_itoa(irq));
+ printk("su_kbd_ms_interrupt(%s)...", __irq_itoa(irq));
#endif
if (!info)
return;
int pass_counter = 0;
#ifdef SERIAL_DEBUG_INTR
- printk("su_interrupt(%s)...", __irq_itoa(irq));
+ printk("su_serial_interrupt(%s)...", __irq_itoa(irq));
#endif
info = (struct su_struct *)dev_id;
- if (!info || !info->tty)
+ if (!info || !info->tty) {
+#ifdef SERIAL_DEBUG_INTR
+ printk("strain\n");
+#endif
return;
-
+ }
+
do {
status = serial_inp(info, UART_LSR);
#ifdef SERIAL_DEBUG_INTR
transmit_chars(info, 0);
if (pass_counter++ > RS_ISR_PASS_LIMIT) {
-#if 0
- printk("rs loop break\n");
+#ifdef SERIAL_DEBUG_INTR
+ printk("rs loop break");
#endif
break; /* Prevent infinite loops */
}
* interrupt driver proper are done; the interrupt driver schedules
* them using su_sched_event(), and they get done here.
*/
-static void
-do_serial_bh(void)
+static void do_serial_bh(void)
{
run_task_queue(&tq_serial);
}
-static void
-do_softint(void *private_)
+static void do_softint(void *private_)
{
struct su_struct *info = (struct su_struct *) private_;
struct tty_struct *tty;
-
+
tty = info->tty;
if (!tty)
return;
cli();
#ifdef SERIAL_DEBUG_OPEN
- printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+ printk("starting up ttys%d (irq %s)...", info->line,
+ __irq_itoa(info->irq));
#endif
if (uart_config[info->type].flags & UART_STARTECH) {
su_flush_buffer(struct tty_struct *tty)
{
struct su_struct *info = (struct su_struct *)tty->driver_data;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->device, "su_flush_buffer"))
return;
- cli();
+ save_flags(flags); cli();
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- sti();
+ restore_flags(flags);
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
su_throttle(struct tty_struct * tty)
{
struct su_struct *info = (struct su_struct *)tty->driver_data;
+ unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
-
+
printk("throttle %s: %d....\n", tty_name(tty, buf),
tty->ldisc.chars_in_buffer(tty));
#endif
if (serial_paranoia_check(info, tty->device, "su_throttle"))
return;
-
+
if (I_IXOFF(tty))
su_send_xchar(tty, STOP_CHAR(tty));
if (tty->termios->c_cflag & CRTSCTS)
info->MCR &= ~UART_MCR_RTS;
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
static void
su_unthrottle(struct tty_struct * tty)
{
struct su_struct *info = (struct su_struct *)tty->driver_data;
+ unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
-
+
printk("unthrottle %s: %d....\n", tty_name(tty, buf),
tty->ldisc.chars_in_buffer(tty));
#endif
if (serial_paranoia_check(info, tty->device, "su_unthrottle"))
return;
-
+
if (I_IXOFF(tty)) {
if (info->x_char)
info->x_char = 0;
}
if (tty->termios->c_cflag & CRTSCTS)
info->MCR |= UART_MCR_RTS;
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
/*
{
unsigned char status;
unsigned int result;
+ unsigned long flags;
- cli();
+ save_flags(flags); cli();
status = serial_in(info, UART_LSR);
- sti();
+ restore_flags(flags);
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
return put_user(result,value);
}
{
unsigned char control, status;
unsigned int result;
+ unsigned long flags;
control = info->MCR;
- cli();
+ save_flags(flags); cli();
status = serial_in(info, UART_MSR);
- sti();
+ restore_flags(flags);
result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
#ifdef TIOCM_OUT1
{
int error;
unsigned int arg;
+ unsigned long flags;
error = get_user(arg, value);
if (error)
default:
return -EINVAL;
}
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
return 0;
}
default:
return -ENOIOCTLCMD;
}
- /* return 0; */ /* Trigger warnings is fall through by a chance. */
+ /* return 0; */ /* Trigger warnings if fall through by a chance. */
}
static void
su_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
struct su_struct *info = (struct su_struct *)tty->driver_data;
+ unsigned long flags;
if ( (tty->termios->c_cflag == old_termios->c_cflag)
&& ( RELEVANT_IFLAG(tty->termios->c_iflag)
if ((old_termios->c_cflag & CBAUD) &&
!(tty->termios->c_cflag & CBAUD)) {
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
-
+
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) &&
(tty->termios->c_cflag & CBAUD)) {
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->MCR |= UART_MCR_RTS;
}
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
/* Handle turning off CRTSCTS */
if (info->type == PORT_UNKNOWN)
return;
+ if (info->xmit_fifo_size == 0)
+ return; /* Just in case ... */
+
orig_jiffies = jiffies;
/*
* Set the check interval to be 1/5 of the estimated time to
struct su_struct *info)
{
struct wait_queue wait = { current, NULL };
- int retval;
- int do_clocal = 0;
+ int retval;
+ int do_clocal = 0, extra_count = 0;
+ unsigned long flags;
/*
* If the device is in the middle of being closed, then block
printk("block_til_ready before block: ttys%d, count = %d\n",
info->line, info->count);
#endif
- cli();
- if (!tty_hung_up_p(filp))
+ save_flags(flags); cli();
+ if (!tty_hung_up_p(filp)) {
+ extra_count = 1;
info->count--;
- sti();
+ }
+ restore_flags(flags);
info->blocked_open++;
while (1) {
- cli();
+ save_flags(flags); cli();
if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
(tty->termios->c_cflag & CBAUD))
serial_out(info, UART_MCR,
serial_inp(info, UART_MCR) |
(UART_MCR_DTR | UART_MCR_RTS));
- sti();
+ restore_flags(flags);
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
}
current->state = TASK_RUNNING;
remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
+ if (extra_count)
info->count++;
info->blocked_open--;
#ifdef SERIAL_DEBUG_OPEN
if ((line < 0) || (line >= NR_PORTS))
return -ENODEV;
info = su_table + line;
- if (serial_paranoia_check(info, tty->device, "su_open"))
- return -ENODEV;
info->count++;
+ tty->driver_data = info;
+ info->tty = tty;
+
+ if (serial_paranoia_check(info, tty->device, "su_open")) {
+ info->count--;
+ return -ENODEV;
+ }
#ifdef SERIAL_DEBUG_OPEN
printk("su_open %s%d, count = %d\n", tty->driver.name, info->line,
info->count);
#endif
- tty->driver_data = info;
- info->tty = tty;
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
if (!tmp_buf) {
static __inline__ int
line_info(char *buf, struct su_struct *info)
{
- char stat_buf[30], control, status;
- int ret;
+ char stat_buf[30], control, status;
+ int ret;
+ unsigned long flags;
ret = sprintf(buf, "%d: uart:%s port:%X irq:%s",
info->line, uart_config[info->type].name,
/*
* Figure out the current RS-232 lines
*/
- cli();
+ save_flags(flags); cli();
status = serial_in(info, UART_MSR);
control = info ? info->MCR : serial_in(info, UART_MCR);
- sti();
+ restore_flags(flags);
stat_buf[0] = 0;
stat_buf[1] = 0;
* number, and identifies which options were configured into this
* driver.
*/
-static __inline__
-void show_su_version(void)
+__initfunc(static __inline__ void show_su_version(void))
{
+ char *revision = "$Revision: 1.16 $";
+ char *version, *p;
+
+ version = strchr(revision, ' ');
+ strcpy(serial_version, ++version);
+ p = strchr(serial_version, ' ');
+ *p = '\0';
printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
}
* 0x80 is a non-existent port; which should be safe since
* include/asm/io.h also makes this assumption.
*/
- scratch = serial_in(info, UART_IER);
- su_outb(info, UART_IER, 0);
- scratch2 = serial_in(info, UART_IER);
- su_outb(info, UART_IER, scratch);
+ scratch = serial_inp(info, UART_IER);
+ serial_outp(info, UART_IER, 0);
+ scratch2 = serial_inp(info, UART_IER);
+ serial_outp(info, UART_IER, scratch);
if (scratch2) {
restore_flags(flags);
return; /* We failed; there's nothing here */
}
-#if 0 /* P3 You will never beleive but SuperIO fails this test in MrCoffee. */
- scratch = serial_in(info, UART_MCR);
- su_outb(info, UART_MCR, UART_MCR_LOOP | scratch);
- scratch2 = serial_in(info, UART_MSR);
- su_outb(info, UART_MCR, UART_MCR_LOOP | 0x0A);
- status1 = serial_in(info, UART_MSR) & 0xF0;
- su_outb(info, UART_MCR, scratch);
- su_outb(info, UART_MSR, scratch2);
+#if 0 /* P3: This does not work on MrCoffee. OUT2 is 0x80 - should work... */
+ scratch = serial_inp(info, UART_MCR);
+ serial_outp(info, UART_MCR, UART_MCR_LOOP | scratch);
+ serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A);
+ status1 = serial_inp(info, UART_MSR) & 0xF0;
+ serial_outp(info, UART_MCR, scratch);
if (status1 != 0x90) {
restore_flags(flags);
return;
#endif
scratch2 = serial_in(info, UART_LCR);
- su_outb(info, UART_LCR, 0xBF); /* set up for StarTech test */
- su_outb(info, UART_EFR, 0); /* EFR is the same as FCR */
- su_outb(info, UART_LCR, 0);
- su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */
+ serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */
+ serial_outp(info, UART_LCR, 0);
+ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
scratch = serial_in(info, UART_IIR) >> 6;
switch (scratch) {
case 0:
}
if (info->type == PORT_16550A) {
/* Check for Startech UART's */
- su_outb(info, UART_LCR, scratch2 | UART_LCR_DLAB);
- if (su_inb(info, UART_EFR) == 0) {
+ serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB);
+ if (serial_in(info, UART_EFR) == 0) {
info->type = PORT_16650;
} else {
- su_outb(info, UART_LCR, 0xBF);
- if (su_inb(info, UART_EFR) == 0)
+ serial_outp(info, UART_LCR, 0xBF);
+ if (serial_in(info, UART_EFR) == 0)
info->type = PORT_16650V2;
}
}
if (info->type == PORT_16550A) {
/* Check for TI 16750 */
- su_outb(info, UART_LCR, scratch2 | UART_LCR_DLAB);
- su_outb(info, UART_FCR,
+ serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB);
+ serial_outp(info, UART_FCR,
UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- scratch = su_inb(info, UART_IIR) >> 5;
+ scratch = serial_in(info, UART_IIR) >> 5;
if (scratch == 7) {
- su_outb(info, UART_LCR, 0);
- su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO);
- scratch = su_inb(info, UART_IIR) >> 5;
+ serial_outp(info, UART_LCR, 0);
+ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+ scratch = serial_in(info, UART_IIR) >> 5;
if (scratch == 6)
info->type = PORT_16750;
}
- su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
}
- su_outb(info, UART_LCR, scratch2);
+ serial_outp(info, UART_LCR, scratch2);
if (info->type == PORT_16450) {
- scratch = su_inb(info, UART_SCR);
- su_outb(info, UART_SCR, 0xa5);
- status1 = su_inb(info, UART_SCR);
- su_outb(info, UART_SCR, 0x5a);
- status2 = su_inb(info, UART_SCR);
- su_outb(info, UART_SCR, scratch);
+ scratch = serial_in(info, UART_SCR);
+ serial_outp(info, UART_SCR, 0xa5);
+ status1 = serial_in(info, UART_SCR);
+ serial_outp(info, UART_SCR, 0x5a);
+ status2 = serial_in(info, UART_SCR);
+ serial_outp(info, UART_SCR, scratch);
if ((status1 != 0xa5) || (status2 != 0x5a))
info->type = PORT_8250;
/*
* Reset the UART.
*/
- su_outb(info, UART_MCR, 0x00);
- su_outb(info, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
- su_inb(info, UART_RX);
+ serial_outp(info, UART_MCR, 0x00);
+ serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT));
+ (void)serial_in(info, UART_RX);
+ serial_outp(info, UART_IER, 0x00);
restore_flags(flags);
}
-/* $Id: zs.c,v 1.31 1998/10/07 11:35:29 jj Exp $
+/* $Id: zs.c,v 1.32 1998/11/08 11:15:29 davem Exp $
* zs.c: Zilog serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.31 $";
+ char *revision = "$Revision: 1.32 $";
char *version, *p;
version = strchr(revision, ' ');
(SDptr->type != TYPE_ROM ||
strncmp(SDptr->vendor, "TOSHIBA", 7))) {
build_wide_nego_msg(esp, 16);
- esp->config3[SCptr->target] |= ESP_CONFIG3_EWIDE;
SDptr->wide = 1;
esp->wnip = 1;
goto after_nego_msg_built;
# Each configuration option enables a list of files.
obj-$(CONFIG_SOUND) += soundcore.o
-
-ifeq ($(ARCH),m68k)
-
-obj-$(CONFIG_DMASOUND) += dmasound.o
-
-else
-
-ifeq ($(CONFIG_PMAC),y)
-
obj-$(CONFIG_DMASOUND) += dmasound.o
-
-else
-
obj-$(CONFIG_SOUND_OSS) += sound.o
obj-$(CONFIG_SOUND_ADLIB) += adlib_card.o opl3.o
obj-$(CONFIG_SOUND_CS4232) += cs4232.o ad1848.o
obj-$(CONFIG_SOUND_ES1371) += es1371.o
obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
-endif
-endif
-
# Declare multi-part drivers.
list-multi := sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
bool 'SMB Win95 bug work-around' CONFIG_SMB_WIN95
fi
fi
-if [ "$CONFIG_IPX" != "n" ]; then
+if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then
tristate 'NCP filesystem support (to mount NetWare volumes)' CONFIG_NCP_FS
if [ "$CONFIG_NCP_FS" != "n" ]; then
source fs/ncpfs/Config.in
};
struct autofs_wait_queue {
- unsigned long wait_queue_token;
struct wait_queue *queue;
struct autofs_wait_queue *next;
+ autofs_wqt_t wait_queue_token;
/* We use the following to see what we are waiting for */
int hash;
int len;
};
struct autofs_symlink {
- int len;
char *data;
+ int len;
time_t mtime;
};
/* Queue management functions */
int autofs_wait(struct autofs_sb_info *,struct qstr *);
-int autofs_wait_release(struct autofs_sb_info *,unsigned long,int);
+int autofs_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
void autofs_catatonic_mode(struct autofs_sb_info *);
#ifdef DEBUG
switch(cmd) {
case AUTOFS_IOC_READY: /* Wait queue: go ahead and retry */
- return autofs_wait_release(sbi,arg,0);
+ return autofs_wait_release(sbi,(autofs_wqt_t)arg,0);
case AUTOFS_IOC_FAIL: /* Wait queue: fail with ENOENT */
- return autofs_wait_release(sbi,arg,-ENOENT);
+ return autofs_wait_release(sbi,(autofs_wqt_t)arg,-ENOENT);
case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
autofs_catatonic_mode(sbi);
return 0;
/* We make this a static variable rather than a part of the superblock; it
is better if we don't reassign numbers easily even across filesystems */
-static int autofs_next_wait_queue = 1;
+static autofs_wqt_t autofs_next_wait_queue = 1;
/* These are the signals we allow interrupting a pending mount */
#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT))
}
-int autofs_wait_release(struct autofs_sb_info *sbi, unsigned long wait_queue_token, int status)
+int autofs_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_token, int status)
{
struct autofs_wait_queue *wq, **wql;
if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
printk("dev = %s, ino = %ld\n",
kdevname(inode->i_dev), inode->i_ino);
- panic("fat_read_inode: unable to read i-node block");
+ fat_fs_panic(sb, "fat_read_inode: unable to read i-node block");
+ return;
}
raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
[inode->i_ino & (MSDOS_DPB-1)];
if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
printk("dev = %s, ino = %ld\n",
kdevname(inode->i_dev), inode->i_ino);
- panic("msdos_write_inode: unable to read i-node block");
+ fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
+ return;
}
raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
[inode->i_ino & (MSDOS_DPB-1)];
do {
name++;
} while (*name == '/');
+ __prefix_lookup_dentry(name, lookup_flags);
base = dget(current->fs->root);
} else if (!base) {
base = dget(current->fs->pwd);
-/* $Id: namei.h,v 1.1 1996/12/13 14:48:23 jj Exp $
+/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $
* linux/include/asm-alpha/namei.h
*
* Included from linux/fs/namei.c
* Look at asm-sparc/namei.h for details.
*/
-#define __prefix_namei(retrieve_mode, name, base, buf, res_dir, res_inode, \
- last_name, last_entry, last_error) 1
+#define __prefix_lookup_dentry(name, lookup_flags) \
+ do {} while (0)
#endif /* __ALPHA_NAMEI_H */
-/*
- * linux/include/asm-i386/namei.h
+/*
+ * linux/include/asm-arm/namei.h
*
* Included from linux/fs/namei.c
*/
* Look at asm-sparc/namei.h for details.
*/
-#define __prefix_namei(retrieve_mode, name, base, buf, res_dir, res_inode, \
- last_name, last_entry, last_error) 1
+#define __prefix_lookup_dentry(name, lookup_flags) \
+ do {} while (0)
#endif /* __ASMARM_NAMEI_H */
* Look at asm-sparc/namei.h for details.
*/
-#define __prefix_namei(retrieve_mode, name, base, buf, res_dir, res_inode, \
- last_name, last_entry, last_error) 1
+#define __prefix_lookup_dentry(name, lookup_flags) \
+ do {} while (0)
#endif /* __I386_NAMEI_H */
#define __NR_sendfile 187
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
+#define __NR_mrecow 190
/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
* Look at asm-sparc/namei.h for details.
*/
-#define __prefix_lookup_dentry(name, follow_link) \
+#define __prefix_lookup_dentry(name, lookup_flags) \
do {} while (0)
#endif
*
* Included from linux/fs/namei.c
*
- * $Id: namei.h,v 1.9 1998/05/01 01:35:59 ralf Exp $
+ * $Id: namei.h,v 1.10 1998/10/28 08:13:24 jj Exp $
*/
#ifndef __ASM_MIPS_NAMEI_H
#define __ASM_MIPS_NAMEI_H
#define IRIX32_EMUL "usr/gnemul/irix/"
static inline struct dentry *
-__mips_lookup_dentry(const char *name, int follow_link)
+__mips_lookup_dentry(const char *name, int lookup_flags)
{
struct dentry *base;
return ERR_PTR(-ENOENT);
base = lookup_dentry (IRIX32_EMUL,
- dget (current->fs->root), 1);
+ dget (current->fs->root),
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
if (IS_ERR (base)) return base;
- base = lookup_dentry (name, base, follow_link);
+ base = lookup_dentry (name, base, lookup_flags);
if (IS_ERR (base)) return base;
#ifdef CONFIG_BINFMT_IRIX
-#define __prefix_lookup_dentry(name, follow_link) \
- dentry = __mips_lookup_dentry (name, follow_link); \
+#define __prefix_lookup_dentry(name, lookup_flags) \
+ dentry = __mips_lookup_dentry (name, lookup_flags); \
if (!IS_ERR (dentry)) return dentry;
#else /* !defined(CONFIG_BINFMT_IRIX) */
-#define __prefix_lookup_dentry(name, follow_link) \
+#define __prefix_lookup_dentry(name, lookup_flags) \
do {} while (0)
#endif /* !defined(CONFIG_BINFMT_IRIX) */
#define ASIZ_task_tarray_ptr 0x00000004
#define AOFF_task_wait_chldexit 0x0000008c
#define ASIZ_task_wait_chldexit 0x00000004
-#define AOFF_task_timeout 0x00000090
-#define ASIZ_task_timeout 0x00000004
-#define AOFF_task_policy 0x00000094
+#define AOFF_task_policy 0x00000090
#define ASIZ_task_policy 0x00000004
-#define AOFF_task_rt_priority 0x00000098
+#define AOFF_task_rt_priority 0x00000094
#define ASIZ_task_rt_priority 0x00000004
-#define AOFF_task_it_real_value 0x0000009c
+#define AOFF_task_it_real_value 0x00000098
#define ASIZ_task_it_real_value 0x00000004
-#define AOFF_task_it_prof_value 0x000000a0
+#define AOFF_task_it_prof_value 0x0000009c
#define ASIZ_task_it_prof_value 0x00000004
-#define AOFF_task_it_virt_value 0x000000a4
+#define AOFF_task_it_virt_value 0x000000a0
#define ASIZ_task_it_virt_value 0x00000004
-#define AOFF_task_it_real_incr 0x000000a8
+#define AOFF_task_it_real_incr 0x000000a4
#define ASIZ_task_it_real_incr 0x00000004
-#define AOFF_task_it_prof_incr 0x000000ac
+#define AOFF_task_it_prof_incr 0x000000a8
#define ASIZ_task_it_prof_incr 0x00000004
-#define AOFF_task_it_virt_incr 0x000000b0
+#define AOFF_task_it_virt_incr 0x000000ac
#define ASIZ_task_it_virt_incr 0x00000004
-#define AOFF_task_real_timer 0x000000b4
+#define AOFF_task_real_timer 0x000000b0
#define ASIZ_task_real_timer 0x00000014
-#define AOFF_task_times 0x000000c8
+#define AOFF_task_times 0x000000c4
#define ASIZ_task_times 0x00000010
-#define AOFF_task_start_time 0x000000d8
+#define AOFF_task_start_time 0x000000d4
#define ASIZ_task_start_time 0x00000004
-#define AOFF_task_per_cpu_utime 0x000000dc
+#define AOFF_task_per_cpu_utime 0x000000d8
#define ASIZ_task_per_cpu_utime 0x00000004
-#define AOFF_task_min_flt 0x000000e4
+#define AOFF_task_min_flt 0x000000e0
#define ASIZ_task_min_flt 0x00000004
-#define AOFF_task_maj_flt 0x000000e8
+#define AOFF_task_maj_flt 0x000000e4
#define ASIZ_task_maj_flt 0x00000004
-#define AOFF_task_nswap 0x000000ec
+#define AOFF_task_nswap 0x000000e8
#define ASIZ_task_nswap 0x00000004
-#define AOFF_task_cmin_flt 0x000000f0
+#define AOFF_task_cmin_flt 0x000000ec
#define ASIZ_task_cmin_flt 0x00000004
-#define AOFF_task_cmaj_flt 0x000000f4
+#define AOFF_task_cmaj_flt 0x000000f0
#define ASIZ_task_cmaj_flt 0x00000004
-#define AOFF_task_cnswap 0x000000f8
+#define AOFF_task_cnswap 0x000000f4
#define ASIZ_task_cnswap 0x00000004
-#define AOFF_task_swap_address 0x00000100
+#define AOFF_task_swap_address 0x000000fc
#define ASIZ_task_swap_address 0x00000004
-#define AOFF_task_old_maj_flt 0x00000104
+#define AOFF_task_old_maj_flt 0x00000100
#define ASIZ_task_old_maj_flt 0x00000004
-#define AOFF_task_dec_flt 0x00000108
+#define AOFF_task_dec_flt 0x00000104
#define ASIZ_task_dec_flt 0x00000004
-#define AOFF_task_swap_cnt 0x0000010c
+#define AOFF_task_swap_cnt 0x00000108
#define ASIZ_task_swap_cnt 0x00000004
-#define AOFF_task_uid 0x00000110
+#define AOFF_task_uid 0x0000010c
#define ASIZ_task_uid 0x00000002
-#define AOFF_task_euid 0x00000112
+#define AOFF_task_euid 0x0000010e
#define ASIZ_task_euid 0x00000002
-#define AOFF_task_suid 0x00000114
+#define AOFF_task_suid 0x00000110
#define ASIZ_task_suid 0x00000002
-#define AOFF_task_fsuid 0x00000116
+#define AOFF_task_fsuid 0x00000112
#define ASIZ_task_fsuid 0x00000002
-#define AOFF_task_gid 0x00000118
+#define AOFF_task_gid 0x00000114
#define ASIZ_task_gid 0x00000002
-#define AOFF_task_egid 0x0000011a
+#define AOFF_task_egid 0x00000116
#define ASIZ_task_egid 0x00000002
-#define AOFF_task_sgid 0x0000011c
+#define AOFF_task_sgid 0x00000118
#define ASIZ_task_sgid 0x00000002
-#define AOFF_task_fsgid 0x0000011e
+#define AOFF_task_fsgid 0x0000011a
#define ASIZ_task_fsgid 0x00000002
-#define AOFF_task_ngroups 0x00000120
+#define AOFF_task_ngroups 0x0000011c
#define ASIZ_task_ngroups 0x00000004
-#define AOFF_task_groups 0x00000124
+#define AOFF_task_groups 0x00000120
#define ASIZ_task_groups 0x00000040
-#define AOFF_task_cap_effective 0x00000164
+#define AOFF_task_cap_effective 0x00000160
#define ASIZ_task_cap_effective 0x00000004
-#define AOFF_task_cap_inheritable 0x00000168
+#define AOFF_task_cap_inheritable 0x00000164
#define ASIZ_task_cap_inheritable 0x00000004
-#define AOFF_task_cap_permitted 0x0000016c
+#define AOFF_task_cap_permitted 0x00000168
#define ASIZ_task_cap_permitted 0x00000004
-#define AOFF_task_user 0x00000170
+#define AOFF_task_user 0x0000016c
#define ASIZ_task_user 0x00000004
-#define AOFF_task_rlim 0x00000174
+#define AOFF_task_rlim 0x00000170
#define ASIZ_task_rlim 0x00000050
-#define AOFF_task_used_math 0x000001c4
+#define AOFF_task_used_math 0x000001c0
#define ASIZ_task_used_math 0x00000002
-#define AOFF_task_comm 0x000001c6
+#define AOFF_task_comm 0x000001c2
#define ASIZ_task_comm 0x00000010
-#define AOFF_task_link_count 0x000001d8
+#define AOFF_task_link_count 0x000001d4
#define ASIZ_task_link_count 0x00000004
-#define AOFF_task_tty 0x000001dc
+#define AOFF_task_tty 0x000001d8
#define ASIZ_task_tty 0x00000004
-#define AOFF_task_semundo 0x000001e0
+#define AOFF_task_semundo 0x000001dc
#define ASIZ_task_semundo 0x00000004
-#define AOFF_task_semsleeping 0x000001e4
+#define AOFF_task_semsleeping 0x000001e0
#define ASIZ_task_semsleeping 0x00000004
#define AOFF_task_tss 0x000001e8
#define ASIZ_task_tss 0x00000388
#define ASIZ_task_tarray_ptr 0x00000004
#define AOFF_task_wait_chldexit 0x0000008c
#define ASIZ_task_wait_chldexit 0x00000004
-#define AOFF_task_timeout 0x00000090
-#define ASIZ_task_timeout 0x00000004
-#define AOFF_task_policy 0x00000094
+#define AOFF_task_policy 0x00000090
#define ASIZ_task_policy 0x00000004
-#define AOFF_task_rt_priority 0x00000098
+#define AOFF_task_rt_priority 0x00000094
#define ASIZ_task_rt_priority 0x00000004
-#define AOFF_task_it_real_value 0x0000009c
+#define AOFF_task_it_real_value 0x00000098
#define ASIZ_task_it_real_value 0x00000004
-#define AOFF_task_it_prof_value 0x000000a0
+#define AOFF_task_it_prof_value 0x0000009c
#define ASIZ_task_it_prof_value 0x00000004
-#define AOFF_task_it_virt_value 0x000000a4
+#define AOFF_task_it_virt_value 0x000000a0
#define ASIZ_task_it_virt_value 0x00000004
-#define AOFF_task_it_real_incr 0x000000a8
+#define AOFF_task_it_real_incr 0x000000a4
#define ASIZ_task_it_real_incr 0x00000004
-#define AOFF_task_it_prof_incr 0x000000ac
+#define AOFF_task_it_prof_incr 0x000000a8
#define ASIZ_task_it_prof_incr 0x00000004
-#define AOFF_task_it_virt_incr 0x000000b0
+#define AOFF_task_it_virt_incr 0x000000ac
#define ASIZ_task_it_virt_incr 0x00000004
-#define AOFF_task_real_timer 0x000000b4
+#define AOFF_task_real_timer 0x000000b0
#define ASIZ_task_real_timer 0x00000014
-#define AOFF_task_times 0x000000c8
+#define AOFF_task_times 0x000000c4
#define ASIZ_task_times 0x00000010
-#define AOFF_task_start_time 0x000000d8
+#define AOFF_task_start_time 0x000000d4
#define ASIZ_task_start_time 0x00000004
-#define AOFF_task_per_cpu_utime 0x000000dc
+#define AOFF_task_per_cpu_utime 0x000000d8
#define ASIZ_task_per_cpu_utime 0x00000080
-#define AOFF_task_min_flt 0x000001dc
+#define AOFF_task_min_flt 0x000001d8
#define ASIZ_task_min_flt 0x00000004
-#define AOFF_task_maj_flt 0x000001e0
+#define AOFF_task_maj_flt 0x000001dc
#define ASIZ_task_maj_flt 0x00000004
-#define AOFF_task_nswap 0x000001e4
+#define AOFF_task_nswap 0x000001e0
#define ASIZ_task_nswap 0x00000004
-#define AOFF_task_cmin_flt 0x000001e8
+#define AOFF_task_cmin_flt 0x000001e4
#define ASIZ_task_cmin_flt 0x00000004
-#define AOFF_task_cmaj_flt 0x000001ec
+#define AOFF_task_cmaj_flt 0x000001e8
#define ASIZ_task_cmaj_flt 0x00000004
-#define AOFF_task_cnswap 0x000001f0
+#define AOFF_task_cnswap 0x000001ec
#define ASIZ_task_cnswap 0x00000004
-#define AOFF_task_swap_address 0x000001f8
+#define AOFF_task_swap_address 0x000001f4
#define ASIZ_task_swap_address 0x00000004
-#define AOFF_task_old_maj_flt 0x000001fc
+#define AOFF_task_old_maj_flt 0x000001f8
#define ASIZ_task_old_maj_flt 0x00000004
-#define AOFF_task_dec_flt 0x00000200
+#define AOFF_task_dec_flt 0x000001fc
#define ASIZ_task_dec_flt 0x00000004
-#define AOFF_task_swap_cnt 0x00000204
+#define AOFF_task_swap_cnt 0x00000200
#define ASIZ_task_swap_cnt 0x00000004
-#define AOFF_task_uid 0x00000208
+#define AOFF_task_uid 0x00000204
#define ASIZ_task_uid 0x00000002
-#define AOFF_task_euid 0x0000020a
+#define AOFF_task_euid 0x00000206
#define ASIZ_task_euid 0x00000002
-#define AOFF_task_suid 0x0000020c
+#define AOFF_task_suid 0x00000208
#define ASIZ_task_suid 0x00000002
-#define AOFF_task_fsuid 0x0000020e
+#define AOFF_task_fsuid 0x0000020a
#define ASIZ_task_fsuid 0x00000002
-#define AOFF_task_gid 0x00000210
+#define AOFF_task_gid 0x0000020c
#define ASIZ_task_gid 0x00000002
-#define AOFF_task_egid 0x00000212
+#define AOFF_task_egid 0x0000020e
#define ASIZ_task_egid 0x00000002
-#define AOFF_task_sgid 0x00000214
+#define AOFF_task_sgid 0x00000210
#define ASIZ_task_sgid 0x00000002
-#define AOFF_task_fsgid 0x00000216
+#define AOFF_task_fsgid 0x00000212
#define ASIZ_task_fsgid 0x00000002
-#define AOFF_task_ngroups 0x00000218
+#define AOFF_task_ngroups 0x00000214
#define ASIZ_task_ngroups 0x00000004
-#define AOFF_task_groups 0x0000021c
+#define AOFF_task_groups 0x00000218
#define ASIZ_task_groups 0x00000040
-#define AOFF_task_cap_effective 0x0000025c
+#define AOFF_task_cap_effective 0x00000258
#define ASIZ_task_cap_effective 0x00000004
-#define AOFF_task_cap_inheritable 0x00000260
+#define AOFF_task_cap_inheritable 0x0000025c
#define ASIZ_task_cap_inheritable 0x00000004
-#define AOFF_task_cap_permitted 0x00000264
+#define AOFF_task_cap_permitted 0x00000260
#define ASIZ_task_cap_permitted 0x00000004
-#define AOFF_task_user 0x00000268
+#define AOFF_task_user 0x00000264
#define ASIZ_task_user 0x00000004
-#define AOFF_task_rlim 0x0000026c
+#define AOFF_task_rlim 0x00000268
#define ASIZ_task_rlim 0x00000050
-#define AOFF_task_used_math 0x000002bc
+#define AOFF_task_used_math 0x000002b8
#define ASIZ_task_used_math 0x00000002
-#define AOFF_task_comm 0x000002be
+#define AOFF_task_comm 0x000002ba
#define ASIZ_task_comm 0x00000010
-#define AOFF_task_link_count 0x000002d0
+#define AOFF_task_link_count 0x000002cc
#define ASIZ_task_link_count 0x00000004
-#define AOFF_task_tty 0x000002d4
+#define AOFF_task_tty 0x000002d0
#define ASIZ_task_tty 0x00000004
-#define AOFF_task_semundo 0x000002d8
+#define AOFF_task_semundo 0x000002d4
#define ASIZ_task_semundo 0x00000004
-#define AOFF_task_semsleeping 0x000002dc
+#define AOFF_task_semsleeping 0x000002d8
#define ASIZ_task_semsleeping 0x00000004
#define AOFF_task_tss 0x000002e0
#define ASIZ_task_tss 0x00000388
#include <asm/page.h>
#include <asm/spinlock.h>
+#include <asm/pgtable.h>
/* The io-unit handles all virtual to physical address translations
* that occur between the SBUS and physical memory. Access by
#define IOUNIT_BMAPM_START IOUNIT_BMAP2_END
#define IOUNIT_BMAPM_END ((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT)
+extern __u32 iounit_map_dma_init(struct linux_sbus *, int);
+#define iounit_map_dma_finish(sbus, addr, len) mmu_release_scsi_one(addr, len, sbus)
+extern __u32 iounit_map_dma_page(__u32, void *, struct linux_sbus *);
+
#endif /* !(_SPARC_IO_UNIT_H) */
-/* $Id: namei.h,v 1.11 1998/01/15 12:58:24 jj Exp $
+/* $Id: namei.h,v 1.12 1998/10/28 08:13:42 jj Exp $
* linux/include/asm-sparc/namei.h
*
* Routines to handle famous /usr/gnemul/s*.
#define SPARC_SOL_EMUL "usr/gnemul/solaris/"
static inline struct dentry *
-__sparc_lookup_dentry(const char *name, int follow_link)
+__sparc_lookup_dentry(const char *name, int lookup_flags)
{
struct dentry *base;
char *emul;
return NULL;
}
- base = lookup_dentry (emul, dget (current->fs->root), 1);
+ base = lookup_dentry (emul,
+ dget (current->fs->root),
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
if (IS_ERR (base)) return NULL;
- base = lookup_dentry (name, base, follow_link);
+ base = lookup_dentry (name, base, lookup_flags);
if (IS_ERR (base)) return NULL;
if (!base->d_inode) {
struct dentry *fromroot;
- fromroot = lookup_dentry (name, dget (current->fs->root), follow_link);
+ fromroot = lookup_dentry (name, dget (current->fs->root), lookup_flags);
if (IS_ERR (fromroot)) return base;
return base;
}
-#define __prefix_lookup_dentry(name, follow_link) \
+#define __prefix_lookup_dentry(name, lookup_flags) \
if (current->personality) { \
- dentry = __sparc_lookup_dentry (name, follow_link); \
+ dentry = __sparc_lookup_dentry (name, lookup_flags); \
if (dentry) return dentry; \
}
#else
extern __inline__ int hard_smp_processor_id(void)
{
- int cpuid __asm__ ("g2");
+ int cpuid;
__asm__ __volatile__("mov %%o7, %%g1\n\t"
"call ___f___smp_processor_id\n\t"
- " nop\n\t" : "=r"(cpuid) : : "g1");
+ " nop\n\t"
+ "mov %%g2, %0\n\t" : "=r"(cpuid) : : "g1", "g2");
return cpuid;
}
#endif
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
-typedef struct { } rwlock_t;
-#define RW_LOCK_UNLOCKED { }
+typedef struct { volatile unsigned int lock; } rwlock_t;
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
#define read_lock(lock) do { } while(0)
#define read_unlock(lock) do { } while(0)
};
typedef struct _spinlock_debug spinlock_t;
-#define SPIN_LOCK_UNLOCKED { 0, 0 }
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0 }
#define spin_lock_init(lp) do { (lp)->owner_pc = 0; (lp)->lock = 0; } while(0)
#define spin_unlock_wait(lp) do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
};
typedef struct _rwlock_debug rwlock_t;
-#define RW_LOCK_UNLOCKED { 0, 0, {0} }
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, {0} }
extern void _do_read_lock(rwlock_t *rw, char *str);
extern void _do_read_unlock(rwlock_t *rw, char *str);
*/
typedef struct { volatile unsigned int lock; } rwlock_t;
-#define RW_LOCK_UNLOCKED { 0 }
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
/* Sort of like atomic_t's on Sparc, but even more clever.
*
#define ASIZ_task_tarray_ptr 0x00000008
#define AOFF_task_wait_chldexit 0x000000e8
#define ASIZ_task_wait_chldexit 0x00000008
-#define AOFF_task_timeout 0x000000f0
-#define ASIZ_task_timeout 0x00000008
-#define AOFF_task_policy 0x000000f8
+#define AOFF_task_policy 0x000000f0
#define ASIZ_task_policy 0x00000008
-#define AOFF_task_rt_priority 0x00000100
+#define AOFF_task_rt_priority 0x000000f8
#define ASIZ_task_rt_priority 0x00000008
-#define AOFF_task_it_real_value 0x00000108
+#define AOFF_task_it_real_value 0x00000100
#define ASIZ_task_it_real_value 0x00000008
-#define AOFF_task_it_prof_value 0x00000110
+#define AOFF_task_it_prof_value 0x00000108
#define ASIZ_task_it_prof_value 0x00000008
-#define AOFF_task_it_virt_value 0x00000118
+#define AOFF_task_it_virt_value 0x00000110
#define ASIZ_task_it_virt_value 0x00000008
-#define AOFF_task_it_real_incr 0x00000120
+#define AOFF_task_it_real_incr 0x00000118
#define ASIZ_task_it_real_incr 0x00000008
-#define AOFF_task_it_prof_incr 0x00000128
+#define AOFF_task_it_prof_incr 0x00000120
#define ASIZ_task_it_prof_incr 0x00000008
-#define AOFF_task_it_virt_incr 0x00000130
+#define AOFF_task_it_virt_incr 0x00000128
#define ASIZ_task_it_virt_incr 0x00000008
-#define AOFF_task_real_timer 0x00000138
+#define AOFF_task_real_timer 0x00000130
#define ASIZ_task_real_timer 0x00000028
-#define AOFF_task_times 0x00000160
+#define AOFF_task_times 0x00000158
#define ASIZ_task_times 0x00000020
-#define AOFF_task_start_time 0x00000180
+#define AOFF_task_start_time 0x00000178
#define ASIZ_task_start_time 0x00000008
-#define AOFF_task_per_cpu_utime 0x00000188
+#define AOFF_task_per_cpu_utime 0x00000180
#define ASIZ_task_per_cpu_utime 0x00000008
-#define AOFF_task_min_flt 0x00000198
+#define AOFF_task_min_flt 0x00000190
#define ASIZ_task_min_flt 0x00000008
-#define AOFF_task_maj_flt 0x000001a0
+#define AOFF_task_maj_flt 0x00000198
#define ASIZ_task_maj_flt 0x00000008
-#define AOFF_task_nswap 0x000001a8
+#define AOFF_task_nswap 0x000001a0
#define ASIZ_task_nswap 0x00000008
-#define AOFF_task_cmin_flt 0x000001b0
+#define AOFF_task_cmin_flt 0x000001a8
#define ASIZ_task_cmin_flt 0x00000008
-#define AOFF_task_cmaj_flt 0x000001b8
+#define AOFF_task_cmaj_flt 0x000001b0
#define ASIZ_task_cmaj_flt 0x00000008
-#define AOFF_task_cnswap 0x000001c0
+#define AOFF_task_cnswap 0x000001b8
#define ASIZ_task_cnswap 0x00000008
-#define AOFF_task_swap_address 0x000001d0
+#define AOFF_task_swap_address 0x000001c8
#define ASIZ_task_swap_address 0x00000008
-#define AOFF_task_old_maj_flt 0x000001d8
+#define AOFF_task_old_maj_flt 0x000001d0
#define ASIZ_task_old_maj_flt 0x00000008
-#define AOFF_task_dec_flt 0x000001e0
+#define AOFF_task_dec_flt 0x000001d8
#define ASIZ_task_dec_flt 0x00000008
-#define AOFF_task_swap_cnt 0x000001e8
+#define AOFF_task_swap_cnt 0x000001e0
#define ASIZ_task_swap_cnt 0x00000008
-#define AOFF_task_uid 0x000001f0
+#define AOFF_task_uid 0x000001e8
#define ASIZ_task_uid 0x00000004
-#define AOFF_task_euid 0x000001f4
+#define AOFF_task_euid 0x000001ec
#define ASIZ_task_euid 0x00000004
-#define AOFF_task_suid 0x000001f8
+#define AOFF_task_suid 0x000001f0
#define ASIZ_task_suid 0x00000004
-#define AOFF_task_fsuid 0x000001fc
+#define AOFF_task_fsuid 0x000001f4
#define ASIZ_task_fsuid 0x00000004
-#define AOFF_task_gid 0x00000200
+#define AOFF_task_gid 0x000001f8
#define ASIZ_task_gid 0x00000004
-#define AOFF_task_egid 0x00000204
+#define AOFF_task_egid 0x000001fc
#define ASIZ_task_egid 0x00000004
-#define AOFF_task_sgid 0x00000208
+#define AOFF_task_sgid 0x00000200
#define ASIZ_task_sgid 0x00000004
-#define AOFF_task_fsgid 0x0000020c
+#define AOFF_task_fsgid 0x00000204
#define ASIZ_task_fsgid 0x00000004
-#define AOFF_task_ngroups 0x00000210
+#define AOFF_task_ngroups 0x00000208
#define ASIZ_task_ngroups 0x00000004
-#define AOFF_task_groups 0x00000214
+#define AOFF_task_groups 0x0000020c
#define ASIZ_task_groups 0x00000080
-#define AOFF_task_cap_effective 0x00000294
+#define AOFF_task_cap_effective 0x0000028c
#define ASIZ_task_cap_effective 0x00000004
-#define AOFF_task_cap_inheritable 0x00000298
+#define AOFF_task_cap_inheritable 0x00000290
#define ASIZ_task_cap_inheritable 0x00000004
-#define AOFF_task_cap_permitted 0x0000029c
+#define AOFF_task_cap_permitted 0x00000294
#define ASIZ_task_cap_permitted 0x00000004
-#define AOFF_task_user 0x000002a0
+#define AOFF_task_user 0x00000298
#define ASIZ_task_user 0x00000008
-#define AOFF_task_rlim 0x000002a8
+#define AOFF_task_rlim 0x000002a0
#define ASIZ_task_rlim 0x000000a0
-#define AOFF_task_used_math 0x00000348
+#define AOFF_task_used_math 0x00000340
#define ASIZ_task_used_math 0x00000002
-#define AOFF_task_comm 0x0000034a
+#define AOFF_task_comm 0x00000342
#define ASIZ_task_comm 0x00000010
-#define AOFF_task_link_count 0x0000035c
+#define AOFF_task_link_count 0x00000354
#define ASIZ_task_link_count 0x00000004
-#define AOFF_task_tty 0x00000360
+#define AOFF_task_tty 0x00000358
#define ASIZ_task_tty 0x00000008
-#define AOFF_task_semundo 0x00000368
+#define AOFF_task_semundo 0x00000360
#define ASIZ_task_semundo 0x00000008
-#define AOFF_task_semsleeping 0x00000370
+#define AOFF_task_semsleeping 0x00000368
#define ASIZ_task_semsleeping 0x00000008
-#define AOFF_task_tss 0x00000380
+#define AOFF_task_tss 0x00000370
#define ASIZ_task_tss 0x00000470
-#define AOFF_task_fs 0x000007f0
+#define AOFF_task_fs 0x000007e0
#define ASIZ_task_fs 0x00000008
-#define AOFF_task_files 0x000007f8
+#define AOFF_task_files 0x000007e8
#define ASIZ_task_files 0x00000008
-#define AOFF_task_mm 0x00000800
+#define AOFF_task_mm 0x000007f0
#define ASIZ_task_mm 0x00000008
-#define AOFF_task_sigmask_lock 0x00000808
+#define AOFF_task_sigmask_lock 0x000007f8
#define ASIZ_task_sigmask_lock 0x00000001
-#define AOFF_task_sig 0x00000810
+#define AOFF_task_sig 0x00000800
#define ASIZ_task_sig 0x00000008
-#define AOFF_task_signal 0x00000818
+#define AOFF_task_signal 0x00000808
#define ASIZ_task_signal 0x00000008
-#define AOFF_task_blocked 0x00000820
+#define AOFF_task_blocked 0x00000810
#define ASIZ_task_blocked 0x00000008
-#define AOFF_task_sigqueue 0x00000828
+#define AOFF_task_sigqueue 0x00000818
#define ASIZ_task_sigqueue 0x00000008
-#define AOFF_task_sigqueue_tail 0x00000830
+#define AOFF_task_sigqueue_tail 0x00000820
#define ASIZ_task_sigqueue_tail 0x00000008
-#define AOFF_task_sas_ss_sp 0x00000838
+#define AOFF_task_sas_ss_sp 0x00000828
#define ASIZ_task_sas_ss_sp 0x00000008
-#define AOFF_task_sas_ss_size 0x00000840
+#define AOFF_task_sas_ss_size 0x00000830
#define ASIZ_task_sas_ss_size 0x00000008
-#define ASIZ_task 0x00000850
+#define ASIZ_task 0x00000840
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_cache 0x00000008
#define ASIZ_task_tarray_ptr 0x00000008
#define AOFF_task_wait_chldexit 0x000000e8
#define ASIZ_task_wait_chldexit 0x00000008
-#define AOFF_task_timeout 0x000000f0
-#define ASIZ_task_timeout 0x00000008
-#define AOFF_task_policy 0x000000f8
+#define AOFF_task_policy 0x000000f0
#define ASIZ_task_policy 0x00000008
-#define AOFF_task_rt_priority 0x00000100
+#define AOFF_task_rt_priority 0x000000f8
#define ASIZ_task_rt_priority 0x00000008
-#define AOFF_task_it_real_value 0x00000108
+#define AOFF_task_it_real_value 0x00000100
#define ASIZ_task_it_real_value 0x00000008
-#define AOFF_task_it_prof_value 0x00000110
+#define AOFF_task_it_prof_value 0x00000108
#define ASIZ_task_it_prof_value 0x00000008
-#define AOFF_task_it_virt_value 0x00000118
+#define AOFF_task_it_virt_value 0x00000110
#define ASIZ_task_it_virt_value 0x00000008
-#define AOFF_task_it_real_incr 0x00000120
+#define AOFF_task_it_real_incr 0x00000118
#define ASIZ_task_it_real_incr 0x00000008
-#define AOFF_task_it_prof_incr 0x00000128
+#define AOFF_task_it_prof_incr 0x00000120
#define ASIZ_task_it_prof_incr 0x00000008
-#define AOFF_task_it_virt_incr 0x00000130
+#define AOFF_task_it_virt_incr 0x00000128
#define ASIZ_task_it_virt_incr 0x00000008
-#define AOFF_task_real_timer 0x00000138
+#define AOFF_task_real_timer 0x00000130
#define ASIZ_task_real_timer 0x00000028
-#define AOFF_task_times 0x00000160
+#define AOFF_task_times 0x00000158
#define ASIZ_task_times 0x00000020
-#define AOFF_task_start_time 0x00000180
+#define AOFF_task_start_time 0x00000178
#define ASIZ_task_start_time 0x00000008
-#define AOFF_task_per_cpu_utime 0x00000188
+#define AOFF_task_per_cpu_utime 0x00000180
#define ASIZ_task_per_cpu_utime 0x00000100
-#define AOFF_task_min_flt 0x00000388
+#define AOFF_task_min_flt 0x00000380
#define ASIZ_task_min_flt 0x00000008
-#define AOFF_task_maj_flt 0x00000390
+#define AOFF_task_maj_flt 0x00000388
#define ASIZ_task_maj_flt 0x00000008
-#define AOFF_task_nswap 0x00000398
+#define AOFF_task_nswap 0x00000390
#define ASIZ_task_nswap 0x00000008
-#define AOFF_task_cmin_flt 0x000003a0
+#define AOFF_task_cmin_flt 0x00000398
#define ASIZ_task_cmin_flt 0x00000008
-#define AOFF_task_cmaj_flt 0x000003a8
+#define AOFF_task_cmaj_flt 0x000003a0
#define ASIZ_task_cmaj_flt 0x00000008
-#define AOFF_task_cnswap 0x000003b0
+#define AOFF_task_cnswap 0x000003a8
#define ASIZ_task_cnswap 0x00000008
-#define AOFF_task_swap_address 0x000003c0
+#define AOFF_task_swap_address 0x000003b8
#define ASIZ_task_swap_address 0x00000008
-#define AOFF_task_old_maj_flt 0x000003c8
+#define AOFF_task_old_maj_flt 0x000003c0
#define ASIZ_task_old_maj_flt 0x00000008
-#define AOFF_task_dec_flt 0x000003d0
+#define AOFF_task_dec_flt 0x000003c8
#define ASIZ_task_dec_flt 0x00000008
-#define AOFF_task_swap_cnt 0x000003d8
+#define AOFF_task_swap_cnt 0x000003d0
#define ASIZ_task_swap_cnt 0x00000008
-#define AOFF_task_uid 0x000003e0
+#define AOFF_task_uid 0x000003d8
#define ASIZ_task_uid 0x00000004
-#define AOFF_task_euid 0x000003e4
+#define AOFF_task_euid 0x000003dc
#define ASIZ_task_euid 0x00000004
-#define AOFF_task_suid 0x000003e8
+#define AOFF_task_suid 0x000003e0
#define ASIZ_task_suid 0x00000004
-#define AOFF_task_fsuid 0x000003ec
+#define AOFF_task_fsuid 0x000003e4
#define ASIZ_task_fsuid 0x00000004
-#define AOFF_task_gid 0x000003f0
+#define AOFF_task_gid 0x000003e8
#define ASIZ_task_gid 0x00000004
-#define AOFF_task_egid 0x000003f4
+#define AOFF_task_egid 0x000003ec
#define ASIZ_task_egid 0x00000004
-#define AOFF_task_sgid 0x000003f8
+#define AOFF_task_sgid 0x000003f0
#define ASIZ_task_sgid 0x00000004
-#define AOFF_task_fsgid 0x000003fc
+#define AOFF_task_fsgid 0x000003f4
#define ASIZ_task_fsgid 0x00000004
-#define AOFF_task_ngroups 0x00000400
+#define AOFF_task_ngroups 0x000003f8
#define ASIZ_task_ngroups 0x00000004
-#define AOFF_task_groups 0x00000404
+#define AOFF_task_groups 0x000003fc
#define ASIZ_task_groups 0x00000080
-#define AOFF_task_cap_effective 0x00000484
+#define AOFF_task_cap_effective 0x0000047c
#define ASIZ_task_cap_effective 0x00000004
-#define AOFF_task_cap_inheritable 0x00000488
+#define AOFF_task_cap_inheritable 0x00000480
#define ASIZ_task_cap_inheritable 0x00000004
-#define AOFF_task_cap_permitted 0x0000048c
+#define AOFF_task_cap_permitted 0x00000484
#define ASIZ_task_cap_permitted 0x00000004
-#define AOFF_task_user 0x00000490
+#define AOFF_task_user 0x00000488
#define ASIZ_task_user 0x00000008
-#define AOFF_task_rlim 0x00000498
+#define AOFF_task_rlim 0x00000490
#define ASIZ_task_rlim 0x000000a0
-#define AOFF_task_used_math 0x00000538
+#define AOFF_task_used_math 0x00000530
#define ASIZ_task_used_math 0x00000002
-#define AOFF_task_comm 0x0000053a
+#define AOFF_task_comm 0x00000532
#define ASIZ_task_comm 0x00000010
-#define AOFF_task_link_count 0x0000054c
+#define AOFF_task_link_count 0x00000544
#define ASIZ_task_link_count 0x00000004
-#define AOFF_task_tty 0x00000550
+#define AOFF_task_tty 0x00000548
#define ASIZ_task_tty 0x00000008
-#define AOFF_task_semundo 0x00000558
+#define AOFF_task_semundo 0x00000550
#define ASIZ_task_semundo 0x00000008
-#define AOFF_task_semsleeping 0x00000560
+#define AOFF_task_semsleeping 0x00000558
#define ASIZ_task_semsleeping 0x00000008
-#define AOFF_task_tss 0x00000570
+#define AOFF_task_tss 0x00000560
#define ASIZ_task_tss 0x00000470
-#define AOFF_task_fs 0x000009e0
+#define AOFF_task_fs 0x000009d0
#define ASIZ_task_fs 0x00000008
-#define AOFF_task_files 0x000009e8
+#define AOFF_task_files 0x000009d8
#define ASIZ_task_files 0x00000008
-#define AOFF_task_mm 0x000009f0
+#define AOFF_task_mm 0x000009e0
#define ASIZ_task_mm 0x00000008
-#define AOFF_task_sigmask_lock 0x000009f8
+#define AOFF_task_sigmask_lock 0x000009e8
#define ASIZ_task_sigmask_lock 0x00000001
-#define AOFF_task_sig 0x00000a00
+#define AOFF_task_sig 0x000009f0
#define ASIZ_task_sig 0x00000008
-#define AOFF_task_signal 0x00000a08
+#define AOFF_task_signal 0x000009f8
#define ASIZ_task_signal 0x00000008
-#define AOFF_task_blocked 0x00000a10
+#define AOFF_task_blocked 0x00000a00
#define ASIZ_task_blocked 0x00000008
-#define AOFF_task_sigqueue 0x00000a18
+#define AOFF_task_sigqueue 0x00000a08
#define ASIZ_task_sigqueue 0x00000008
-#define AOFF_task_sigqueue_tail 0x00000a20
+#define AOFF_task_sigqueue_tail 0x00000a10
#define ASIZ_task_sigqueue_tail 0x00000008
-#define AOFF_task_sas_ss_sp 0x00000a28
+#define AOFF_task_sas_ss_sp 0x00000a18
#define ASIZ_task_sas_ss_sp 0x00000008
-#define AOFF_task_sas_ss_size 0x00000a30
+#define AOFF_task_sas_ss_size 0x00000a20
#define ASIZ_task_sas_ss_size 0x00000008
-#define ASIZ_task 0x00000a40
+#define ASIZ_task 0x00000a30
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_cache 0x00000008
#define ASIZ_task_tarray_ptr 0x00000008
#define AOFF_task_wait_chldexit 0x000000e8
#define ASIZ_task_wait_chldexit 0x00000008
-#define AOFF_task_timeout 0x000000f0
-#define ASIZ_task_timeout 0x00000008
-#define AOFF_task_policy 0x000000f8
+#define AOFF_task_policy 0x000000f0
#define ASIZ_task_policy 0x00000008
-#define AOFF_task_rt_priority 0x00000100
+#define AOFF_task_rt_priority 0x000000f8
#define ASIZ_task_rt_priority 0x00000008
-#define AOFF_task_it_real_value 0x00000108
+#define AOFF_task_it_real_value 0x00000100
#define ASIZ_task_it_real_value 0x00000008
-#define AOFF_task_it_prof_value 0x00000110
+#define AOFF_task_it_prof_value 0x00000108
#define ASIZ_task_it_prof_value 0x00000008
-#define AOFF_task_it_virt_value 0x00000118
+#define AOFF_task_it_virt_value 0x00000110
#define ASIZ_task_it_virt_value 0x00000008
-#define AOFF_task_it_real_incr 0x00000120
+#define AOFF_task_it_real_incr 0x00000118
#define ASIZ_task_it_real_incr 0x00000008
-#define AOFF_task_it_prof_incr 0x00000128
+#define AOFF_task_it_prof_incr 0x00000120
#define ASIZ_task_it_prof_incr 0x00000008
-#define AOFF_task_it_virt_incr 0x00000130
+#define AOFF_task_it_virt_incr 0x00000128
#define ASIZ_task_it_virt_incr 0x00000008
-#define AOFF_task_real_timer 0x00000138
+#define AOFF_task_real_timer 0x00000130
#define ASIZ_task_real_timer 0x00000028
-#define AOFF_task_times 0x00000160
+#define AOFF_task_times 0x00000158
#define ASIZ_task_times 0x00000020
-#define AOFF_task_start_time 0x00000180
+#define AOFF_task_start_time 0x00000178
#define ASIZ_task_start_time 0x00000008
-#define AOFF_task_per_cpu_utime 0x00000188
+#define AOFF_task_per_cpu_utime 0x00000180
#define ASIZ_task_per_cpu_utime 0x00000100
-#define AOFF_task_min_flt 0x00000388
+#define AOFF_task_min_flt 0x00000380
#define ASIZ_task_min_flt 0x00000008
-#define AOFF_task_maj_flt 0x00000390
+#define AOFF_task_maj_flt 0x00000388
#define ASIZ_task_maj_flt 0x00000008
-#define AOFF_task_nswap 0x00000398
+#define AOFF_task_nswap 0x00000390
#define ASIZ_task_nswap 0x00000008
-#define AOFF_task_cmin_flt 0x000003a0
+#define AOFF_task_cmin_flt 0x00000398
#define ASIZ_task_cmin_flt 0x00000008
-#define AOFF_task_cmaj_flt 0x000003a8
+#define AOFF_task_cmaj_flt 0x000003a0
#define ASIZ_task_cmaj_flt 0x00000008
-#define AOFF_task_cnswap 0x000003b0
+#define AOFF_task_cnswap 0x000003a8
#define ASIZ_task_cnswap 0x00000008
-#define AOFF_task_swap_address 0x000003c0
+#define AOFF_task_swap_address 0x000003b8
#define ASIZ_task_swap_address 0x00000008
-#define AOFF_task_old_maj_flt 0x000003c8
+#define AOFF_task_old_maj_flt 0x000003c0
#define ASIZ_task_old_maj_flt 0x00000008
-#define AOFF_task_dec_flt 0x000003d0
+#define AOFF_task_dec_flt 0x000003c8
#define ASIZ_task_dec_flt 0x00000008
-#define AOFF_task_swap_cnt 0x000003d8
+#define AOFF_task_swap_cnt 0x000003d0
#define ASIZ_task_swap_cnt 0x00000008
-#define AOFF_task_uid 0x000003e0
+#define AOFF_task_uid 0x000003d8
#define ASIZ_task_uid 0x00000004
-#define AOFF_task_euid 0x000003e4
+#define AOFF_task_euid 0x000003dc
#define ASIZ_task_euid 0x00000004
-#define AOFF_task_suid 0x000003e8
+#define AOFF_task_suid 0x000003e0
#define ASIZ_task_suid 0x00000004
-#define AOFF_task_fsuid 0x000003ec
+#define AOFF_task_fsuid 0x000003e4
#define ASIZ_task_fsuid 0x00000004
-#define AOFF_task_gid 0x000003f0
+#define AOFF_task_gid 0x000003e8
#define ASIZ_task_gid 0x00000004
-#define AOFF_task_egid 0x000003f4
+#define AOFF_task_egid 0x000003ec
#define ASIZ_task_egid 0x00000004
-#define AOFF_task_sgid 0x000003f8
+#define AOFF_task_sgid 0x000003f0
#define ASIZ_task_sgid 0x00000004
-#define AOFF_task_fsgid 0x000003fc
+#define AOFF_task_fsgid 0x000003f4
#define ASIZ_task_fsgid 0x00000004
-#define AOFF_task_ngroups 0x00000400
+#define AOFF_task_ngroups 0x000003f8
#define ASIZ_task_ngroups 0x00000004
-#define AOFF_task_groups 0x00000404
+#define AOFF_task_groups 0x000003fc
#define ASIZ_task_groups 0x00000080
-#define AOFF_task_cap_effective 0x00000484
+#define AOFF_task_cap_effective 0x0000047c
#define ASIZ_task_cap_effective 0x00000004
-#define AOFF_task_cap_inheritable 0x00000488
+#define AOFF_task_cap_inheritable 0x00000480
#define ASIZ_task_cap_inheritable 0x00000004
-#define AOFF_task_cap_permitted 0x0000048c
+#define AOFF_task_cap_permitted 0x00000484
#define ASIZ_task_cap_permitted 0x00000004
-#define AOFF_task_user 0x00000490
+#define AOFF_task_user 0x00000488
#define ASIZ_task_user 0x00000008
-#define AOFF_task_rlim 0x00000498
+#define AOFF_task_rlim 0x00000490
#define ASIZ_task_rlim 0x000000a0
-#define AOFF_task_used_math 0x00000538
+#define AOFF_task_used_math 0x00000530
#define ASIZ_task_used_math 0x00000002
-#define AOFF_task_comm 0x0000053a
+#define AOFF_task_comm 0x00000532
#define ASIZ_task_comm 0x00000010
-#define AOFF_task_link_count 0x0000054c
+#define AOFF_task_link_count 0x00000544
#define ASIZ_task_link_count 0x00000004
-#define AOFF_task_tty 0x00000550
+#define AOFF_task_tty 0x00000548
#define ASIZ_task_tty 0x00000008
-#define AOFF_task_semundo 0x00000558
+#define AOFF_task_semundo 0x00000550
#define ASIZ_task_semundo 0x00000008
-#define AOFF_task_semsleeping 0x00000560
+#define AOFF_task_semsleeping 0x00000558
#define ASIZ_task_semsleeping 0x00000008
-#define AOFF_task_tss 0x00000570
+#define AOFF_task_tss 0x00000560
#define ASIZ_task_tss 0x00000470
-#define AOFF_task_fs 0x000009e0
+#define AOFF_task_fs 0x000009d0
#define ASIZ_task_fs 0x00000008
-#define AOFF_task_files 0x000009e8
+#define AOFF_task_files 0x000009d8
#define ASIZ_task_files 0x00000008
-#define AOFF_task_mm 0x000009f0
+#define AOFF_task_mm 0x000009e0
#define ASIZ_task_mm 0x00000008
-#define AOFF_task_sigmask_lock 0x000009f8
+#define AOFF_task_sigmask_lock 0x000009e8
#define ASIZ_task_sigmask_lock 0x0000000c
-#define AOFF_task_sig 0x00000a08
+#define AOFF_task_sig 0x000009f8
#define ASIZ_task_sig 0x00000008
-#define AOFF_task_signal 0x00000a10
+#define AOFF_task_signal 0x00000a00
#define ASIZ_task_signal 0x00000008
-#define AOFF_task_blocked 0x00000a18
+#define AOFF_task_blocked 0x00000a08
#define ASIZ_task_blocked 0x00000008
-#define AOFF_task_sigqueue 0x00000a20
+#define AOFF_task_sigqueue 0x00000a10
#define ASIZ_task_sigqueue 0x00000008
-#define AOFF_task_sigqueue_tail 0x00000a28
+#define AOFF_task_sigqueue_tail 0x00000a18
#define ASIZ_task_sigqueue_tail 0x00000008
-#define AOFF_task_sas_ss_sp 0x00000a30
+#define AOFF_task_sas_ss_sp 0x00000a20
#define ASIZ_task_sas_ss_sp 0x00000008
-#define AOFF_task_sas_ss_size 0x00000a38
+#define AOFF_task_sas_ss_size 0x00000a28
#define ASIZ_task_sas_ss_size 0x00000008
-#define ASIZ_task 0x00000a40
+#define ASIZ_task 0x00000a30
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_cache 0x00000008
-/* $Id: dma.h,v 1.9 1998/10/26 20:03:15 davem Exp $
+/* $Id: dma.h,v 1.10 1998/10/27 23:28:50 davem Exp $
* include/asm-sparc64/dma.h
*
* Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
extern spinlock_t dma_spin_lock;
-static __inline__ unsigned long claim_dma_lock(void)
-{
- unsigned long flags;
- spin_lock_irqsave(&dma_spin_lock, flags);
- return flags;
-}
-
-static __inline__ void release_dma_lock(unsigned long flags)
-{
- spin_unlock_irqrestore(&dma_spin_lock, flags);
-}
+#define claim_dma_lock() \
+({ unsigned long flags; \
+ spin_lock_irqsave(&dma_spin_lock, flags); \
+ flags; \
+})
+
+#define release_dma_lock(__flags) \
+ spin_unlock_irqrestore(&dma_spin_lock, __flags);
/* These are irrelevant for Sparc DMA, but we leave it in so that
* things can compile.
-/* $Id: namei.h,v 1.12 1998/03/13 17:38:13 jj Exp $
+/* $Id: namei.h,v 1.13 1998/10/28 08:13:49 jj Exp $
* linux/include/asm-sparc64/namei.h
*
* Routines to handle famous /usr/gnemul/s*.
return NULL;
}
- base = lookup_dentry (emul, dget (current->fs->root), (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
+ base = lookup_dentry (emul,
+ dget (current->fs->root),
+ (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK));
if (IS_ERR (base)) return NULL;
-/* $Id: pgtable.h,v 1.95 1998/10/22 03:05:57 davem Exp $
+/* $Id: pgtable.h,v 1.96 1998/10/27 23:28:42 davem Exp $
* pgtable.h: SpitFire page table operations.
*
* Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
{ pte_t pte; pte_val(pte) = (type<<PAGE_SHIFT)|(offset<<(PAGE_SHIFT+8)); return pte; }
extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space)
-{ pte_t pte; pte_val(pte) = ((page) | pgprot_val(prot) | _PAGE_E) & ~(unsigned long)_PAGE_CACHE; return pte; }
+{
+ pte_t pte;
+ pte_val(pte) = ((page) | pgprot_val(prot) | _PAGE_E) & ~(unsigned long)_PAGE_CACHE;
+ pte_val(pte) |= (((unsigned long)space) << 32);
+ return pte;
+}
#define SWP_TYPE(entry) (((entry>>PAGE_SHIFT) & 0xff))
#define SWP_OFFSET(entry) ((entry) >> (PAGE_SHIFT+8))
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
-typedef struct { } rwlock_t;
-#define RW_LOCK_UNLOCKED { }
+typedef unsigned long rwlock_t;
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
#define read_lock(lock) do { } while(0)
#define read_unlock(lock) do { } while(0)
unsigned char lock;
unsigned int owner_pc, owner_cpu;
} spinlock_t;
-#define SPIN_LOCK_UNLOCKED { 0, 0, NO_PROC_ID }
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, NO_PROC_ID }
#define spin_lock_init(__lock) \
do { (__lock)->lock = 0; \
(__lock)->owner_pc = 0; \
unsigned int writer_pc, writer_cpu;
unsigned int reader_pc[4];
} rwlock_t;
-#define RW_LOCK_UNLOCKED { 0, 0, NO_PROC_ID, { 0, 0, 0, 0 } }
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, NO_PROC_ID, { 0, 0, 0, 0 } }
extern void _do_read_lock(rwlock_t *rw, char *str);
extern void _do_read_unlock(rwlock_t *rw, char *str);
#define AUTOFS_PROTO_VERSION 3
+/*
+ * Architectures where both 32- and 64-bit binaries can be executed
+ * on 64-bit kernels need this. This keeps the structure format
+ * uniform, and makes sure the wait_queue_token isn't too big to be
+ * passed back down to the kernel.
+ *
+ * This assumes that on these architectures:
+ * mode 32 bit 64 bit
+ * -------------------------
+ * int 32 bit 32 bit
+ * long 32 bit 64 bit
+ *
+ * If so, 32-bit user-space code should be backwards compatible.
+ */
+
+#if defined(__sparc__) || defined(__mips__)
+typedef unsigned int autofs_wqt_t;
+#else
+typedef unsigned long autofs_wqt_t;
+#endif
+
enum autofs_packet_type {
autofs_ptype_missing, /* Missing entry (mount request) */
autofs_ptype_expire, /* Expire entry (umount request) */
struct autofs_packet_missing {
struct autofs_packet_hdr hdr;
- unsigned long wait_queue_token;
+ autofs_wqt_t wait_queue_token;
int len;
char name[NAME_MAX+1];
};
struct lp_struct {
struct pardevice *dev;
- int flags;
+ unsigned long flags;
unsigned int chars;
unsigned int time;
unsigned int wait;
extern int riscom8_init(void);
extern int specialix_init(void);
extern int espserial_init(void);
+extern int macserial_init(void);
extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device,
const char *routine);
#ifdef CONFIG_MD_BOOT
{ "md=", md_setup},
#endif
-#ifdef CONFIG_MACMOUSE
+#ifdef CONFIG_ADBMOUSE
{ "adb_buttons=", adb_mouse_setup },
#endif
#ifdef CONFIG_LTPC
#ifdef CONFIG_SBUS
sbus_init();
#endif
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
powermac_init();
#endif
#ifdef CONFIG_MCA
O_TARGET := mm.o
O_OBJS := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
- vmalloc.o slab.o \
+ vmalloc.o slab.o mrecow.o \
swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o
include $(TOPDIR)/Rules.make
touch_page(page);
break;
}
- age_page(page);
- if (page->age)
- break;
if (pgcache_under_min())
break;
remove_inode_page(page);
--- /dev/null
+/*
+ * linux/mm/recow.c
+ *
+ * Copyright (C) 1998 Linus Torvalds
+ */
+
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+
+#include <asm/pgtable.h>
+
+/*
+ * This implements the "re-COW" system call.
+ *
+ * "re-cow" - synchronize two page-aligned areas with each other,
+ * returning the first offset at which they differ. This is useful
+ * for doing large memory compares. One example is simulating a
+ * VGA device under DOSEMU, where you cache the old state of the
+ * screen, and let DOSEMU have a private copy that it can change.
+ *
+ * When you want to synchronize the real screen with the private
+ * simulation, you "re-cow()" the areas and see where the changes
+ * have been. It will not only tell you what pages have been modified,
+ * it will also share pages if they are the same..
+ *
+ * Doing this in user mode is prohibitive, as we need to access
+ * the page tables in order to do this efficiently.
+ */
+
+#define verify_recow(mm, vma, addr, len) do { \
+ vma = find_vma(mm, addr); \
+ if (!vma || (vma->vm_flags & VM_SHARED) || addr < vma->vm_start || vma->vm_end - addr < len) \
+ goto badvma; \
+} while (0)
+
+static int do_compare(struct mm_struct *mm, pte_t * firstpte, unsigned long addr)
+{
+ pgd_t * pgd;
+
+ pgd = pgd_offset(mm, addr);
+ if (!pgd_none(*pgd)) {
+ pmd_t * pmd = pmd_offset(pgd, addr);
+ if (!pmd_none(*pmd)) {
+ pte_t * pte = pte_offset(pmd, addr);
+ pte_t entry = *pte;
+ if (pte_present(entry)) {
+ unsigned long page1 = pte_page(*firstpte);
+ unsigned long page2 = pte_page(entry);
+
+ if (page1 == page2)
+ return 1;
+
+ if (!memcmp((void *) page1, (void *) page2, PAGE_SIZE)) {
+ entry = pte_wrprotect(entry);
+ *firstpte = entry;
+ *pte = entry;
+ atomic_inc(&mem_map[MAP_NR(page2)].count);
+ free_page(page1);
+ return 2;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * NOTE! We return zero for all "special" cases,
+ * so that if something is not present for any
+ * reason the user has to compare that by hand.
+ */
+static int same_page(struct mm_struct *mm, unsigned long addr1, unsigned long addr2)
+{
+ pgd_t * pgd;
+
+ pgd = pgd_offset(mm, addr1);
+ if (!pgd_none(*pgd)) {
+ pmd_t * pmd = pmd_offset(pgd, addr1);
+ if (!pmd_none(*pmd)) {
+ pte_t * pte = pte_offset(pmd, addr1);
+ if (pte_present(*pte))
+ return do_compare(mm, pte, addr2);
+ }
+ }
+ return 0;
+}
+
+asmlinkage long sys_mrecow(unsigned long addr1, unsigned long addr2, size_t len)
+{
+ int shared = 0;
+ long retval;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma1, *vma2;
+
+ /*
+ * Everything has to be page-aligned..
+ */
+ if ((addr1 | addr2 | len) & ~PAGE_MASK)
+ return -EINVAL;
+
+ /* Make sure we're not aliased (trivially the same for the whole length) */
+ if (addr1 == addr2)
+ return len;
+
+ down(&mm->mmap_sem);
+
+ /*
+ * We require that the comparison areas are fully contained
+ * within the vm_area_structs, and that they are both private
+ * mappings..
+ */
+ retval = -EFAULT;
+ verify_recow(mm, vma1, addr1, len);
+ verify_recow(mm, vma2, addr2, len);
+
+ /*
+ * We need to have the same page protections on both
+ * areas, otherwise we'll mess up when we combine pages.
+ *
+ * Right now we also only allow this on anonymous areas,
+ * I don't know if we'd want to expand it to other things
+ * at some point.
+ */
+ retval = -EINVAL;
+ if (pgprot_val(vma1->vm_page_prot) != pgprot_val(vma2->vm_page_prot))
+ goto badvma;
+ if (vma1->vm_file || vma2->vm_file)
+ goto badvma;
+
+ /*
+ * Ok, start the page walk..
+ */
+ lock_kernel();
+ retval = 0;
+ while (len) {
+ int same = same_page(mm, addr1, addr2);
+ if (!same)
+ break;
+
+ shared |= same;
+ len -= PAGE_SIZE;
+ retval += PAGE_SIZE;
+ addr1 += PAGE_SIZE;
+ addr2 += PAGE_SIZE;
+ }
+ unlock_kernel();
+ if (shared)
+ flush_tlb_mm(mm);
+
+badvma:
+ up(&mm->mmap_sem);
+ return retval;
+}
+
+
p->max = swap_header->info.last_page;
if (p->max >= 0x7fffffffL/PAGE_SIZE ||
- (void *) &swap_header->info.badpages[swap_header->info.nr_badpages-1] >= (void *) swap_header->magic.magic) {
+ (void *) &swap_header->info.badpages[(int) swap_header->info.nr_badpages-1] >= (void *) swap_header->magic.magic) {
error = -EINVAL;
goto bad_swap;
}
do {
if (!do_try_to_free_page(0))
break;
- if (nr_free_pages > 2*freepages.high)
+ if (nr_free_pages > freepages.high + SWAP_CLUSTER_MAX)
break;
} while (time_before_eq(jiffies,end_time));
}
* priority.
*/
want_wakeup = 0;
- if (buffer_over_max() || pgcache_over_max())
- want_wakeup = 1;
pages = nr_free_pages;
if (pages < freepages.high)
want_wakeup = 1;
*
* PF_INET protocol family socket handler.
*
- * Version: $Id: af_inet.c,v 1.79 1998/10/04 06:51:08 davem Exp $
+ * Version: $Id: af_inet.c,v 1.80 1998/11/08 11:17:03 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* RAW - implementation of IP "raw" sockets.
*
- * Version: $Id: raw.c,v 1.38 1998/10/03 09:37:45 davem Exp $
+ * Version: $Id: raw.c,v 1.39 1998/11/08 11:17:04 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.130 1998/11/07 14:36:10 davem Exp $
+ * Version: $Id: tcp.c,v 1.132 1998/11/08 13:21:14 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
/*
* Compute minimal free write space needed to queue new packets.
*/
-static inline int tcp_min_write_space(struct sock *sk, struct tcp_opt *tp)
-{
- int space;
-#if 1 /* This needs benchmarking and real world tests */
- space = max(tp->mss_cache + 128, MIN_WRITE_SPACE);
-#else /* 2.0 way */
- /* More than half of the socket queue free? */
- space = atomic_read(&sk->wmem_alloc) / 2;
-#endif
- return space;
-}
+#define tcp_min_write_space(__sk) \
+ (atomic_read(&(__sk)->wmem_alloc) / 2)
/*
* Wait for a TCP event.
mask |= POLLIN | POLLRDNORM;
if (!(sk->shutdown & SEND_SHUTDOWN)) {
- if (sock_wspace(sk) >= tcp_min_write_space(sk, tp)) {
+ if (sock_wspace(sk) >= tcp_min_write_space(sk)) {
mask |= POLLOUT | POLLWRNORM;
} else { /* send SIGIO later */
sk->socket->flags |= SO_NOSPACE;
wake_up_interruptible(sk->sleep);
if (sock_wspace(sk) >=
- tcp_min_write_space(sk, &(sk->tp_pinfo.af_tcp)))
+ tcp_min_write_space(sk))
sock_wake_async(sk->socket, 2);
}
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.136 1998/11/07 14:36:18 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.140 1998/11/12 06:45:15 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
}
/* When we get a reset we do this. */
-static void tcp_reset(struct sock *sk, struct sk_buff *skb)
+static void tcp_reset(struct sock *sk)
{
sk->zapped = 1;
default:
sk->err = ECONNRESET;
};
- tcp_set_state(sk,TCP_CLOSE);
+ tcp_set_state(sk, TCP_CLOSE);
sk->shutdown = SHUTDOWN_MASK;
if (!sk->dead)
sk->state_change(sk);
if (tp->high_seq == 0 || after(ack, tp->high_seq)) {
tp->dup_acks++;
if ((tp->fackets_out > 3) || (tp->dup_acks == 3)) {
- tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2);
+ tp->snd_ssthresh =
+ max(min(tp->snd_wnd, tp->snd_cwnd) >> 1, 2);
tp->snd_cwnd = (tp->snd_ssthresh + 3);
tp->high_seq = tp->snd_nxt;
if(!tp->fackets_out)
- tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+ tcp_retransmit_skb(sk,
+ skb_peek(&sk->write_queue));
else
tcp_fack_retransmit(sk);
tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
}
- }
-
- /* 2. Each time another duplicate ACK arrives, increment
- * cwnd by the segment size. [...] Transmit a packet...
- *
- * Packet transmission will be done on normal flow processing
- * since we're not in "retransmit mode". We do not use duplicate
- * ACKs to artificially inflate the congestion window when
- * doing FACK.
- */
- if (tp->dup_acks > 3) {
+ } else if (++tp->dup_acks > 3) {
+ /* 2. Each time another duplicate ACK arrives, increment
+ * cwnd by the segment size. [...] Transmit a packet...
+ *
+ * Packet transmission will be done on normal flow processing
+ * since we're not in "retransmit mode". We do not use
+ * duplicate ACKs to artificially inflate the congestion
+ * window when doing FACK.
+ */
if(!tp->fackets_out) {
tp->snd_cwnd++;
} else {
- /* Fill any further holes which may have appeared.
- * We may want to change this to run every further
- * multiple-of-3 dup ack increments, to be more robust
- * against out-of-order packet delivery. -DaveM
+ /* Fill any further holes which may have
+ * appeared.
+ *
+ * We may want to change this to run every
+ * further multiple-of-3 dup ack increments,
+ * to be more robust against out-of-order
+ * packet delivery. -DaveM
*/
tcp_fack_retransmit(sk);
}
* from snd_una is if this was a window update.
*/
if (ack != tp->snd_una && before(ack, tp->high_seq)) {
- tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+ tcp_retransmit_skb(sk,
+ skb_peek(&sk->write_queue));
tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
}
} else {
/* This is Jacobson's slow start and congestion avoidance.
* SIGCOMM '88, p. 328.
*/
-static void tcp_cong_avoid(struct tcp_opt *tp)
+static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
{
if (tp->snd_cwnd <= tp->snd_ssthresh) {
/* In "safe" area, increase. */
}
}
+/* Should we open up the congestion window? */
+static __inline__ int should_advance_cwnd(struct tcp_opt *tp, int flag)
+{
+ /* Data must have been acked. */
+ if ((flag & FLAG_DATA_ACKED) == 0)
+ return 0;
+
+ /* Some of the data acked was retransmitted somehow? */
+ if ((flag & FLAG_RETRANS_DATA_ACKED) != 0) {
+ /* We advance in all cases except during
+ * non-FACK fast retransmit/recovery.
+ */
+ if (tp->fackets_out != 0 ||
+ tp->retransmits != 0)
+ return 1;
+
+ /* Non-FACK fast retransmit does it's own
+ * congestion window management, don't get
+ * in the way.
+ */
+ return 0;
+ }
+
+ /* New non-retransmitted data acked, always advance. */
+ return 1;
+}
+
/* Read draft-ietf-tcplw-high-performance before mucking
* with this code. (Superceeds RFC1323)
*/
}
} else {
tcp_set_rto(tp);
- tcp_cong_avoid(tp);
}
+ if (should_advance_cwnd(tp, flag))
+ tcp_cong_avoid(tp);
+
/* NOTE: safe here so long as cong_ctl doesn't use rto */
tcp_bound_rto(tp);
}
tcp_set_rto(tp);
tcp_bound_rto(tp);
}
- tcp_cong_avoid(tp);
}
}
+ if (should_advance_cwnd(tp, flag))
+ tcp_cong_avoid(tp);
}
if (tp->packets_out) {
if(th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) {
SOCK_DEBUG(sk, "syn in established state\n");
tcp_statistics.TcpInErrs++;
- tcp_reset(sk, skb);
+ tcp_reset(sk);
return 1;
}
if(th->rst) {
- tcp_reset(sk,skb);
+ tcp_reset(sk);
goto discard;
}
}
if(th->rst) {
- tcp_reset(sk,skb);
+ tcp_reset(sk);
goto discard;
}
/* step 2: check RST bit */
if(th->rst) {
- tcp_reset(sk,skb);
+ tcp_reset(sk);
goto discard;
}
*/
if (th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) {
- tcp_reset(sk, skb);
+ tcp_reset(sk);
return 1;
}
*/
if ((sk->shutdown & RCV_SHUTDOWN) && sk->dead) {
if (after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
- tcp_reset(sk, skb);
+ tcp_reset(sk);
return 1;
}
}
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_output.c,v 1.96 1998/11/07 10:54:40 davem Exp $
+ * Version: $Id: tcp_output.c,v 1.97 1998/11/08 13:21:27 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
struct sk_buff *skb;
/* NOTE: No TCP options attached and we never retransmit this. */
- do {
- skb = alloc_skb(MAX_HEADER + sk->prot->max_header, GFP_KERNEL);
- } while(skb == NULL);
+ skb = alloc_skb(MAX_HEADER + sk->prot->max_header, GFP_KERNEL);
+ if (!skb)
+ return;
/* Reserve space for headers and prepare control bits. */
skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.63 1998/10/03 09:38:16 davem Exp $
+ * Version: $Id: udp.c,v 1.64 1998/11/08 11:17:07 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* Adapted from linux/net/ipv4/raw.c
*
- * $Id: raw.c,v 1.22 1998/10/03 09:38:40 davem Exp $
+ * $Id: raw.c,v 1.23 1998/11/08 11:17:09 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
}
-static void rawv6_close(struct sock *sk, unsigned long timeout)
+static void rawv6_close(struct sock *sk, long timeout)
{
/* See for explanation: raw_close in ipv4/raw.c */
sk->state = TCP_CLOSE;
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp.c,v 1.36 1998/10/03 09:38:54 davem Exp $
+ * $Id: udp.c,v 1.37 1998/11/08 11:17:10 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
return(0);
}
-static void udpv6_close(struct sock *sk, unsigned long timeout)
+static void udpv6_close(struct sock *sk, long timeout)
{
/* See for explanation: raw_close in ipv4/raw.c */
sk->state = TCP_CLOSE;