The module will be called usbcore.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
-UHCI (intel PIIX4 and others) support?
+UHCI (intel PIIX4, VIA, and others) support?
CONFIG_USB_UHCI
The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB
The module will be called usb-uhci.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
-OHCI-HCD (compaq and some others) support?
+OHCI-HCD (Compaq, iMacs, OPTi, SiS, and others) support?
CONFIG_USB_OHCI_HCD
The Open Host Controller Interface is a standard by
Compaq/Microsoft/National for accessing the USB PC hardware (also
The module will be called acm.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
-USB Belkin and Peracom serial support
+USB serial converter support
CONFIG_USB_SERIAL
- Say Y here if you want to connect a Belkin, Peracom, or eTek
+ Say Y here if you want to connect a Connect Tech WhiteHEAT
+ multi-port USB to serial converter, or a Belkin, Peracom, or eTek
single port USB to serial converter.
This code is also available as a module ( = code which can be
DABUSB driver
CONFIG_USB_DABUSB
- A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought to
- you by the DAB-Team (http://dab.in.tum.de).
+ A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought
+ to you by the DAB-Team (http://dab.in.tum.de).
This driver can be taken as an example for URB-based bulk, control, and
isochronous transactions.
#
CONFIG_PCMCIA=y
CONFIG_CARDBUS=y
-CONFIG_I82365=y
-# CONFIG_TCIC is not set
+CONFIG_YENTA=y
+# CONFIG_I82365 is not set
+CONFIG_TCIC=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-/* $Id: sys_sparc.c,v 1.54 1999/11/19 04:11:36 davem Exp $
+/* $Id: sys_sparc.c,v 1.55 1999/12/21 14:09:09 jj Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
}
/* Linux version of mmap */
-asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+static unsigned long do_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd,
- unsigned long off)
+ unsigned long pgoff)
{
struct file * file = NULL;
unsigned long retval = -EBADF;
- down(¤t->mm->mmap_sem);
- lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
goto out;
}
+
+ down(¤t->mm->mmap_sem);
+ lock_kernel();
retval = -ENOMEM;
len = PAGE_ALIGN(len);
if(!(flags & MAP_FIXED) &&
goto out_putf;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- retval = do_mmap(file, addr, len, prot, flags, off);
+ retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
out_putf:
+ unlock_kernel();
+ up(¤t->mm->mmap_sem);
if (file)
fput(file);
out:
- unlock_kernel();
- up(¤t->mm->mmap_sem);
return retval;
}
+asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long pgoff)
+{
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long off)
+{
+ return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+}
+
/* we come to here via sys_nis_syscall so it can setup the regs argument */
asmlinkage unsigned long
c_sys_nis_syscall (struct pt_regs *regs)
-/* $Id: systbls.S,v 1.87 1999/12/15 17:51:09 jj Exp $
+/* $Id: systbls.S,v 1.88 1999/12/21 14:09:06 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
/*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
/*45*/ .long sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
/*50*/ .long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl
-/*55*/ .long sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
-/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize
+/*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve
+/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
/*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall
/*70*/ .long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
-/*75*/ .long sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups
-/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
+/*75*/ .long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_nis_syscall, sys_getgroups
+/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_ftruncate64
/*85*/ .long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
/*90*/ .long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
/*95*/ .long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*115*/ .long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
/*125*/ .long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate
-/*130*/ .long sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall
+/*130*/ .long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
+/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64
/*140*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
/*145*/ .long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
/*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
-/* $Id: sys32.S,v 1.8 1998/10/28 08:10:37 jj Exp $
+/* $Id: sys32.S,v 1.9 1999/12/21 14:09:18 jj Exp $
* sys32.S: I-cache tricks for 32-bit compatability layer simple
* conversions.
*
sethi %hi(sys_bdflush), %g1
jmpl %g1 + %lo(sys_bdflush), %g0
sra %o1, 0, %o1
+
+ .align 32
+ .globl sys32_mmap2
+sys32_mmap2:
+ srl %o4, 0, %o4
+ sethi %hi(sys_mmap), %g1
+ srl %o5, 0, %o5
+ jmpl %g1 + %lo(sys_mmap), %g0
+ sllx %o5, 12, %o5
-/* $Id: sys_sparc.c,v 1.30 1999/10/13 11:48:07 jj Exp $
+/* $Id: sys_sparc.c,v 1.31 1999/12/21 14:09:25 jj Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
struct file * file = NULL;
unsigned long retval = -EBADF;
- down(¤t->mm->mmap_sem);
- lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
goto out;
}
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = -ENOMEM;
len = PAGE_ALIGN(len);
+ down(¤t->mm->mmap_sem);
+ lock_kernel();
if(!(flags & MAP_FIXED) && !addr) {
addr = get_unmapped_area(addr, len);
if(!addr)
}
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = do_mmap(file, addr, len, prot, flags, off);
out_putf:
+ unlock_kernel();
+ up(¤t->mm->mmap_sem);
if (file)
fput(file);
out:
- unlock_kernel();
- up(¤t->mm->mmap_sem);
return retval;
}
-/* $Id: sys_sparc32.c,v 1.125 1999/12/20 05:02:15 davem Exp $
+/* $Id: sys_sparc32.c,v 1.126 1999/12/21 14:09:21 jj Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
return ret;
}
+extern asmlinkage long sys_truncate(const char * path, unsigned long length);
+extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
+
+asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
+{
+ if ((int)high < 0)
+ return -EINVAL;
+ else
+ return sys_truncate(path, (high << 32) | low);
+}
+
+asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
+{
+ if ((int)high < 0)
+ return -EINVAL;
+ else
+ return sys_ftruncate(fd, (high << 32) | low);
+}
+
extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
struct utimbuf32 {
-/* $Id: systbls.S,v 1.60 1999/12/15 17:51:19 jj Exp $
+/* $Id: systbls.S,v 1.61 1999/12/21 14:09:15 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
/*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_nis_syscall
.word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
/*50*/ .word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl
- .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys32_execve
-/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize
+ .word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve
+/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize
.word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_nis_syscall
/*70*/ .word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
- .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups
-/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall
+ .word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys_nis_syscall, sys32_getgroups
+/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys32_ftruncate64
.word sys_swapon, sys32_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
/*90*/ .word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall
.word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
.word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate
-/*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
- .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_nis_syscall
+/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
+ .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64
/*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
.word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
hwif->io_ports[IDE_DATA_OFFSET]+7,
hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
#elif defined(__sparc__)
- printk("%s at 0x%03x-0x%03x,0x%03x on irq %s", hwif->name,
+ printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET],
hwif->io_ports[IDE_DATA_OFFSET]+7,
hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));
int loops = 10;
int retval = 0;
+ /* Check if the BIOS detected a device on the auxiliary port. */
+ if (aux_device_present == 0xaa)
+ return 1;
+
spin_lock_irqsave(&kbd_controller_lock, flags);
/* Put the value 0x5A in the output buffer using the "Write
if [ "$CONFIG_PCMCIA" != "n" ]; then
if [ "$CONFIG_PCI" != "n" ]; then
bool ' CardBus support' CONFIG_CARDBUS
+ dep_tristate ' Yenta Cardbus support' CONFIG_YENTA $CONFIG_CARDBUS
fi
- bool ' i82365/Yenta compatible bridge support' CONFIG_I82365
+ bool ' i82365 compatible bridge support' CONFIG_I82365
bool ' Databook TCIC host bridge support' CONFIG_TCIC
fi
ifeq ($(CONFIG_TCIC),y)
O_OBJS += tcic.o
endif
+ ifeq ($(CONFIG_YENTA),y)
+ OX_OBJS += yenta.o pci_socket.o
+ endif
ifeq ($(CONFIG_CARDBUS),y)
O_OBJS += cardbus.o
OX_OBJS += cb_enabler.o
======================================================================*/
-static int register_callback(socket_info_t *s, ss_callback_t *call)
+static int register_callback(socket_info_t *s, void (*handler)(void *, unsigned int), void * info)
{
- return s->ss_entry->register_callback(s->sock, call);
+ return s->ss_entry->register_callback(s->sock, handler, info);
}
static int get_socket_status(socket_info_t *s, int *val)
}
if (--s->real_clients == 0)
- register_callback(s, NULL);
+ register_callback(s, NULL, NULL);
return CS_SUCCESS;
} /* deregister_client */
s = socket_table[ns];
if (++s->real_clients == 1) {
- ss_callback_t call;
int status;
- call.handler = &parse_events;
- call.info = s;
- register_callback(s, &call);
+ register_callback(s, &parse_events, s);
get_socket_status(s, &status);
if ((status & SS_DETECT) &&
!(s->state & SOCKET_SETUP_PENDING)) {
#include "o2micro.h"
/* PCI-bus controllers */
-#include "yenta.h"
+#include "old-yenta.h"
#include "ti113x.h"
#include "smc34c90.h"
#include "topic.h"
/*====================================================================*/
-static int pcic_register_callback(u_short sock, ss_callback_t *call)
+static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
{
- if (call == NULL) {
- socket[sock].handler = NULL;
+ socket[sock].handler = handler;
+ socket[sock].info = info;
+ if (handler == NULL) {
MOD_DEC_USE_COUNT;
} else {
MOD_INC_USE_COUNT;
- socket[sock].handler = call->handler;
- socket[sock].info = call->info;
}
return 0;
} /* pcic_register_callback */
/*====================================================================*/
-static int pcic_inquire_socket(u_short sock, socket_cap_t *cap)
+static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap)
{
*cap = socket[sock].cap;
return 0;
}
#endif
-static void pcic_proc_setup(u_short sock, struct proc_dir_entry *base)
+static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
{
#ifdef CONFIG_PROC_FS
socket_info_t *s = &socket[sock];
#endif
-static int pcic_get_status(u_short sock, u_int *value)
+static int pcic_get_status(unsigned int sock, u_int *value)
{
if (socket[sock].flags & IS_ALIVE) {
*value = 0;
LOCKED(i365_get_status(sock, value));
}
-static int pcic_get_socket(u_short sock, socket_state_t *state)
+static int pcic_get_socket(unsigned int sock, socket_state_t *state)
{
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_get_socket(sock, state));
}
-static int pcic_set_socket(u_short sock, socket_state_t *state)
+static int pcic_set_socket(unsigned int sock, socket_state_t *state)
{
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_set_socket(sock, state));
}
-static int pcic_get_io_map(u_short sock, struct pccard_io_map *io)
+static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io)
{
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_get_io_map(sock, io));
}
-static int pcic_set_io_map(u_short sock, struct pccard_io_map *io)
+static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io)
{
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_set_io_map(sock, io));
}
-static int pcic_get_mem_map(u_short sock, struct pccard_mem_map *mem)
+static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
{
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_get_mem_map(sock, mem));
}
-static int pcic_set_mem_map(u_short sock, struct pccard_mem_map *mem)
+static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
{
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_set_mem_map(sock, mem));
}
-static int pcic_get_bridge(u_short sock, struct cb_bridge_map *m)
+static int pcic_get_bridge(unsigned int sock, struct cb_bridge_map *m)
{
#ifdef CONFIG_CARDBUS
return cb_get_bridge(sock, m);
#endif
}
-static int pcic_set_bridge(u_short sock, struct cb_bridge_map *m)
+static int pcic_set_bridge(unsigned int sock, struct cb_bridge_map *m)
{
#ifdef CONFIG_CARDBUS
return cb_set_bridge(sock, m);
pcic_proc_setup
};
-#if 0
-static int pcic_service(u_int sock, u_int cmd, void *arg)
-{
- subfn_t fn;
- int ret;
-#ifdef CONFIG_ISA
- u_long flags = 0;
-#endif
-
- DEBUG(2, "pcic_ioctl(%d, %d, 0x%p)\n", sock, cmd, arg);
-
- if (cmd >= NFUNC)
- return -EINVAL;
-
- if (socket[sock].flags & IS_ALIVE) {
- if (cmd == SS_GetStatus)
- *(u_int *)arg = 0;
- return -EINVAL;
- }
-
- fn = pcic_service_table[cmd];
-#ifdef CONFIG_CARDBUS
- if ((socket[sock].flags & IS_CARDBUS) &&
- (cb_readl(sock, CB_SOCKET_STATE) & CB_SS_32BIT)) {
- if (cmd == SS_GetStatus)
- fn = (subfn_t)&cb_get_status;
- else if (cmd == SS_GetSocket)
- fn = (subfn_t)&cb_get_socket;
- else if (cmd == SS_SetSocket)
- fn = (subfn_t)&cb_set_socket;
- }
-#endif
-
- ISA_LOCK(sock, flags);
- ret = (fn == NULL) ? -EINVAL : fn(sock, arg);
- ISA_UNLOCK(sock, flags);
- return ret;
-} /* pcic_service */
-#endif
-
/*====================================================================*/
static int __init init_i82365(void)
--- /dev/null
+/*
+ * yenta.h 1.16 1999/10/25 20:03:34
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU Public License version 2 (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#ifndef _LINUX_YENTA_H
+#define _LINUX_YENTA_H
+
+/* PCI Configuration Registers */
+
+#define PCI_STATUS_CAPLIST 0x10
+#define PCI_CB_CAPABILITY_POINTER 0x14 /* 8 bit */
+#define PCI_CAPABILITY_ID 0x00 /* 8 bit */
+#define PCI_CAPABILITY_PM 0x01
+#define PCI_NEXT_CAPABILITY 0x01 /* 8 bit */
+#define PCI_PM_CAPABILITIES 0x02 /* 16 bit */
+#define PCI_PMCAP_PME_D3COLD 0x8000
+#define PCI_PMCAP_PME_D3HOT 0x4000
+#define PCI_PMCAP_PME_D2 0x2000
+#define PCI_PMCAP_PME_D1 0x1000
+#define PCI_PMCAP_PME_D0 0x0800
+#define PCI_PMCAP_D2_CAP 0x0400
+#define PCI_PMCAP_D1_CAP 0x0200
+#define PCI_PMCAP_DYN_DATA 0x0100
+#define PCI_PMCAP_DSI 0x0020
+#define PCI_PMCAP_AUX_PWR 0x0010
+#define PCI_PMCAP_PMECLK 0x0008
+#define PCI_PMCAP_VERSION_MASK 0x0007
+#define PCI_PM_CONTROL_STATUS 0x04 /* 16 bit */
+#define PCI_PMCS_PME_STATUS 0x8000
+#define PCI_PMCS_DATASCALE_MASK 0x6000
+#define PCI_PMCS_DATASCALE_SHIFT 13
+#define PCI_PMCS_DATASEL_MASK 0x1e00
+#define PCI_PMCS_DATASEL_SHIFT 9
+#define PCI_PMCS_PME_ENABLE 0x0100
+#define PCI_PMCS_PWR_STATE_MASK 0x0003
+#define PCI_PMCS_PWR_STATE_D0 0x0000
+#define PCI_PMCS_PWR_STATE_D1 0x0001
+#define PCI_PMCS_PWR_STATE_D2 0x0002
+#define PCI_PMCS_PWR_STATE_D3 0x0003
+#define PCI_PM_BRIDGE_EXT 0x06 /* 8 bit */
+#define PCI_PM_DATA 0x07 /* 8 bit */
+
+#define CB_PRIMARY_BUS 0x18 /* 8 bit */
+#define CB_CARDBUS_BUS 0x19 /* 8 bit */
+#define CB_SUBORD_BUS 0x1a /* 8 bit */
+#define CB_LATENCY_TIMER 0x1b /* 8 bit */
+
+#define CB_MEM_BASE(m) (0x1c + 8*(m))
+#define CB_MEM_LIMIT(m) (0x20 + 8*(m))
+#define CB_IO_BASE(m) (0x2c + 8*(m))
+#define CB_IO_LIMIT(m) (0x30 + 8*(m))
+
+#define CB_BRIDGE_CONTROL 0x3e /* 16 bit */
+#define CB_BCR_PARITY_ENA 0x0001
+#define CB_BCR_SERR_ENA 0x0002
+#define CB_BCR_ISA_ENA 0x0004
+#define CB_BCR_VGA_ENA 0x0008
+#define CB_BCR_MABORT 0x0020
+#define CB_BCR_CB_RESET 0x0040
+#define CB_BCR_ISA_IRQ 0x0080
+#define CB_BCR_PREFETCH(m) (0x0100 << (m))
+#define CB_BCR_WRITE_POST 0x0400
+
+#define CB_LEGACY_MODE_BASE 0x44
+
+/* Memory mapped registers */
+
+#define CB_SOCKET_EVENT 0x0000
+#define CB_SE_CSTSCHG 0x00000001
+#define CB_SE_CCD1 0x00000002
+#define CB_SE_CCD2 0x00000004
+#define CB_SE_PWRCYCLE 0x00000008
+
+#define CB_SOCKET_MASK 0x0004
+#define CB_SM_CSTSCHG 0x00000001
+#define CB_SM_CCD 0x00000006
+#define CB_SM_PWRCYCLE 0x00000008
+
+#define CB_SOCKET_STATE 0x0008
+#define CB_SS_CSTSCHG 0x00000001
+#define CB_SS_CCD1 0x00000002
+#define CB_SS_CCD2 0x00000004
+#define CB_SS_PWRCYCLE 0x00000008
+#define CB_SS_16BIT 0x00000010
+#define CB_SS_32BIT 0x00000020
+#define CB_SS_CINT 0x00000040
+#define CB_SS_BADCARD 0x00000080
+#define CB_SS_DATALOST 0x00000100
+#define CB_SS_BADVCC 0x00000200
+#define CB_SS_5VCARD 0x00000400
+#define CB_SS_3VCARD 0x00000800
+#define CB_SS_XVCARD 0x00001000
+#define CB_SS_YVCARD 0x00002000
+#define CB_SS_5VSOCKET 0x10000000
+#define CB_SS_3VSOCKET 0x20000000
+#define CB_SS_XVSOCKET 0x40000000
+#define CB_SS_YVSOCKET 0x80000000
+
+#define CB_SOCKET_FORCE 0x000c
+#define CB_SF_CVSTEST 0x00004000
+
+#define CB_SOCKET_CONTROL 0x0010
+#define CB_SC_VPP_MASK 0x00000007
+#define CB_SC_VPP_OFF 0x00000000
+#define CB_SC_VPP_12V 0x00000001
+#define CB_SC_VPP_5V 0x00000002
+#define CB_SC_VPP_3V 0x00000003
+#define CB_SC_VPP_XV 0x00000004
+#define CB_SC_VPP_YV 0x00000005
+#define CB_SC_VCC_MASK 0x00000070
+#define CB_SC_VCC_OFF 0x00000000
+#define CB_SC_VCC_5V 0x00000020
+#define CB_SC_VCC_3V 0x00000030
+#define CB_SC_VCC_XV 0x00000040
+#define CB_SC_VCC_YV 0x00000050
+#define CB_SC_CCLK_STOP 0x00000080
+
+#define CB_SOCKET_POWER 0x0020
+#define CB_SP_CLK_CTRL 0x00000001
+#define CB_SP_CLK_CTRL_ENA 0x00010000
+#define CB_SP_CLK_MODE 0x01000000
+#define CB_SP_ACCESS 0x02000000
+
+/* Address bits 31..24 for memory windows for 16-bit cards,
+ accessable only by memory mapping the 16-bit register set */
+#define CB_MEM_PAGE(map) (0x40 + (map))
+
+#endif /* _LINUX_YENTA_H */
--- /dev/null
+/*
+ * Generic PCI pccard driver interface.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * This implements the common parts of PCI pccard drivers,
+ * notably detection and infrastructure conversion (ie change
+ * from socket index to "struct pci_dev" etc)
+ *
+ * This does NOT implement the actual low-level driver details,
+ * and this has on purpose been left generic enough that it can
+ * be used to set up a PCI PCMCIA controller (ie non-cardbus),
+ * or to set up a controller.
+ *
+ * See for example the "yenta" driver for PCI cardbus controllers
+ * conforming to the yenta cardbus specifications.
+ */
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+
+#include "pci_socket.h"
+
+static struct pci_simple_probe_entry controller_list[] = {
+ { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, 0, 0, ¥ta_operations },
+ { 0, 0, 0, 0, NULL }
+};
+
+
+/*
+ * Arbitrary define. This is the array of active cardbus
+ * entries.
+ */
+#define MAX_SOCKETS (8)
+static pci_socket_t pci_socket_array[MAX_SOCKETS];
+
+/*
+ * Work in progress. I need to distill the _real_ differences in
+ * carbus drivers, and change the cardbus "op" list to match. This
+ * is just a direct 1:1 mapping of the pccard operations.
+ */
+static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ socket->handler = handler;
+ socket->info = info;
+ if (handler)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->inquire)
+ return socket->op->inquire(socket, cap);
+ return -EINVAL;
+}
+
+static int pci_get_status(unsigned int sock, unsigned int *value)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_status)
+ return socket->op->get_status(socket, value);
+ *value = 0;
+ return -EINVAL;
+}
+
+static int pci_get_socket(unsigned int sock, socket_state_t *state)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_socket)
+ return socket->op->get_socket(socket, state);
+ return -EINVAL;
+}
+
+static int pci_set_socket(unsigned int sock, socket_state_t *state)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->set_socket)
+ return socket->op->set_socket(socket, state);
+ return -EINVAL;
+}
+
+static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_io_map)
+ return socket->op->get_io_map(socket, io);
+ return -EINVAL;
+}
+
+static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->set_io_map)
+ return socket->op->set_io_map(socket, io);
+ return -EINVAL;
+}
+
+static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_mem_map)
+ return socket->op->get_mem_map(socket, mem);
+ return -EINVAL;
+}
+
+static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->set_mem_map)
+ return socket->op->set_mem_map(socket, mem);
+ return -EINVAL;
+}
+
+static int pci_get_bridge(unsigned int sock, struct cb_bridge_map *m)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_bridge)
+ return socket->op->get_bridge(socket, m);
+ return -EINVAL;
+}
+
+static int pci_set_bridge(unsigned int sock, struct cb_bridge_map *m)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->set_bridge)
+ return socket->op->set_bridge(socket, m);
+ return -EINVAL;
+}
+
+static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->proc_setup)
+ socket->op->proc_setup(socket, base);
+}
+
+static struct pccard_operations pci_socket_operations = {
+ pci_register_callback,
+ pci_inquire_socket,
+ pci_get_status,
+ pci_get_socket,
+ pci_set_socket,
+ pci_get_io_map,
+ pci_set_io_map,
+ pci_get_mem_map,
+ pci_set_mem_map,
+ pci_get_bridge,
+ pci_set_bridge,
+ pci_proc_setup
+};
+
+static int __init pci_socket_probe(struct pci_dev *dev, int nr, const struct pci_simple_probe_entry * entry, void *data)
+{
+ pci_socket_t *socket = nr + pci_socket_array;
+
+ printk("Found controller %d: %s\n", nr, dev->name);
+ socket->dev = dev;
+ socket->op = entry->dev_data;
+ socket->op->open(socket);
+ return 0;
+}
+
+static int __init pci_socket_init(void)
+{
+ int sockets = pci_simple_probe(controller_list, MAX_SOCKETS, pci_socket_probe, NULL);
+
+ if (sockets <= 0)
+ return -1;
+ register_ss_entry(sockets, &pci_socket_operations);
+ return 0;
+}
+
+static void __exit pci_socket_exit(void)
+{
+ int i;
+
+ unregister_ss_entry(&pci_socket_operations);
+ for (i = 0; i < MAX_SOCKETS; i++) {
+ pci_socket_t *socket = pci_socket_array + i;
+
+ if (socket->op && socket->op->close)
+ socket->op->close(socket);
+ }
+}
+
+module_init(pci_socket_init);
+module_exit(pci_socket_exit);
--- /dev/null
+/*
+ * drivers/pcmcia/pci_socket.h
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ */
+
+struct pci_socket_ops;
+
+typedef struct pci_socket {
+ struct pci_dev *dev;
+ int irq;
+ void *base;
+ void (*handler)(void *, unsigned int);
+ void *info;
+ struct pci_socket_ops *op;
+} pci_socket_t;
+
+struct pci_socket_ops {
+ int (*open)(struct pci_socket *);
+ void (*close)(struct pci_socket *);
+
+ int (*inquire)(struct pci_socket *, socket_cap_t *cap);
+ int (*get_status)(struct pci_socket *, unsigned int *);
+ int (*get_socket)(struct pci_socket *, socket_state_t *);
+ int (*set_socket)(struct pci_socket *, socket_state_t *);
+ int (*get_io_map)(struct pci_socket *, struct pccard_io_map *);
+ int (*set_io_map)(struct pci_socket *, struct pccard_io_map *);
+ int (*get_mem_map)(struct pci_socket *, struct pccard_mem_map *);
+ int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *);
+ int (*get_bridge)(struct pci_socket *, struct cb_bridge_map *);
+ int (*set_bridge)(struct pci_socket *, struct cb_bridge_map *);
+ void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base);
+};
+
+extern struct pci_socket_ops yenta_operations;
/*====================================================================*/
-static int tcic_register_callback(u_short lsock, ss_callback_t *call)
+static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
{
- if (call == NULL) {
- socket_table[lsock].handler = NULL;
+ socket_table[lsock].handler = handler;
+ socket_table[lsock].info = info;
+ if (handler == NULL) {
MOD_DEC_USE_COUNT;
} else {
MOD_INC_USE_COUNT;
- socket_table[lsock].handler = call->handler;
- socket_table[lsock].info = call->info;
}
return 0;
} /* tcic_register_callback */
/*====================================================================*/
-static int tcic_get_status(u_short lsock, u_int *value)
+static int tcic_get_status(unsigned int lsock, u_int *value)
{
u_short psock = socket_table[lsock].psock;
u_char reg;
/*====================================================================*/
-static int tcic_inquire_socket(u_short lsock, socket_cap_t *cap)
+static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
{
*cap = tcic_cap;
return 0;
/*====================================================================*/
-static int tcic_get_socket(u_short lsock, socket_state_t *state)
+static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
{
u_short psock = socket_table[lsock].psock;
u_char reg;
/*====================================================================*/
-static int tcic_set_socket(u_short lsock, socket_state_t *state)
+static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
{
u_short psock = socket_table[lsock].psock;
u_char reg;
/*====================================================================*/
-static int tcic_get_io_map(u_short lsock, struct pccard_io_map *io)
+static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io)
{
u_short psock = socket_table[lsock].psock;
u_short base, ioctl;
/*====================================================================*/
-static int tcic_set_io_map(u_short lsock, struct pccard_io_map *io)
+static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
{
u_short psock = socket_table[lsock].psock;
u_int addr;
/*====================================================================*/
-static int tcic_get_mem_map(u_short lsock, struct pccard_mem_map *mem)
+static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
{
u_short psock = socket_table[lsock].psock;
u_short addr, ctl;
/*====================================================================*/
-static int tcic_set_mem_map(u_short lsock, struct pccard_mem_map *mem)
+static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
{
u_short psock = socket_table[lsock].psock;
u_short addr, ctl;
/*====================================================================*/
-int tcic_get_bridge(u_short sock, struct cb_bridge_map *m)
+int tcic_get_bridge(unsigned int sock, struct cb_bridge_map *m)
{
return -EINVAL;
}
#define tcic_set_bridge tcic_get_bridge
-void tcic_proc_setup(u_short sock, struct proc_dir_entry *base)
+void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
{
- return -EINVAL;
}
static struct pccard_operations tcic_operations = {
--- /dev/null
+/*
+ * Regular lowlevel cardbus driver ("yenta")
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+
+#include "yenta.h"
+#include "i82365.h"
+
+/* Don't ask.. */
+#define to_cycles(ns) ((ns)/120)
+#define to_ns(cycles) ((cycles)*120)
+
+/* Fixme! */
+static int yenta_inquire(pci_socket_t *socket, socket_cap_t *cap)
+{
+ cap->features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
+ cap->irq_mask = 0;
+ cap->map_size = 0;
+ cap->pci_irq = socket->irq;
+ cap->cardbus = 1;
+ cap->cb_bus = NULL;
+ cap->bus = NULL;
+
+printk("yenta_inquire()\n");
+
+ return 0;
+}
+
+/*
+Â * Silly interface. We convert the cardbus status to a internal status,
+ * and we probably really should keep it in cardbus status form and
+ * only convert for old-style 16-bit PCMCIA cards..
+ */
+static int yenta_get_status(pci_socket_t *socket, unsigned int *value)
+{
+ u32 state = cb_readl(socket, CB_SOCKET_STATE);
+ u8 status;
+ unsigned int val;
+
+ /* Convert from Yenta status to old-style status */
+ val = (state & CB_CARDSTS) ? SS_STSCHG : 0;
+ val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
+ val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
+ val |= (state & CB_CBCARD) ? SS_CARDBUS : 0;
+ val |= (state & CB_3VCARD) ? SS_3VCARD : 0;
+ val |= (state & CB_XVCARD) ? SS_XVCARD : 0;
+
+ /* Get the old compatibility status too.. */
+ status = exca_readb(socket, I365_STATUS);
+ val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
+ val |= (status & I365_CS_READY) ? SS_READY : 0;
+ val |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
+
+printk("yenta_get_status(%p)= %x\n", socket, val);
+
+ *value = val;
+ return 0;
+}
+
+static int yenta_Vcc_power(u32 control)
+{
+ switch ((control >> CB_VCCCTRL) & CB_PWRBITS) {
+ case CB_PWR5V: return 50;
+ case CB_PWR3V: return 33;
+ default: return 0;
+ }
+}
+
+static int yenta_Vpp_power(u32 control)
+{
+ switch ((control >> CB_VPPCTRL) & CB_PWRBITS) {
+ case CB_PWR12V: return 120;
+ case CB_PWR5V: return 50;
+ case CB_PWR3V: return 33;
+ default: return 0;
+ }
+}
+
+static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
+{
+ u32 control = cb_readl(socket, CB_SOCKET_CONTROL);
+ u8 reg;
+
+ state->Vcc = yenta_Vcc_power(control);
+ state->Vpp = yenta_Vpp_power(control);
+ state->io_irq = socket->irq;
+
+ reg = exca_readb(socket, I365_POWER);
+ state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
+ state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
+
+ reg = exca_readb(socket, I365_INTCTL);
+ state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
+ state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
+
+ reg = exca_readb(socket, I365_CSCINT);
+ state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
+ if (state->flags & SS_IOCARD) {
+ state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+ } else {
+ state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
+ state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
+ state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
+ }
+
+printk("yenta_get_socket(%p) = %d, %d\n", socket, state->Vcc, state->Vpp);
+
+ return 0;
+}
+
+static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
+{
+ u8 reg;
+ u16 bridge;
+ u32 control;
+
+printk("yenta_set_socket(%p, %d, %d, %x)\n", socket, state->Vcc, state->Vpp, state->flags);
+
+ bridge = config_readw(socket, CB_BRIDGE_CONTROL);
+ bridge &= ~CB_BRIDGE_CRST;
+ bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0;
+ config_writew(socket, CB_BRIDGE_CONTROL, bridge);
+
+ reg = socket->irq;
+ reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
+ reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
+ exca_writeb(socket, I365_INTCTL, reg);
+
+ reg = I365_PWR_NORESET;
+ control = 0; /* CB_STOPCLK ? Better power management */
+ switch (state->Vcc) {
+ case 33:
+ control |= CB_PWR3V << CB_VCCCTRL;
+ reg |= I365_VCC_5V;
+ break;
+ case 50:
+ control |= CB_PWR5V << CB_VCCCTRL;
+ reg |= I365_VCC_5V;
+ break;
+ }
+ switch (state->Vpp) {
+ case 33:
+ control |= CB_PWR3V << CB_VPPCTRL;
+ reg |= I365_VPP1_5V;
+ break;
+ case 50:
+ control |= CB_PWR5V << CB_VPPCTRL;
+ reg |= I365_VPP1_5V;
+ break;
+ case 120:
+ control |= CB_PWR12V << CB_VPPCTRL;
+ reg |= I365_VPP1_12V;
+ break;
+ }
+ cb_writel(socket, CB_SOCKET_CONTROL, control);
+
+ reg |= (state->flags & SS_PWR_AUTO) ? I365_PWR_AUTO : 0;
+ reg |= (state->flags & SS_OUTPUT_ENA) ? I365_PWR_OUT : 0;
+ if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
+ exca_writeb(socket, I365_POWER, reg);
+
+ reg = socket->irq;
+ reg |= (state->csc_mask & SS_DETECT) ? I365_CSC_DETECT : 0;
+ if (state->flags & SS_IOCARD) {
+ reg |= (state->csc_mask & SS_STSCHG) ? I365_CSC_STSCHG : 0;
+ } else {
+ reg |= (state->csc_mask & SS_BATDEAD) ? I365_CSC_BVD1 : 0;
+ reg |= (state->csc_mask & SS_BATWARN) ? I365_CSC_BVD2 : 0;
+ reg |= (state->csc_mask & SS_READY) ? I365_CSC_READY : 0;
+ }
+ exca_writeb(socket, I365_CSCINT, reg);
+ exca_readb(socket, I365_CSC);
+
+ return 0;
+}
+
+static int yenta_get_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+{
+ int map;
+ unsigned char ioctl, addr;
+
+ map = io->map;
+ if (map > 1)
+ return -EINVAL;
+
+ io->start = exca_readw(socket, I365_IO(map)+I365_W_START);
+ io->stop = exca_readw(socket, I365_IO(map)+I365_W_STOP);
+
+ ioctl = exca_readb(socket, I365_IOCTL);
+ addr = exca_readb(socket, I365_ADDRWIN);
+ io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
+ io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
+ io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
+ io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
+ io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
+
+printk("yenta_get_io_map(%d) = %x, %x, %x\n", map, io->start, io->stop, io->flags);
+
+ return 0;
+}
+
+static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+{
+ int map;
+ unsigned char ioctl, addr, enable;
+
+ map = io->map;
+
+printk("yenta_set_io_map(%d, %x, %x, %x)\n", map, io->start, io->stop, io->flags);
+
+ if (map > 1)
+ return -EINVAL;
+
+ enable = I365_ENA_IO(map);
+ addr = exca_readb(socket, I365_ADDRWIN);
+
+ /* Disable the window before changing it.. */
+ if (addr & enable) {
+ addr &= ~enable;
+ exca_writeb(socket, I365_ADDRWIN, addr);
+ }
+
+ exca_writew(socket, I365_IO(map)+I365_W_START, io->start);
+ exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop);
+
+ ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map);
+ if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
+ if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
+ if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
+ exca_writeb(socket, I365_IOCTL, ioctl);
+
+ if (io->flags & MAP_ACTIVE)
+ exca_writeb(socket, I365_ADDRWIN, addr | enable);
+ return 0;
+}
+
+static int yenta_get_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+{
+ int map;
+ unsigned char addr;
+ unsigned int start, stop, page, offset;
+
+ map = mem->map;
+ if (map > 4)
+ return -EINVAL;
+
+ addr = exca_readb(socket, I365_ADDRWIN);
+ mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
+
+ start = exca_readw(socket, I365_MEM(map) + I365_W_START);
+ mem->flags |= (start & I365_MEM_16BIT) ? MAP_16BIT : 0;
+ mem->flags |= (start & I365_MEM_0WS) ? MAP_0WS : 0;
+ start = (start & 0x0fff) << 12;
+
+ stop = exca_readw(socket, I365_MEM(map) + I365_W_STOP);
+ mem->speed = (stop & I365_MEM_WS0) ? 1 : 0;
+ mem->speed += (stop & I365_MEM_WS1) ? 2 : 0;
+ mem->speed = to_ns(mem->speed);
+ stop = ((u_long)(stop & 0x0fff) << 12) + 0x0fff;
+
+ offset = exca_readw(socket, I365_MEM(map) + I365_W_OFF);
+ mem->flags |= (offset & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
+ mem->flags |= (offset & I365_MEM_REG) ? MAP_ATTRIB : 0;
+ offset = ((offset & 0x3fff) << 12) + start;
+ mem->card_start = offset & 0x3ffffff;
+
+ page = exca_readb(socket, CB_MEM_PAGE(map)) << 24;
+ mem->sys_start = start + page;
+ mem->sys_stop = start + page;
+
+printk("yenta_get_map(%d) = %lx, %lx, %x\n", map, mem->sys_start, mem->sys_stop, mem->card_start);
+
+ return 0;
+}
+
+static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+{
+ int map;
+ unsigned char addr, enable;
+ unsigned int start, stop, card_start;
+ unsigned short word;
+
+ map = mem->map;
+ start = mem->sys_start;
+ stop = mem->sys_stop;
+ card_start = mem->card_start;
+
+printk("yenta_set_map(%d, %x, %x, %x)\n", map, start, stop, card_start);
+
+ if (map > 4 || start > stop || ((start ^ stop) >> 24) || (card_start >> 26) || mem->speed > 1000)
+ return -EINVAL;
+
+ enable = I365_ENA_MEM(map);
+ addr = exca_readb(socket, I365_ADDRWIN);
+ if (addr & enable) {
+ addr &= ~enable;
+ exca_writeb(socket, I365_ADDRWIN, addr);
+ }
+
+ word = (start >> 12) & 0x0fff;
+ if (mem->flags & MAP_16BIT)
+ word |= I365_MEM_16BIT;
+ if (mem->flags & MAP_0WS)
+ word |= I365_MEM_0WS;
+ exca_writew(socket, I365_MEM(map) + I365_W_START, word);
+
+ word = (stop >> 12) & 0x0fff;
+ switch (to_cycles(mem->speed)) {
+ case 0: break;
+ case 1: word |= I365_MEM_WS0; break;
+ case 2: word |= I365_MEM_WS1; break;
+ default: word |= I365_MEM_WS1 | I365_MEM_WS0; break;
+ }
+ exca_writew(socket, I365_MEM(map) + I365_W_STOP, word);
+
+ word = ((card_start - start) >> 12) & 0x3fff;
+ if (mem->flags & MAP_WRPROT)
+ word |= I365_MEM_WRPROT;
+ if (mem->flags & MAP_ATTRIB)
+ word |= I365_MEM_REG;
+ exca_writew(socket, I365_MEM(map) + I365_W_OFF, word);
+
+ if (mem->flags & MAP_ACTIVE)
+ exca_writeb(socket, I365_ADDRWIN, addr | enable);
+ return 0;
+}
+
+static int yenta_get_bridge(pci_socket_t *socket, struct cb_bridge_map *m)
+{
+ printk("yenta_get_bridge() called\n");
+ return -EINVAL;
+}
+
+static int yenta_set_bridge(pci_socket_t *socket, struct cb_bridge_map *m)
+{
+ printk("yenta_set_bridge() called\n");
+ return -EINVAL;
+}
+
+static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
+{
+ /* Not done yet */
+}
+
+static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ pci_socket_t *sock = (pci_socket_t *) dev_id;
+ u32 event = readl(sock->base + CB_SOCKET_EVENT);
+
+ /* Clear interrupt status for the event */
+ writel(event, sock->base +CB_SOCKET_EVENT);
+
+ printk("Socket interrupt event %08x\n", event);
+}
+
+/*
+ * Initialize a cardbus controller. Make sure we have a usable
+ * interrupt, and that we can map the cardbus area. Fill in the
+ * socket information structure..
+ */
+static int yenta_open(pci_socket_t *socket)
+{
+ struct pci_dev *dev = socket->dev;
+
+ /*
+ * Do some basic sanity checking..
+ */
+ if (pci_enable_device(dev)) {
+ printk("Unable to enable device\n");
+ return -1;
+ }
+ if (!dev->irq) {
+ printk("No cardbus irq!\n");
+ return -1;
+ }
+ if (!dev->resource[0].start) {
+ printk("No cardbus resource!\n");
+ return -1;
+ }
+
+ /*
+ * Ok, start setup.. Map the cardbus registers,
+ * and request the IRQ.
+ */
+ socket->base = ioremap(dev->resource[0].start, 0x1000);
+ if (!socket->base)
+ return -1;
+ if (request_irq(dev->irq, yenta_interrupt, SA_SHIRQ, dev->name, socket))
+ return -1;
+ socket->irq = dev->irq;
+
+ /* Enable all events */
+ writel(0x0f, socket->base + 4);
+
+ printk("Socket status: %08x\n", readl(socket->base + 8));
+ return 0;
+}
+
+/*
+ * Close it down - release our resources and go home..
+ */
+static void yenta_close(pci_socket_t *sock)
+{
+ if (sock->irq)
+ free_irq(sock->irq, sock);
+ if (sock->base)
+ iounmap(sock->base);
+}
+
+struct pci_socket_ops yenta_operations = {
+ yenta_open,
+ yenta_close,
+ yenta_inquire,
+ yenta_get_status,
+ yenta_get_socket,
+ yenta_set_socket,
+ yenta_get_io_map,
+ yenta_set_io_map,
+ yenta_get_mem_map,
+ yenta_set_mem_map,
+ yenta_get_bridge,
+ yenta_set_bridge,
+ yenta_proc_setup
+};
+#ifndef __YENTA_H
+#define __YENTA_H
+
+#include <asm/io.h>
+#include "pci_socket.h"
+
+/*
+ * Generate easy-to-use ways of reading a cardbus sockets
+ * regular memory space ("cb_xxx"), configuration space
+ * ("config_xxx") and compatibility space ("exca_xxxx")
+ */
+
+#define cb_readb(sock,reg) readb((sock)->base + (reg))
+#define cb_readw(sock,reg) readw((sock)->base + (reg))
+#define cb_readl(sock,reg) readl((sock)->base + (reg))
+#define cb_writeb(sock,reg,val) writeb((val), (sock)->base + (reg))
+#define cb_writew(sock,reg,val) writew((val), (sock)->base + (reg))
+#define cb_writel(sock,reg,val) writel((val), (sock)->base + (reg))
+
+#define config_readb(sock,offset) ({ __u8 __val; pci_read_config_byte((sock)->dev, (offset), &__val); __val; })
+#define config_readw(sock,offset) ({ __u16 __val; pci_read_config_word((sock)->dev, (offset), &__val); __val; })
+#define config_readl(sock,offset) ({ __u32 __val; pci_read_config_dword((sock)->dev, (offset), &__val); __val; })
+
+#define config_writeb(sock,offset,val) pci_write_config_byte((sock)->dev, (offset), (val))
+#define config_writew(sock,offset,val) pci_write_config_word((sock)->dev, (offset), (val))
+#define config_writel(sock,offset,val) pci_write_config_dword((sock)->dev, (offset), (val))
+
+#define exca_readb(sock,reg) cb_readb((sock),(reg)+0x0800)
+#define exca_readw(sock,reg) cb_readw((sock),(reg)+0x0800)
+#define exca_readl(sock,reg) cb_readl((sock),(reg)+0x0800)
+
+#define exca_writeb(sock,reg,val) cb_writeb((sock),(reg)+0x0800,(val))
+#define exca_writew(sock,reg,val) cb_writew((sock),(reg)+0x0800,(val))
+#define exca_writel(sock,reg,val) cb_writel((sock),(reg)+0x0800,(val))
+
+#define CB_SOCKET_EVENT 0x00
+#define CB_CSTSEVENT 0x00000001 /* Card status event */
+#define CB_CD1EVENT 0x00000002 /* Card detect 1 change event */
+#define CB_CD2EVENT 0x00000004 /* Card detect 2 change event */
+#define CB_PWREVENT 0x00000008 /* PWRCYCLE change event */
+
+#define CB_SOCKET_MASK 0x04
+#define CB_CSTSMASK 0x00000001 /* Card status mask */
+#define CB_CDMASK 0x00000006 /* Card detect 1&2 mask */
+#define CB_PWRMASK 0x00000008 /* PWRCYCLE change mask */
+
+#define CB_SOCKET_STATE 0x08
+#define CB_CARDSTS 0x00000001 /* CSTSCHG status */
+#define CB_CDETECT1 0x00000002 /* Card detect status 1 */
+#define CB_CDETECT2 0x00000004 /* Card detect status 2 */
+#define CB_PWRCYCLE 0x00000008 /* Socket powered */
+#define CB_16BITCARD 0x00000010 /* 16-bit card detected */
+#define CB_CBCARD 0x00000020 /* CardBus card detected */
+#define CB_IREQCINT 0x00000040 /* READY(xIRQ)/xCINT high */
+#define CB_NOTACARD 0x00000080 /* Unrecognizable PC card detected */
+#define CB_DATALOST 0x00000100 /* Potential data loss due to card removal */
+#define CB_BADVCCREQ 0x00000200 /* Invalid Vcc request by host software */
+#define CB_5VCARD 0x00000400 /* Card Vcc at 5.0 volts? */
+#define CB_3VCARD 0x00000800 /* Card Vcc at 3.3 volts? */
+#define CB_XVCARD 0x00001000 /* Card Vcc at X.X volts? */
+#define CB_YVCARD 0x00002000 /* Card Vcc at Y.Y volts? */
+#define CB_5VSOCKET 0x10000000 /* Socket Vcc at 5.0 volts? */
+#define CB_3VSOCKET 0x20000000 /* Socket Vcc at 3.3 volts? */
+#define CB_XVSOCKET 0x40000000 /* Socket Vcc at X.X volts? */
+#define CB_YVSOCKET 0x80000000 /* Socket Vcc at Y.Y volts? */
+
+#define CB_SOCKET_FORCE 0x0C
+#define CB_FCARDSTS 0x00000001 /* Force CSTSCHG */
+#define CB_FCDETECT1 0x00000002 /* Force CD1EVENT */
+#define CB_FCDETECT2 0x00000004 /* Force CD2EVENT */
+#define CB_FPWRCYCLE 0x00000008 /* Force PWREVENT */
+#define CB_F16BITCARD 0x00000010 /* Force 16-bit PCMCIA card */
+#define CB_FCBCARD 0x00000020 /* Force CardBus line */
+#define CB_FNOTACARD 0x00000080 /* Force NOTACARD */
+#define CB_FDATALOST 0x00000100 /* Force data lost */
+#define CB_FBADVCCREQ 0x00000200 /* Force bad Vcc request */
+#define CB_F5VCARD 0x00000400 /* Force 5.0 volt card */
+#define CB_F3VCARD 0x00000800 /* Force 3.3 volt card */
+#define CB_FXVCARD 0x00001000 /* Force X.X volt card */
+#define CB_FYVCARD 0x00002000 /* Force Y.Y volt card */
+#define CB_CVSTEST 0x00004000 /* Card VS test */
+
+#define CB_SOCKET_CONTROL 0x10
+#define CB_VPPCTRL 0 /* Shift for Vpp */
+#define CB_VCCCTRL 4 /* Shift for Vcc */
+#define CB_STOPCLK 0x00000080 /* CLKRUN can slow CB clock when idle */
+
+#define CB_PWRBITS 0x7
+#define CB_PWROFF 0x0
+#define CB_PWR12V 0x1 /* Only valid for Vpp */
+#define CB_PWR5V 0x2
+#define CB_PWR3V 0x3
+#define CB_PWRXV 0x4
+#define CB_PWRYV 0x5
+
+#define CB_SOCKET_POWER 0x20
+#define CB_SKTACCES 0x02000000 /* A PC card access has occurred (clear on read) */
+#define CB_SKTMODE 0x01000000 /* Clock frequency has changed (clear on read) */
+#define CB_CLKCTRLEN 0x00010000 /* Clock control enabled (RW) */
+#define CB_CLKCTRL 0x00000001 /* Stop(0) or slow(1) CB clock (RW) */
+
+/*
+ * Cardbus configuration space
+ */
+#define CB_BRIDGE_CONTROL 0x3e
+#define CB_BRIDGE_CPERREN 0x00000001
+#define CB_BRIDGE_CSERREN 0x00000002
+#define CB_BRIDGE_ISAEN 0x00000004
+#define CB_BRIDGE_VGAEN 0x00000008
+#define CB_BRIDGE_MABTMODE 0x00000020
+#define CB_BRIDGE_CRST 0x00000040
+#define CB_BRIDGE_INTR 0x00000080
+#define CB_BRIDGE_PREFETCH0 0x00000100
+#define CB_BRIDGE_PREFETCH1 0x00000200
+#define CB_BRIDGE_POSTEN 0x00000400
+
/*
- * yenta.h 1.16 1999/10/25 20:03:34
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
- *
- * The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL. If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the MPL or the GPL.
+ * ExCA area extensions in Yenta
*/
+#define CB_MEM_PAGE(map) (0x40 + (map))
-#ifndef _LINUX_YENTA_H
-#define _LINUX_YENTA_H
-
-/* PCI Configuration Registers */
-
-#define PCI_STATUS_CAPLIST 0x10
-#define PCI_CB_CAPABILITY_POINTER 0x14 /* 8 bit */
-#define PCI_CAPABILITY_ID 0x00 /* 8 bit */
-#define PCI_CAPABILITY_PM 0x01
-#define PCI_NEXT_CAPABILITY 0x01 /* 8 bit */
-#define PCI_PM_CAPABILITIES 0x02 /* 16 bit */
-#define PCI_PMCAP_PME_D3COLD 0x8000
-#define PCI_PMCAP_PME_D3HOT 0x4000
-#define PCI_PMCAP_PME_D2 0x2000
-#define PCI_PMCAP_PME_D1 0x1000
-#define PCI_PMCAP_PME_D0 0x0800
-#define PCI_PMCAP_D2_CAP 0x0400
-#define PCI_PMCAP_D1_CAP 0x0200
-#define PCI_PMCAP_DYN_DATA 0x0100
-#define PCI_PMCAP_DSI 0x0020
-#define PCI_PMCAP_AUX_PWR 0x0010
-#define PCI_PMCAP_PMECLK 0x0008
-#define PCI_PMCAP_VERSION_MASK 0x0007
-#define PCI_PM_CONTROL_STATUS 0x04 /* 16 bit */
-#define PCI_PMCS_PME_STATUS 0x8000
-#define PCI_PMCS_DATASCALE_MASK 0x6000
-#define PCI_PMCS_DATASCALE_SHIFT 13
-#define PCI_PMCS_DATASEL_MASK 0x1e00
-#define PCI_PMCS_DATASEL_SHIFT 9
-#define PCI_PMCS_PME_ENABLE 0x0100
-#define PCI_PMCS_PWR_STATE_MASK 0x0003
-#define PCI_PMCS_PWR_STATE_D0 0x0000
-#define PCI_PMCS_PWR_STATE_D1 0x0001
-#define PCI_PMCS_PWR_STATE_D2 0x0002
-#define PCI_PMCS_PWR_STATE_D3 0x0003
-#define PCI_PM_BRIDGE_EXT 0x06 /* 8 bit */
-#define PCI_PM_DATA 0x07 /* 8 bit */
-
-#define CB_PRIMARY_BUS 0x18 /* 8 bit */
-#define CB_CARDBUS_BUS 0x19 /* 8 bit */
-#define CB_SUBORD_BUS 0x1a /* 8 bit */
-#define CB_LATENCY_TIMER 0x1b /* 8 bit */
-
-#define CB_MEM_BASE(m) (0x1c + 8*(m))
-#define CB_MEM_LIMIT(m) (0x20 + 8*(m))
-#define CB_IO_BASE(m) (0x2c + 8*(m))
-#define CB_IO_LIMIT(m) (0x30 + 8*(m))
-
-#define CB_BRIDGE_CONTROL 0x3e /* 16 bit */
-#define CB_BCR_PARITY_ENA 0x0001
-#define CB_BCR_SERR_ENA 0x0002
-#define CB_BCR_ISA_ENA 0x0004
-#define CB_BCR_VGA_ENA 0x0008
-#define CB_BCR_MABORT 0x0020
-#define CB_BCR_CB_RESET 0x0040
-#define CB_BCR_ISA_IRQ 0x0080
-#define CB_BCR_PREFETCH(m) (0x0100 << (m))
-#define CB_BCR_WRITE_POST 0x0400
-
-#define CB_LEGACY_MODE_BASE 0x44
-
-/* Memory mapped registers */
-
-#define CB_SOCKET_EVENT 0x0000
-#define CB_SE_CSTSCHG 0x00000001
-#define CB_SE_CCD1 0x00000002
-#define CB_SE_CCD2 0x00000004
-#define CB_SE_PWRCYCLE 0x00000008
-
-#define CB_SOCKET_MASK 0x0004
-#define CB_SM_CSTSCHG 0x00000001
-#define CB_SM_CCD 0x00000006
-#define CB_SM_PWRCYCLE 0x00000008
-
-#define CB_SOCKET_STATE 0x0008
-#define CB_SS_CSTSCHG 0x00000001
-#define CB_SS_CCD1 0x00000002
-#define CB_SS_CCD2 0x00000004
-#define CB_SS_PWRCYCLE 0x00000008
-#define CB_SS_16BIT 0x00000010
-#define CB_SS_32BIT 0x00000020
-#define CB_SS_CINT 0x00000040
-#define CB_SS_BADCARD 0x00000080
-#define CB_SS_DATALOST 0x00000100
-#define CB_SS_BADVCC 0x00000200
-#define CB_SS_5VCARD 0x00000400
-#define CB_SS_3VCARD 0x00000800
-#define CB_SS_XVCARD 0x00001000
-#define CB_SS_YVCARD 0x00002000
-#define CB_SS_5VSOCKET 0x10000000
-#define CB_SS_3VSOCKET 0x20000000
-#define CB_SS_XVSOCKET 0x40000000
-#define CB_SS_YVSOCKET 0x80000000
-
-#define CB_SOCKET_FORCE 0x000c
-#define CB_SF_CVSTEST 0x00004000
-
-#define CB_SOCKET_CONTROL 0x0010
-#define CB_SC_VPP_MASK 0x00000007
-#define CB_SC_VPP_OFF 0x00000000
-#define CB_SC_VPP_12V 0x00000001
-#define CB_SC_VPP_5V 0x00000002
-#define CB_SC_VPP_3V 0x00000003
-#define CB_SC_VPP_XV 0x00000004
-#define CB_SC_VPP_YV 0x00000005
-#define CB_SC_VCC_MASK 0x00000070
-#define CB_SC_VCC_OFF 0x00000000
-#define CB_SC_VCC_5V 0x00000020
-#define CB_SC_VCC_3V 0x00000030
-#define CB_SC_VCC_XV 0x00000040
-#define CB_SC_VCC_YV 0x00000050
-#define CB_SC_CCLK_STOP 0x00000080
-
-#define CB_SOCKET_POWER 0x0020
-#define CB_SP_CLK_CTRL 0x00000001
-#define CB_SP_CLK_CTRL_ENA 0x00010000
-#define CB_SP_CLK_MODE 0x01000000
-#define CB_SP_ACCESS 0x02000000
-
-/* Address bits 31..24 for memory windows for 16-bit cards,
- accessable only by memory mapping the 16-bit register set */
-#define CB_MEM_PAGE(map) (0x40 + (map))
-
-#endif /* _LINUX_YENTA_H */
+#endif
dep_tristate ' UHCI (Intel PIIX4, VIA, and others) support' CONFIG_USB_UHCI \
$CONFIG_USB
- dep_tristate ' OHCI-HCD (Compaq, iMacs, OPTi, and some others) support' \
+ dep_tristate ' OHCI-HCD (Compaq, iMacs, OPTi, SiS, and others) support' \
CONFIG_USB_OHCI_HCD $CONFIG_USB
comment 'Miscellaneous USB options'
dep_tristate ' USB HP scanner support' CONFIG_USB_HP_SCANNER $CONFIG_USB
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB
dep_tristate ' USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB
- dep_tristate ' USB Belkin and Peracom serial support' CONFIG_USB_SERIAL $CONFIG_USB
+ dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
dep_tristate ' USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB
dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
dep_tristate ' USB SCSI (mass storage) support' CONFIG_USB_SCSI $CONFIG_USB
int usb_acm_init(void);
+void usb_acm_cleanup(void);
int usb_audio_init(void);
+int usb_cpia_init(void);
+void usb_cpia_cleanup(void);
+int usb_dc2xx_init(void);
+void usb_dc2xx_cleanup(void);
int usb_hub_init(void);
void usb_hub_cleanup(void);
int usb_kbd_init(void);
+void usb_kbd_cleanup(void);
void usb_major_init(void);
void usb_major_cleanup(void);
+int usb_mouse_init(void);
void usb_mouse_cleanup(void);
int usb_hp_scanner_init(void);
void usb_hp_scanner_cleanup(void);
int usb_printer_init(void);
-int proc_usb_init (void);
-void proc_usb_cleanup (void);
int usb_scsi_init(void);
-int usb_serial_init (void);
+int usb_serial_init(void);
int dabusb_init(void);
void dabusb_cleanup(void);
+int proc_usb_init(void);
+void proc_usb_cleanup(void);
#define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT) /* should not take 1 minute a page! */
#define BIG_BUF_SIZE 8192
+#define SUBCLASS_PRINTERS 1
+#define PROTOCOL_UNIDIRECTIONAL 1
+#define PROTOCOL_BIDIRECTIONAL 2
/*
* USB Printer Requests
if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
USB_PRINTER_REQ_GET_PORT_STATUS,
USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
- 0, 0, &status, 1, HZ)) {
+ 0, 0, &status, sizeof(status), HZ)) {
return 0;
}
return status;
else if ((status & LP_POUTPA)) {
if (last != LP_POUTPA) {
last = LP_POUTPA;
- printk(KERN_INFO "usblp%d out of paper\n", p->minor);
+ printk(KERN_INFO "usblp%d out of paper (%x)\n", p->minor, status);
}
} else if (!(status & LP_PSELECD)) {
if (last != LP_PSELECD) {
last = LP_PSELECD;
- printk(KERN_INFO "usblp%d off-line\n", p->minor);
+ printk(KERN_INFO "usblp%d off-line (%x)\n", p->minor, status);
}
} else {
if (last != LP_PERRORP) {
last = LP_PERRORP;
- printk(KERN_INFO "usblp%d on fire\n", p->minor);
+ printk(KERN_INFO "usblp%d on fire (%x)\n", p->minor, status);
}
}
p->last_error = last;
-
return status;
}
0, 0, NULL, 0, HZ);
}
-static int open_printer(struct inode * inode, struct file * file)
+static int open_printer(struct inode *inode, struct file *file)
{
struct pp_usb_data *p;
return 0;
}
-static int close_printer(struct inode * inode, struct file * file)
+static int close_printer(struct inode *inode, struct file *file)
{
struct pp_usb_data *p = file->private_data;
return 0;
}
-static ssize_t write_printer(struct file * file,
- const char * buffer, size_t count, loff_t *ppos)
+static ssize_t write_printer(struct file *file,
+ const char *buffer, size_t count, loff_t *ppos)
{
struct pp_usb_data *p = file->private_data;
unsigned long copy_size;
return bytes_written ? bytes_written : -EIO;
}
-static ssize_t read_printer(struct file * file,
- char * buffer, size_t count, loff_t *ppos)
+static ssize_t read_printer(struct file *file,
+ char *buffer, size_t count, loff_t *ppos)
{
struct pp_usb_data *p = file->private_data;
int read_count = 0;
}
if (!p->pusb_dev)
return -ENODEV;
- this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
+ this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
result = usb_bulk_msg(p->pusb_dev,
usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep),
buf, this_read, &partial, HZ*20);
return read_count;
}
-static void * printer_probe(struct usb_device *dev, unsigned int ifnum)
+static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_interface_descriptor *interface;
struct pp_usb_data *pp;
/* Let's be paranoid (for the moment). */
if (interface->bInterfaceClass != USB_CLASS_PRINTER ||
- interface->bInterfaceSubClass != 1 ||
- (interface->bInterfaceProtocol != 2 && interface->bInterfaceProtocol != 1) ||
+ interface->bInterfaceSubClass != SUBCLASS_PRINTERS ||
+ (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL &&
+ interface->bInterfaceProtocol != PROTOCOL_UNIDIRECTIONAL) ||
interface->bNumEndpoints > 2) {
return NULL;
}
break;
}
if (i >= MAX_PRINTERS) {
- printk("No minor table space available for USB Printer\n");
+ printk(KERN_ERR "No minor table space available for USB Printer\n");
return NULL;
}
memset(pp, 0, sizeof(struct pp_usb_data));
minor_data[i] = PPDATA(pp);
- minor_data[i]->minor = i;
- minor_data[i]->pusb_dev = dev;
- minor_data[i]->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
- if (interface->bInterfaceProtocol != 2) /* if not bidirectional */
- minor_data[i]->noinput = 1;
+ pp->minor = i;
+ pp->pusb_dev = dev;
+ pp->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
+ if (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL)
+ pp->noinput = 1;
- minor_data[i]->bulk_out_index =
+ pp->bulk_out_index =
((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
== USB_DIR_OUT) ? 0 : 1;
- minor_data[i]->bulk_in_index = minor_data[i]->noinput ? -1 :
- (minor_data[i]->bulk_out_index == 0) ? 1 : 0;
- minor_data[i]->bulk_in_ep = minor_data[i]->noinput ? -1 :
- interface->endpoint[minor_data[i]->bulk_in_index].bEndpointAddress &
+ pp->bulk_in_index = pp->noinput ? -1 :
+ (pp->bulk_out_index == 0) ? 1 : 0;
+ pp->bulk_in_ep = pp->noinput ? -1 :
+ interface->endpoint[pp->bulk_in_index].bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
- minor_data[i]->bulk_out_ep =
- interface->endpoint[minor_data[i]->bulk_out_index].bEndpointAddress &
+ pp->bulk_out_ep =
+ interface->endpoint[pp->bulk_out_index].bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
- if (interface->bInterfaceProtocol == 2) { /* if bidirectional */
- minor_data[i]->maxin =
- interface->endpoint[minor_data[i]->bulk_in_index].wMaxPacketSize;
+ if (interface->bInterfaceProtocol == PROTOCOL_BIDIRECTIONAL) {
+ pp->maxin =
+ interface->endpoint[pp->bulk_in_index].wMaxPacketSize;
}
- printk(KERN_INFO "USB Printer Summary:\n");
- printk(KERN_INFO "index=%d, maxout=%d, noinput=%d\n",
- i, minor_data[i]->maxout, minor_data[i]->noinput);
+ printk(KERN_INFO "usblp%d Summary:\n", pp->minor);
+ printk(KERN_INFO "index=%d, maxout=%d, noinput=%d, maxin=%d\n",
+ i, pp->maxout, pp->noinput, pp->maxin);
printk(KERN_INFO "bulk_in_ix=%d, bulk_in_ep=%d, bulk_out_ix=%d, bulk_out_ep=%d\n",
- minor_data[i]->bulk_in_index,
- minor_data[i]->bulk_in_ep,
- minor_data[i]->bulk_out_index,
- minor_data[i]->bulk_out_ep);
+ pp->bulk_in_index,
+ pp->bulk_in_ep,
+ pp->bulk_out_index,
+ pp->bulk_out_ep);
-#if 0
+#if 1
{
__u8 status;
- __u8 ieee_id[64];
+ __u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */
+ int length = be16_to_cpup((__u16 *)ieee_id);
/* Let's get the device id if possible. */
if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
ieee_id[ieee_id[1]+2] = '\0';
else
ieee_id[sizeof(ieee_id)-1] = '\0';
- printk(KERN_INFO " USB Printer ID is %s\n",
- &ieee_id[2]);
+ printk(KERN_INFO " usblp%d Device ID length=%d, string=%s\n",
+ pp->minor, length, &ieee_id[2]);
}
+ else
+ printk(KERN_INFO " usblp%d: error reading IEEE-1284 Device ID\n",
+ pp->minor);
+
status = printer_read_status(PPDATA(pp));
- printk(KERN_INFO " Status is %s,%s,%s\n",
- (status & LP_PSELECD) ? "Selected" : "Not Selected",
- (status & LP_POUTPA) ? "No Paper" : "Paper",
- (status & LP_PERRORP) ? "No Error" : "Error");
+ printk(KERN_INFO " usblp%d Probe Status is %x: %s,%s,%s\n",
+ pp->minor, status,
+ (status & LP_PSELECD) ? "Selected" : "Not Selected",
+ (status & LP_POUTPA) ? "No Paper" : "Paper",
+ (status & LP_PERRORP) ? "No Error" : "Error");
}
#endif
return pp;
* index = parent's connector number;
* count = device count at this level
*/
- /* do not dump descriptors for root hub, but we do want to see the bandwidth */
- if (usbdev->devnum == 1)
+ /* If this is the root hub, display the bandwidth information */
+ if (level == 0)
start += sprintf(start, format_bandwidth, bus->bandwidth_allocated,
FRAME_TIME_MAX_USECS_ALLOC,
(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
- else
- start = usb_dump_desc(start, end, usbdev);
+ /* show the descriptor information for this device */
+ start = usb_dump_desc(start, end, usbdev);
if (start > end)
return start + sprintf(start, "(truncated)\n");
+
/* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) {
if (start > end)
proc_usb_cleanup ();
#endif
usb_hub_cleanup();
-#ifndef MODULE
+#ifndef MODULE
# ifdef CONFIG_USB_MOUSE
usb_mouse_cleanup();
# endif
# ifdef CONFIG_USB_DABUSB
dabusb_cleanup();
# endif
+# ifdef CONFIG_USB_KBD
+ usb_kbd_cleanup();
+# endif
+# ifdef CONFIG_USB_ACM
+ usb_acm_cleanup();
+# endif
+# ifdef CONFIG_USB_CPIA
+ usb_cpia_cleanup();
+# endif
+# ifdef CONFIG_USB_DC2XX
+ usb_dc2xx_cleanup();
+# endif
#endif
}
*
* See README.serial for more information on using this driver.
*
+ * version 0.2.3 (12/21/99) gkh
+ * Added initial support for the Connect Tech WhiteHEAT converter.
+ * Incremented the number of ports in expectation of getting the
+ * WhiteHEAT to work properly (4 ports per connection).
+ * Added notification on insertion and removal of what port the
+ * device is/was connected to (and what kind of device it was).
+ *
* version 0.2.2 (12/16/99) gkh
* Changed major number to the new allocated number. We're legal now!
*
#define BELKIN_SERIAL_CONVERTER 0x8007
#define PERACOM_VENDOR_ID 0x0565
#define PERACOM_SERIAL_CONVERTER 0x0001
+#define CONNECT_TECH_VENDOR_ID 0x0710
+#define CONNECT_TECH_WHITE_HEAT_ID 0x0001
#define SERIAL_MAJOR 188 /* Nice legal number now */
-
-#define NUM_PORTS 4 /* Have to pick a number for now. Need to look */
- /* into dynamically creating them at insertion time. */
+#define NUM_PORTS 16 /* Actually we are allowed 255, but this is good for now */
static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
static void serial_unthrottle (struct tty_struct * tty);
-/* function prototypes for the eTek type converters (this included Belkin and Peracom) */
-static int etek_serial_open (struct tty_struct *tty, struct file * filp);
-static void etek_serial_close (struct tty_struct *tty, struct file * filp);
-static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch);
-static int etek_write_room (struct tty_struct *tty);
-static int etek_chars_in_buffer (struct tty_struct *tty);
-static void etek_throttle (struct tty_struct * tty);
-static void etek_unthrottle (struct tty_struct * tty);
-
-
-/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
-static int generic_serial_open (struct tty_struct *tty, struct file * filp);
-static void generic_serial_close (struct tty_struct *tty, struct file * filp);
-static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch);
-static int generic_write_room (struct tty_struct *tty);
-static int generic_chars_in_buffer (struct tty_struct *tty);
-
-
/* This structure defines the individual serial converter. */
struct usb_serial_device_type {
char *name;
int (*chars_in_buffer)(struct tty_struct *tty);
void (*throttle)(struct tty_struct * tty);
void (*unthrottle)(struct tty_struct * tty);
-
};
+/* function prototypes for the eTek type converters (this included Belkin and Peracom) */
+static int etek_serial_open (struct tty_struct *tty, struct file *filp);
+static void etek_serial_close (struct tty_struct *tty, struct file *filp);
+static int etek_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch);
+static int etek_write_room (struct tty_struct *tty);
+static int etek_chars_in_buffer (struct tty_struct *tty);
+
/* All of the device info needed for the Belkin Serial Converter */
static __u16 belkin_vendor_id = BELKIN_VENDOR_ID;
static __u16 belkin_product_id = BELKIN_SERIAL_CONVERTER;
etek_serial_put_char,
etek_write_room,
etek_chars_in_buffer,
- etek_throttle,
- etek_unthrottle
+ NULL,
+ NULL
};
/* All of the device info needed for the Peracom Serial Converter */
etek_serial_put_char,
etek_write_room,
etek_chars_in_buffer,
- etek_throttle,
- etek_unthrottle
+ NULL,
+ NULL
+};
+
+
+/* function prototypes for the Connect Tech WhiteHEAT serial converter */
+static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp);
+static void whiteheat_serial_close (struct tty_struct *tty, struct file *filp);
+static int whiteheat_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void whiteheat_serial_put_char (struct tty_struct *tty, unsigned char ch);
+static int whiteheat_write_room (struct tty_struct *tty);
+static int whiteheat_chars_in_buffer (struct tty_struct *tty);
+static void whiteheat_throttle (struct tty_struct *tty);
+static void whiteheat_unthrottle (struct tty_struct *tty);
+
+/* All of the device info needed for the Connect Tech WhiteHEAT */
+static __u16 connecttech_vendor_id = CONNECT_TECH_VENDOR_ID;
+static __u16 connecttech_whiteheat_product_id = CONNECT_TECH_WHITE_HEAT_ID;
+static struct usb_serial_device_type whiteheat_device = {
+ "Connect Tech - WhiteHEAT",
+ &connecttech_vendor_id, /* the Connect Tech vendor id */
+ &connecttech_whiteheat_product_id, /* the White Heat product id */
+ DONT_CARE, /* don't have to have an interrupt in endpoint */
+ DONT_CARE, /* don't have to have a bulk in endpoint */
+ DONT_CARE, /* don't have to have a bulk out endpoint */
+ whiteheat_serial_open,
+ whiteheat_serial_close,
+ whiteheat_serial_write,
+ whiteheat_serial_put_char,
+ whiteheat_write_room,
+ whiteheat_chars_in_buffer,
+ whiteheat_throttle,
+ whiteheat_unthrottle
};
+
+/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
+static int generic_serial_open (struct tty_struct *tty, struct file *filp);
+static void generic_serial_close (struct tty_struct *tty, struct file *filp);
+static int generic_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch);
+static int generic_write_room (struct tty_struct *tty);
+static int generic_chars_in_buffer (struct tty_struct *tty);
+
/* All of the device info needed for the Generic Serial Converter */
static struct usb_serial_device_type generic_device = {
"Generic",
entry is NULL. */
static struct usb_serial_device_type *usb_serial_devices[] = {
&generic_device,
+ &whiteheat_device,
&belkin_device,
&peracom_device,
NULL
void * irq_handle;
unsigned int irqpipe;
struct tty_struct * tty; /* the coresponding tty for this device */
+ unsigned char number;
char present;
char active;
unsigned char* data = buffer;
int i;
- debug_info("USB serial: serial_read_irq\n");
+ debug_info("USB Serial: serial_read_irq\n");
#ifdef SERIAL_DEBUG
if (count) {
}
+#if 0
+/* we will need this soon... removed for now to keep the compile warnings down */
static int usb_serial_irq (int state, void *buffer, int len, void *dev_id)
{
-// struct usb_serial_state *serial = (struct usb_serial_state *) dev_id;
+ struct usb_serial_state *serial = (struct usb_serial_state *) dev_id;
debug_info("USB Serial: usb_serial_irq\n");
return (1);
}
-
+#endif
}
-static void etek_throttle (struct tty_struct * tty)
+/*****************************************************************************
+ * Connect Tech's White Heat specific driver functions
+ *****************************************************************************/
+static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp)
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("USB Serial: etek_throttle\n");
+ debug_info("USB Serial: whiteheat_serial_open\n");
+
+ if (!serial->present) {
+ debug_info("USB Serial: no device registered\n");
+ return -EINVAL;
+ }
+
+ if (serial->active) {
+ debug_info ("USB Serial: device already open\n");
+ return -EINVAL;
+ }
+ serial->active = 1;
+
+ /*Start reading from the device*/
+ serial->bulk_in_inuse = 1;
+ serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
+
+ /* Need to do device specific setup here (control lines, baud rate, etc.) */
+ /* FIXME!!! */
+
+ return (0);
+}
+
+
+static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
+{
+ struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ debug_info("USB Serial: whiteheat_serial_close\n");
+
+ /* Need to change the control lines here */
+ /* FIXME */
+
+ /* shutdown our bulk reads and writes */
+ if (serial->bulk_out_inuse){
+ usb_terminate_bulk (serial->dev, serial->bulk_out_transfer);
+ serial->bulk_out_inuse = 0;
+ }
+ if (serial->bulk_in_inuse){
+ usb_terminate_bulk (serial->dev, serial->bulk_in_transfer);
+ serial->bulk_in_inuse = 0;
+ }
+
+ /* release the irq? */
+
+ serial->active = 0;
+}
+
+
+static int whiteheat_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+ struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ int written;
+
+ debug_info("USB Serial: whiteheat_serial_write\n");
+
+ if (serial->bulk_out_inuse) {
+ debug_info ("USB Serial: already writing\n");
+ return (0);
+ }
+
+ written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count;
+
+ if (from_user) {
+ copy_from_user(serial->bulk_out_buffer, buf, written);
+ }
+ else {
+ memcpy (serial->bulk_out_buffer, buf, written);
+ }
+
+ /* send the data out the bulk port */
+ serial->bulk_out_inuse = 1;
+ serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial);
+
+ return (written);
+}
+
+
+static void whiteheat_serial_put_char (struct tty_struct *tty, unsigned char ch)
+{
+ struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
+
+ debug_info("USB Serial: whiteheat_serial_put_char\n");
+
+ if (serial->bulk_out_inuse) {
+ debug_info ("USB Serial: already writing\n");
+ return;
+ }
+
+ /* send the single character out the bulk port */
+ serial->bulk_out_buffer[0] = ch;
+ serial->bulk_out_inuse = 1;
+ serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial);
+
+ return;
+}
+
+
+static int whiteheat_write_room (struct tty_struct *tty)
+{
+ struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
+
+ debug_info("USB Serial: whiteheat_write_room\n");
+
+ if (serial->bulk_out_inuse) {
+ return (0);
+ }
+
+ return (serial->bulk_out_size);
+}
+
+
+static int whiteheat_chars_in_buffer (struct tty_struct *tty)
+{
+ struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
+
+ debug_info("USB Serial: whiteheat_chars_in_buffer\n");
+
+ if (serial->bulk_out_inuse) {
+ return (serial->bulk_out_size);
+ }
+
+ return (0);
+}
+
+
+static void whiteheat_throttle (struct tty_struct * tty)
+{
+ debug_info("USB Serial: whiteheat_throttle\n");
/* Change the control signals */
/* FIXME!!! */
}
-static void etek_unthrottle (struct tty_struct * tty)
+static void whiteheat_unthrottle (struct tty_struct * tty)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
-
- debug_info("USB Serial: etek_unthrottle\n");
+ debug_info("USB Serial: whiteheat_unthrottle\n");
/* Change the control signals */
/* FIXME!!! */
while (usb_serial_devices[device_num] != NULL) {
type = usb_serial_devices[device_num];
#ifdef SERIAL_DEBUG
- printk ("USB Serial: Looking at %s\nVendor id=%.4x\nProduct id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct));
+ printk ("USB Serial: Looking at %s Vendor id=%.4x Product id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct));
#endif
/* look at the device descriptor */
(bulk_in_pipe & type->needs_bulk_in) &&
(bulk_out_pipe & type->needs_bulk_out)) {
/* found all that we need */
- printk (KERN_INFO "USB serial converter detected.\n");
+ printk (KERN_INFO "USB Serial: %s converter detected.\n", type->name);
if (0>(serial_num = Get_Free_Serial())) {
debug_info("USB Serial: Too many devices connected\n");
memset(serial, 0, sizeof(struct usb_serial_state));
serial->dev = dev;
serial->type = type;
+ serial->number = serial_num;
/* set up the endpoint information */
if (bulk_in_endpoint) {
serial->present = 1;
MOD_INC_USE_COUNT;
+ printk(KERN_INFO "USB Serial: %s converter now attached to ttyUSB%d\n", type->name, serial_num);
return serial;
} else {
printk(KERN_INFO "USB Serial: descriptors matched, but endpoints did not\n");
serial->present = 0;
serial->active = 0;
+
+ printk (KERN_INFO "USB Serial: %s converter now disconnected from ttyUSB%d\n", serial->type->name, serial->number);
+
+ } else {
+ printk (KERN_INFO "USB Serial: device disconnected.\n");
}
MOD_DEC_USE_COUNT;
- printk (KERN_INFO "USB Serial: device disconnected.\n");
}
#define USB_MAJOR 180
-extern int usb_hub_init(void);
-extern int usb_kbd_init(void);
-extern int usb_cpia_init(void);
-extern int usb_dc2xx_init(void);
-extern int usb_mouse_init(void);
-extern int usb_printer_init(void);
-
-extern void usb_hub_cleanup(void);
-extern void usb_mouse_cleanup(void);
-
/* for 2.2-kernels */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
return 0;
if (change_mode(pp, ECR_EPP))
return 0;
- i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buf, length, &rlen, HZ*20);
+ i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buf, length, rlen);
change_mode(pp, ECR_PS2);
return 0;
if (change_mode(pp, ECR_ECP))
return 0;
- i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen, HZ*20);
+ i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
return 0;
if (change_mode(pp, ECR_PPF))
return 0;
- i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen, HZ*20);
+ i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
-Last update: 03-07-1998
+Last update: 1999-12-23
+
+- Fragmented files and directories were incorrectly handled.
+ Fixed 1999-12-23, Anders.
+
+- readdir sometimes returned the same dir entry more than once.
+ Fixed 1999-12-13, Anders.
+
+- File names with a length of exactly 16 chars were handled incorrectly.
+ Fixed 1999-12-11, Anders.
- Files in a subdir can't be accessed, I think that the inode information
is not correctly copied at some point. Solved 06-06-1998, Richard.
This is a snapshot of the QNX4 filesystem for Linux.
- Please send diffs and remarks to <qnxfs@rtc-one.net> .
+ Please send diffs and remarks to <al@alarsen.net> .
Credits :
Richard "Scuba" A. Frowijn <scuba@wxs.nl>
Frank "Jedi/Sector One" Denis <j@4u.net>
-
+Anders Larsen <al@alarsen.net>
Name : QNX4 TODO list
-Last update: 29-06-1998
+Last update: 1999-12-23
+
+ - Writing is still unsupported (it may compile, but it certainly won't
+ bring you any joy).
- qnx4_checkroot (inode.c), currently there's a look for the '/' in
the root direntry, if so then the current mounted device is a qnx4
- Bitmap functions. To find out the free space, largest free block, etc.
Partly done (RO), Richard, 05/06/1998. Optimized 20-06-1998, Frank.
- - Symbolic links. symlinks.c have to be rewritten.
-
- - Extended files.
-
- Complete write, unlink and truncate functions : the bitmap should be
updated.
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 28-05-1998 by Richard Frowijn : first release.
* 20-06-1998 by Frank Denis : basic optimisations.
* 25-06-1998 by Frank Denis : qnx4_is_free, qnx4_set_bitmap, qnx4_bmap .
return qnx4_count_free_blocks(sb) * QNX4_INODES_PER_BLOCK; /* FIXME */
}
-int qnx4_is_free(struct super_block *sb, int block)
+int qnx4_is_free(struct super_block *sb, long block)
{
int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
int size = sb->u.qnx4_sb.BitMap->di_size;
return ret;
}
-int qnx4_bmap(struct inode *inode, int block)
-{
- QNX4DEBUG(("qnx4: bmap on block [%d]\n", block));
- if (block < 0) {
- return 0;
- }
- return !qnx4_is_free(inode->i_sb, block);
-}
-
#ifdef CONFIG_QNX4FS_RW
-int qnx4_set_bitmap(struct super_block *sb, int block, int busy)
+int qnx4_set_bitmap(struct super_block *sb, long block, int busy)
{
int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
int size = sb->u.qnx4_sb.BitMap->di_size;
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 28-05-1998 by Richard Frowijn : first release.
* 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
*/
#include <asm/segment.h>
-static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir);
-
static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct inode *inode = filp->f_dentry->d_inode;
unsigned int offset;
struct buffer_head *bh;
struct qnx4_inode_entry *de;
- long blknum;
- int i;
+ struct qnx4_link_info *le;
+ unsigned long blknum;
+ int ix, ino;
int size;
- blknum = inode->u.qnx4_i.i_first_xtnt.xtnt_blk - 1 +
- ((filp->f_pos >> 6) >> 3);
-
QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos));
- QNX4DEBUG(("BlkNum = %ld\n", (long) blknum));
while (filp->f_pos < inode->i_size) {
+ blknum = qnx4_block_map( inode, filp->f_pos / QNX4_BLOCK_SIZE );
bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
if(bh==NULL)
{
printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
break;
}
- i = (filp->f_pos - (((filp->f_pos >> 6) >> 3) << 9)) & 0x3f;
- while (i < QNX4_INODES_PER_BLOCK) {
- offset = i * QNX4_DIR_ENTRY_SIZE;
+ ix = (filp->f_pos / QNX4_DIR_ENTRY_SIZE - (filp->f_pos / QNX4_BLOCK_SIZE) * QNX4_INODES_PER_BLOCK) % QNX4_INODES_PER_BLOCK;
+ while (ix < QNX4_INODES_PER_BLOCK) {
+ offset = ix * QNX4_DIR_ENTRY_SIZE;
de = (struct qnx4_inode_entry *) (bh->b_data + offset);
size = strlen(de->di_fname);
if (size) {
+ if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX )
+ size = QNX4_SHORT_NAME_MAX;
+ else if ( size > QNX4_NAME_MAX )
+ size = QNX4_NAME_MAX;
- QNX4DEBUG(("qnx4_readdir:%s\n", de->di_fname));
-
- if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
- if (de->di_status) {
- if (filldir(dirent, de->di_fname, size, filp->f_pos, de->di_first_xtnt.xtnt_blk) < 0) {
- brelse(bh);
- return 0;
- }
+ if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) {
+ QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname));
+ if ( ( de->di_status & QNX4_FILE_LINK ) == 0 )
+ ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
+ else
+ {
+ le = (struct qnx4_link_info*)de;
+ ino = ( le->dl_inode_blk - 1 ) *
+ QNX4_INODES_PER_BLOCK +
+ le->dl_inode_ndx;
+ }
+ if (filldir(dirent, de->di_fname, size, filp->f_pos, ino) < 0) {
+ brelse(bh);
+ return 0;
}
}
}
- i++;
+ ix++;
filp->f_pos += QNX4_DIR_ENTRY_SIZE;
}
brelse(bh);
- blknum++;
}
UPDATE_ATIME(inode);
static struct file_operations qnx4_dir_operations =
{
- NULL, /* lseek - default */
- NULL, /* read */
- NULL, /* write - bad */
- qnx4_readdir, /* readdir */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special flush code */
- NULL, /* no special release code */
- file_fsync, /* default fsync */
- NULL, /* default fasync */
- NULL, /* default check_media_change */
- NULL, /* default revalidate */
+ readdir: qnx4_readdir,
+ fsync: file_fsync,
};
struct inode_operations qnx4_dir_inode_operations =
{
- &qnx4_dir_operations,
-#ifdef CONFIG_QNX4FS_RW
- qnx4_create,
-#else
- NULL, /* create */
-#endif
- qnx4_lookup,
- NULL, /* link */
+ default_file_ops: &qnx4_dir_operations,
#ifdef CONFIG_QNX4FS_RW
- qnx4_unlink, /* unlink */
-#else
- NULL,
+ create: qnx4_create,
#endif
- NULL, /* symlink */
- NULL, /* mkdir */
+ lookup: qnx4_lookup,
#ifdef CONFIG_QNX4FS_RW
- qnx4_rmdir, /* rmdir */
-#else
- NULL,
+ unlink: qnx4_unlink,
+ rmdir: qnx4_rmdir,
#endif
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 25-05-1998 by Richard Frowijn : first release.
* 21-06-1998 by Frank Denis : wrote qnx4_readpage to use generic_file_read.
* 27-06-1998 by Frank Denis : file overwriting.
#define MAX(a,b) (((a)>(b))?(a):(b))
-static int qnx4_readpage(struct dentry *dentry, struct page *page);
-
#ifdef CONFIG_QNX4FS_RW
static ssize_t qnx4_file_write(struct file *filp, const char *buf,
size_t count, loff_t * ppos)
}
break;
}
- update_vm_cache(inode, pos, p, c);
+// update_vm_cache(inode, pos, p, c);
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh, 0);
brelse(bh);
#endif
/*
- * We have moostly NULL's here: the current defaults are ok for
+ * We have mostly NULL's here: the current defaults are ok for
* the qnx4 filesystem.
*/
static struct file_operations qnx4_file_operations =
{
- NULL, /* lseek - default */
- generic_file_read, /* read */
+ read: generic_file_read,
#ifdef CONFIG_QNX4FS_RW
- qnx4_file_write, /* write */
-#else
- NULL,
+ write: qnx4_file_write,
#endif
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- generic_file_mmap, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* no special flush code */
- NULL, /* release */
-#ifdef CONFIG_QNX4FS_RW
- qnx4_sync_file, /* fsync */
-#else
- NULL,
+ mmap: generic_file_mmap,
+#ifdef CONFIG_QNX4FS_RW
+ fsync: qnx4_sync_file,
#endif
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
};
struct inode_operations qnx4_file_inode_operations =
{
- &qnx4_file_operations, /* default file operations */
- NULL, /* create? It's not a directory */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- qnx4_bmap, /* get_block */
- qnx4_readpage, /* readpage */
- NULL, /* writepage */
+ default_file_ops: &qnx4_file_operations,
+ get_block: qnx4_get_block,
+ readpage: block_read_full_page,
#ifdef CONFIG_QNX4FS_RW
- qnx4_truncate, /* truncate */
-#else
- NULL,
+ writepage: block_write_full_page,
+ truncate: qnx4_truncate,
#endif
- NULL, /* permission */
- NULL /* revalidate */
};
-
-static int qnx4_readpage(struct dentry *dentry, struct page *page)
-{
- struct inode *inode = dentry->d_inode;
- struct qnx4_inode_info *qnx4_ino = &inode->u.qnx4_i;
- unsigned long buf;
- unsigned long offset, avail, readlen;
- unsigned long start;
- unsigned long count;
- struct buffer_head *bh;
- int res = -EIO;
-
- QNX4DEBUG(("qnx4: readpage index=[%ld]\n", (long) page->index));
-
- if (qnx4_ino->i_xblk != 0) {
- printk("qnx4: sorry, this file is extended, don't know how to handle it (yet) !\n");
- return -EIO;
- }
- atomic_inc(&page->count);
- buf = page_address(page);
- clear_bit(PG_uptodate, &page->flags);
- clear_bit(PG_error, &page->flags);
- offset = page->index<<PAGE_SHIFT;
-
- if (offset < inode->i_size) {
- res = 0;
- avail = inode->i_size - offset;
- readlen = MIN(avail, PAGE_SIZE);
- start = qnx4_ino->i_first_xtnt.xtnt_blk + (offset >> 9) - 1;
- count = PAGE_SIZE / QNX4_BLOCK_SIZE;
- do {
- QNX4DEBUG(("qnx4: reading page starting at [%ld]\n", (long) start));
- if ((bh = bread(inode->i_dev, start, QNX4_BLOCK_SIZE)) == NULL) {
- printk("qnx4: data corrupted or I/O error.\n");
- res = -EIO;
- } else {
- memcpy((void *) buf, bh->b_data, QNX4_BLOCK_SIZE);
- }
- buf += QNX4_BLOCK_SIZE;
- start++;
- count--;
- } while (count != 0);
- }
- if (res != 0) {
- set_bit(PG_error, &page->flags);
- memset((void *) buf, 0, PAGE_SIZE);
- } else {
- set_bit(PG_uptodate, &page->flags);
- }
- UnlockPage(page);
-/* free_page(buf); */
-
- return res;
-}
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 01-06-1998 by Richard Frowijn : first release.
* 20-06-1998 by Frank Denis : Linux 2.1.99+ support, boot signature, misc.
* 30-06-1998 by Frank Denis : first step to write inodes.
kdevname(inode->i_dev), inode->i_ino);
err = -1;
}
- brelse (bh);
+ brelse (bh);
} else if (!bh) {
err = -1;
}
static struct super_operations qnx4_sops =
{
- qnx4_read_inode,
-#ifdef CONFIG_QNX4FS_RW
- qnx4_write_inode,
-#else
- NULL,
-#endif
- NULL, /* put_inode */
+ read_inode: qnx4_read_inode,
#ifdef CONFIG_QNX4FS_RW
- qnx4_delete_inode,
-#else
- NULL, /* delete_inode */
+ write_inode: qnx4_write_inode,
+ delete_inode: qnx4_delete_inode,
#endif
- NULL, /* notify_change */
- qnx4_put_super,
+ put_super: qnx4_put_super,
#ifdef CONFIG_QNX4FS_RW
- qnx4_write_super,
-#else
- NULL,
+ write_super: qnx4_write_super,
#endif
- qnx4_statfs,
- qnx4_remount,
- NULL /* clear_inode */
+ statfs: qnx4_statfs,
+ remount_fs: qnx4_remount,
};
static int qnx4_remount(struct super_block *sb, int *flags, char *data)
return NULL;
}
+int qnx4_get_block( struct inode *inode, long iblock, struct buffer_head *bh, int create )
+{
+ unsigned long phys;
+
+ QNX4DEBUG(("qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock));
+
+ phys = qnx4_block_map( inode, iblock );
+ if ( phys )
+ {
+ // logical block is before EOF
+ bh->b_dev = inode->i_dev;
+ bh->b_blocknr = phys;
+ bh->b_state |= (1UL << BH_Mapped);
+ }
+ else if ( create )
+ {
+ // to be done.
+ }
+ return 0;
+}
+
+unsigned long qnx4_block_map( struct inode *inode, long iblock )
+{
+ int ix;
+ long offset, i_xblk;
+ unsigned long block = 0;
+ struct buffer_head *bh = 0;
+ struct qnx4_xblk *xblk = 0;
+ struct qnx4_inode_info *qnx4_inode = &inode->u.qnx4_i;
+ qnx4_nxtnt_t nxtnt = qnx4_inode->i_num_xtnts;
+
+ if ( iblock < qnx4_inode->i_first_xtnt.xtnt_size )
+ {
+ // iblock is in the first extent. This is easy.
+ block = qnx4_inode->i_first_xtnt.xtnt_blk + iblock - 1;
+ }
+ else
+ {
+ // iblock is beyond first extent. We have to follow the extent chain.
+ i_xblk = qnx4_inode->i_xblk;
+ offset = iblock - qnx4_inode->i_first_xtnt.xtnt_size;
+ ix = 0;
+ while ( --nxtnt > 0 )
+ {
+ if ( ix == 0 )
+ {
+ // read next xtnt block.
+ bh = bread( inode->i_dev, i_xblk - 1, QNX4_BLOCK_SIZE );
+ if ( !bh )
+ {
+ QNX4DEBUG(("qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));
+ return -EIO;
+ }
+ xblk = (struct qnx4_xblk*)bh->b_data;
+ if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) )
+ {
+ QNX4DEBUG(("qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));
+ break;
+ }
+ }
+ if ( offset < xblk->xblk_xtnts[ix].xtnt_size )
+ {
+ // got it!
+ block = xblk->xblk_xtnts[ix].xtnt_blk + offset - 1;
+ break;
+ }
+ offset -= xblk->xblk_xtnts[ix].xtnt_size;
+ if ( ++ix > QNX4_MAX_XTNTS_PER_XBLK )
+ {
+ i_xblk = xblk->xblk_next_xblk;
+ ix = 0;
+ brelse( bh );
+ bh = 0;
+ }
+ }
+ if ( bh )
+ brelse( bh );
+ }
+
+ QNX4DEBUG(("qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block));
+ return block;
+}
+
static int qnx4_statfs(struct super_block *sb,
struct statfs *buf, int bufsize)
{
* it really _is_ a qnx4 filesystem, and to check the size
* of the directory entry.
*/
-static const char *qnx4_checkroot(struct super_block *s)
+static const char *qnx4_checkroot(struct super_block *sb)
{
struct buffer_head *bh;
struct qnx4_inode_entry *rootdir;
int i, j;
int found = 0;
- if (*(s->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
+ if (*(sb->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
return "no qnx4 filesystem (no root dir).";
} else {
- QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(s->s_dev)));
- rd = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
- rl = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
+ QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(sb->s_dev)));
+ rd = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
+ rl = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
for (j = 0; j < rl; j++) {
- bh = bread(s->s_dev, rd + j, QNX4_BLOCK_SIZE); /* root dir, first block */
+ bh = bread(sb->s_dev, rd + j, QNX4_BLOCK_SIZE); /* root dir, first block */
if (bh == NULL) {
return "unable to read root entry.";
}
QNX4DEBUG(("Rootdir entry found : [%s]\n", rootdir->di_fname));
if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
found = 1;
- s->u.qnx4_sb.BitMap = rootdir; /* keep bitmap inode known */
+ sb->u.qnx4_sb.BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
+ memcpy( sb->u.qnx4_sb.BitMap, rootdir, sizeof( struct qnx4_inode_entry ) ); /* keep bitmap inode known */
break;
}
}
}
- /* WAIT! s->u.qnx4_sb.BitMap points into bh->b_data
- and now we release bh?? */
brelse(bh);
if (found != 0) {
break;
return NULL;
}
-static struct super_block *qnx4_read_super(struct super_block *s,
+static struct super_block *qnx4_read_super(struct super_block *s,
void *data, int silent)
{
struct buffer_head *bh;
kdev_t dev = s->s_dev;
struct inode *root;
- char *tmpc;
const char *errmsg;
MOD_INC_USE_COUNT;
printk("qnx4: unable to read the boot sector\n");
goto outnobh;
}
- tmpc = (char *) bh->b_data;
- if (tmpc[4] != 'Q' || tmpc[5] != 'N' || tmpc[6] != 'X' ||
- tmpc[7] != '4' || tmpc[8] != 'F' || tmpc[9] != 'S') {
+ if ( memcmp( (char*)bh->b_data + 4, "QNX4FS", 6 ) ) {
if (!silent)
printk("qnx4: wrong fsid in boot sector.\n");
goto out;
s->u.qnx4_sb.sb_buf = bh;
s->u.qnx4_sb.sb = (struct qnx4_super_block *) bh->b_data;
-
+
/* check before allocating dentries, inodes, .. */
errmsg = qnx4_checkroot(s);
if (errmsg != NULL) {
printk("qnx4: %s\n", errmsg);
goto out;
}
-
+
/* does root not have inode number QNX4_ROOT_INO ?? */
root = iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
if (!root) {
printk("qnx4: get inode failed\n");
goto out;
}
-
+
s->s_root = d_alloc_root(root);
if (s->s_root == NULL)
goto outi;
-
+
brelse(bh);
unlock_super(s);
s->s_dirt = 1;
static void qnx4_put_super(struct super_block *sb)
{
+ kfree_s( sb->u.qnx4_sb.BitMap, sizeof( struct qnx4_inode_entry ) );
MOD_DEC_USE_COUNT;
return;
}
int __init init_qnx4_fs(void)
{
- printk("QNX4 filesystem v0.2 registered.\n");
+ printk("QNX4 filesystem 0.2.1 registered.\n");
return register_filesystem(&qnx4_fs_type);
}
/*
* QNX4 file system, Linux implementation.
*
- * Version : 0.1
+ * Version : 0.2.1
*
* Using parts of the xiafs filesystem.
*
struct buffer_head *bh, unsigned long *offset)
{
struct qnx4_inode_entry *de;
- int namelen;
+ struct qnx4_link_info *le;
+ int namelen, thislen;
if (bh == NULL) {
printk("qnx4: matching unassigned buffer !\n");
}
de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
*offset += QNX4_DIR_ENTRY_SIZE;
- if ((de->di_status & 0x08) == 0x08) {
+ if ((de->di_status & QNX4_FILE_LINK) != 0) {
namelen = QNX4_NAME_MAX;
} else {
- namelen = _SHORT_NAME_MAX;
+ namelen = QNX4_SHORT_NAME_MAX;
}
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
return 1;
}
- if (len != strlen(de->di_fname)) {
+ thislen = strlen( de->di_fname );
+ if ( thislen > namelen )
+ thislen = namelen;
+ if (len != thislen) {
return 0;
}
if (strncmp(name, de->di_fname, len) == 0) {
- if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
- if (de->di_status) {
- return 1;
- }
+ if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
+ return 1;
}
}
return 0;
return NULL;
}
bh = NULL;
- blkofs = dir->u.qnx4_i.i_first_xtnt.xtnt_blk - 1;
- offset = block = 0;
- while (block * QNX4_BLOCK_SIZE + offset < dir->i_size) {
+ block = offset = blkofs = 0;
+ while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
if (!bh) {
- bh = qnx4_bread(dir, block + blkofs, 0);
+ block = qnx4_block_map( dir, blkofs );
+ bh = qnx4_bread(dir, block, 0);
if (!bh) {
- block++;
+ blkofs++;
continue;
}
}
*res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
if (qnx4_match(len, name, bh, &offset)) {
- *ino = (block + blkofs) * QNX4_INODES_PER_BLOCK +
+ *ino = block * QNX4_INODES_PER_BLOCK +
(offset / QNX4_DIR_ENTRY_SIZE) - 1;
return bh;
}
brelse(bh);
bh = NULL;
offset = 0;
- block++;
+ blkofs++;
}
brelse(bh);
*res_dir = NULL;
/*
* QNX4 file system, Linux implementation.
*
- * Version : 0.1
+ * Version : 0.2.1
*
* Using parts of the xiafs filesystem.
*
*/
struct inode_operations qnx4_symlink_inode_operations =
{
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- qnx4_readlink, /* readlink */
- qnx4_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: qnx4_get_block,
+ readpage: block_read_full_page,
};
-
-static struct dentry *qnx4_follow_link(struct dentry *dentry,
- struct dentry *base, unsigned int follow)
-{
-#if 0
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
-
- if (!inode) {
- return ERR_PTR(-ENOENT);
- }
- if (current->link_count > 5) {
- return ERR_PTR(-ELOOP);
- }
- if (!(bh = qnx4_bread(inode, 0, 0))) {
- return ERR_PTR(-EIO);
- }
- current->link_count++;
- current->link_count--;
- brelse(bh);
- return 0;
-#else
- printk("qnx4: qnx4_follow_link needs to be fixed.\n");
- return ERR_PTR(-EIO);
-#endif
-}
-
-static int qnx4_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
- int i;
- char c;
- struct qnx4_inode_info *qnx4_ino;
-
- QNX4DEBUG(("qnx4: qnx4_readlink() called\n"));
-
- if (buffer == NULL || inode == NULL || !S_ISLNK(inode->i_mode)) {
- return -EINVAL;
- }
- qnx4_ino = &inode->u.qnx4_i;
- if (buflen > 1023) {
- buflen = 1023;
- }
- bh = bread(inode->i_dev, qnx4_ino->i_first_xtnt.xtnt_blk,
- QNX4_BLOCK_SIZE);
- if (bh == NULL) {
- QNX4DEBUG(("qnx4: NULL symlink bh\n"));
- return 0;
- }
- QNX4DEBUG(("qnx4: qnx4_bread sym called -> [%s]\n",
- bh->b_data));
- if (bh->b_data[0] != 0) {
- i = 0;
- while (i < buflen && (c = bh->b_data[i])) {
- i++;
- put_user(c, buffer++);
- }
- brelse(bh);
- return i;
- } else {
- brelse(bh);
- memcpy(buffer, "fixme", 5);
- return 5;
- }
-}
/* ---------- LFS-64 ----------- */
-#if BITS_PER_LONG == 32
+#if !defined(__alpha__)
static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
{
return err;
}
-#endif /* BITS_PER_LONG == 32 */
+#endif /* LFS-64 */
-/* $Id: stat.h,v 1.9 1998/07/26 05:24:39 davem Exp $ */
+/* $Id: stat.h,v 1.10 1999/12/21 14:09:41 jj Exp $ */
#ifndef _SPARC_STAT_H
#define _SPARC_STAT_H
unsigned long __unused4[2];
};
+struct stat64 {
+ unsigned char __pad0[6];
+ unsigned short st_dev;
+ unsigned char __pad1[4];
+
+ unsigned int st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned int st_uid;
+ unsigned int st_gid;
+
+ unsigned char __pad2[6];
+ unsigned short st_rdev;
+
+ unsigned char __pad3[8];
+
+ long long st_size;
+ unsigned int st_blksize;
+
+ unsigned char __pad4[8];
+ unsigned int st_blocks;
+
+ unsigned int st_atime;
+ unsigned int __unused1;
+
+ unsigned int st_mtime;
+ unsigned int __unused2;
+
+ unsigned int st_ctime;
+ unsigned int __unused3;
+
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
#endif
-/* $Id: unistd.h,v 1.58 1999/12/15 17:52:01 jj Exp $ */
+/* $Id: unistd.h,v 1.59 1999/12/21 14:09:43 jj Exp $ */
#ifndef _SPARC_UNISTD_H
#define _SPARC_UNISTD_H
/* #define __NR_mctl 53 SunOS specific */
#define __NR_ioctl 54 /* Common */
#define __NR_reboot 55 /* Common */
-/* #define __NR_ni_syscall 56 ENOSYS under SunOS */
+#define __NR_mmap2 56 /* Linux sparc32 Specific */
#define __NR_symlink 57 /* Common */
#define __NR_readlink 58 /* Common */
#define __NR_execve 59 /* Common */
#define __NR_umask 60 /* Common */
#define __NR_chroot 61 /* Common */
#define __NR_fstat 62 /* Common */
-/* #define __NR_ni_syscall 63 ENOSYS under SunOS */
+#define __NR_fstat64 63 /* Linux sparc32 Specific */
#define __NR_getpagesize 64 /* Common */
#define __NR_msync 65 /* Common in newer 1.3.x revs... */
#define __NR_vfork 66 /* Common */
#define __NR_mprotect 74 /* Common */
/* #define __NR_madvise 75 SunOS Specific */
#define __NR_vhangup 76 /* Common */
-/* #define __NR_ni_syscall 77 ENOSYS under SunOS */
+#define __NR_truncate64 77 /* Linux sparc32 Specific */
/* #define __NR_mincore 78 SunOS Specific */
#define __NR_getgroups 79 /* Common */
#define __NR_setgroups 80 /* Common */
#define __NR_getpgrp 81 /* Common */
/* #define __NR_setpgrp 82 setpgid, same difference... */
#define __NR_setitimer 83 /* Common */
-/* #define __NR_ni_syscall 84 ENOSYS under SunOS */
+#define __NR_ftruncate64 84 /* Linux sparc32 Specific */
#define __NR_swapon 85 /* Common */
#define __NR_getitimer 86 /* Common */
/* #define __NR_gethostname 87 SunOS Specific */
#define __NR_truncate 129 /* Common */
#define __NR_ftruncate 130 /* Common */
#define __NR_flock 131 /* Common */
-/* #define __NR_ni_syscall 132 ENOSYS under SunOS */
+#define __NR_lstat64 132 /* Linux sparc32 Specific */
#define __NR_sendto 133 /* Common */
#define __NR_shutdown 134 /* Common */
#define __NR_socketpair 135 /* Common */
#define __NR_mkdir 136 /* Common */
#define __NR_rmdir 137 /* Common */
#define __NR_utimes 138 /* SunOS Specific */
-/* #define __NR_ni_syscall 139 ENOSYS under SunOS */
+#define __NR_stat64 139 /* Linux sparc32 Specific */
/* #define __NR_adjtime 140 SunOS Specific */
#define __NR_getpeername 141 /* Common */
/* #define __NR_gethostid 142 SunOS Specific */
(unsigned long)ret->pprev_hash = mask;
if (!mask)
pgd_quicklist = (unsigned long *)ret->next_hash;
- ret = (struct page *)(page_address(ret) + off);
+ ret = (struct page *)(__page_address(ret) + off);
pgd_cache_size--;
} else {
ret = (struct page *) __get_free_page(GFP_KERNEL);
-/* $Id: pgtable.h,v 1.116 1999/12/15 22:18:55 davem Exp $
+/* $Id: pgtable.h,v 1.118 1999/12/21 21:24:35 davem Exp $
* pgtable.h: SpitFire page table operations.
*
* Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
#define pte_mkold(pte) (__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_ACCESSED))
/* Permanent address of a page. */
-#define page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
-#define __page_address(page) ({ page_address(page); })
+#define __page_address(page) ((page)->virtual)
+#define page_address(page) ({ __page_address(page); })
#define pte_page(x) (mem_map+pte_pagenr(x))
-/* $Id: stat.h,v 1.5 1998/07/26 05:24:41 davem Exp $ */
+/* $Id: stat.h,v 1.6 1999/12/21 14:09:48 jj Exp $ */
#ifndef _SPARC64_STAT_H
#define _SPARC64_STAT_H
unsigned long __unused4[2];
};
+#ifdef __KERNEL__
+/* This is sparc32 stat64 structure. */
+
+struct stat64 {
+ unsigned char __pad0[6];
+ unsigned short st_dev;
+ unsigned char __pad1[4];
+
+ unsigned int st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned int st_uid;
+ unsigned int st_gid;
+
+ unsigned char __pad2[6];
+ unsigned short st_rdev;
+
+ unsigned char __pad3[8];
+
+ long long st_size;
+ unsigned int st_blksize;
+
+ unsigned char __pad4[8];
+ unsigned int st_blocks;
+
+ unsigned int st_atime;
+ unsigned int __unused1;
+
+ unsigned int st_mtime;
+ unsigned int __unused2;
+
+ unsigned int st_ctime;
+ unsigned int __unused3;
+
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
+#endif
+
#endif
-/* $Id: unistd.h,v 1.35 1999/12/15 17:52:09 jj Exp $ */
+/* $Id: unistd.h,v 1.36 1999/12/21 14:09:51 jj Exp $ */
#ifndef _SPARC64_UNISTD_H
#define _SPARC64_UNISTD_H
/* #define __NR_mctl 53 SunOS specific */
#define __NR_ioctl 54 /* Common */
#define __NR_reboot 55 /* Common */
-/* #define __NR_ni_syscall 56 ENOSYS under SunOS */
+/* #define __NR_mmap2 56 Linux sparc32 Specific */
#define __NR_symlink 57 /* Common */
#define __NR_readlink 58 /* Common */
#define __NR_execve 59 /* Common */
#define __NR_umask 60 /* Common */
#define __NR_chroot 61 /* Common */
#define __NR_fstat 62 /* Common */
-/* #define __NR_ni_syscall 63 ENOSYS under SunOS */
+/* #define __NR_fstat64 63 Linux sparc32 Specific */
#define __NR_getpagesize 64 /* Common */
#define __NR_msync 65 /* Common in newer 1.3.x revs... */
#define __NR_vfork 66 /* Common */
#define __NR_mprotect 74 /* Common */
/* #define __NR_madvise 75 SunOS Specific */
#define __NR_vhangup 76 /* Common */
-/* #define __NR_ni_syscall 77 ENOSYS under SunOS */
+/* #define __NR_truncate64 77 Linux sparc32 Specific */
/* #define __NR_mincore 78 SunOS Specific */
#define __NR_getgroups 79 /* Common */
#define __NR_setgroups 80 /* Common */
#define __NR_getpgrp 81 /* Common */
/* #define __NR_setpgrp 82 setpgid, same difference... */
#define __NR_setitimer 83 /* Common */
-/* #define __NR_ni_syscall 84 ENOSYS under SunOS */
+/* #define __NR_ftruncate64 84 Linux sparc32 Specific */
#define __NR_swapon 85 /* Common */
#define __NR_getitimer 86 /* Common */
/* #define __NR_gethostname 87 SunOS Specific */
#define __NR_truncate 129 /* Common */
#define __NR_ftruncate 130 /* Common */
#define __NR_flock 131 /* Common */
-/* #define __NR_ni_syscall 132 ENOSYS under SunOS */
+/* #define __NR_lstat64 132 Linux sparc32 Specific */
#define __NR_sendto 133 /* Common */
#define __NR_shutdown 134 /* Common */
#define __NR_socketpair 135 /* Common */
#define __NR_mkdir 136 /* Common */
#define __NR_rmdir 137 /* Common */
#define __NR_utimes 138 /* SunOS Specific */
-/* #define __NR_ni_syscall 139 ENOSYS under SunOS */
+/* #define __NR_stat64 139 Linux sparc32 Specific */
/* #define __NR_adjtime 140 SunOS Specific */
#define __NR_getpeername 141 /* Common */
/* #define __NR_gethostid 142 SunOS Specific */
#define PCI_VENDOR_ID_TI 0x104c
#define PCI_DEVICE_ID_TI_TVP4010 0x3d04
#define PCI_DEVICE_ID_TI_TVP4020 0x3d07
-#define PCI_DEVICE_ID_TI_PCI1130 0xac12
-#define PCI_DEVICE_ID_TI_PCI1031 0xac13
-#define PCI_DEVICE_ID_TI_PCI1131 0xac15
-#define PCI_DEVICE_ID_TI_PCI1250 0xac16
-#define PCI_DEVICE_ID_TI_PCI1220 0xac17
+#define PCI_DEVICE_ID_TI_1130 0xac12
+#define PCI_DEVICE_ID_TI_1031 0xac13
+#define PCI_DEVICE_ID_TI_1131 0xac15
+#define PCI_DEVICE_ID_TI_1250 0xac16
+#define PCI_DEVICE_ID_TI_1220 0xac17
+#define PCI_DEVICE_ID_TI_1221 0xac19
+#define PCI_DEVICE_ID_TI_1210 0xac1a
+#define PCI_DEVICE_ID_TI_1450 0xac1b
+#define PCI_DEVICE_ID_TI_1225 0xac1c
+#define PCI_DEVICE_ID_TI_1251A 0xac1d
+#define PCI_DEVICE_ID_TI_1211 0xac1e
+#define PCI_DEVICE_ID_TI_1251B 0xac1f
+#define PCI_DEVICE_ID_TI_1420 0xac51
+
#define PCI_VENDOR_ID_OAK 0x104e
#define PCI_DEVICE_ID_OAK_OTI107 0x0107
* Name : qnx4_fs.h
* Author : Richard Frowijn
* Function : qnx4 global filesystem definitions
- * Version : 1.0
- * Last modified : 23-03-1998
+ * Version : 1.0.1
+ * Last modified : 1999-12-13
*
* History : 23-03-1998 created
*/
#define QNX4_ROOT_INO 1
-#define _MAX_XTNTS_PER_XBLK 60
+#define QNX4_MAX_XTNTS_PER_XBLK 60
/* for di_status */
#define QNX4_FILE_USED 0x01
#define QNX4_FILE_MODIFIED 0x02
#define QNX4_INODES_PER_BLOCK 0x08 /* 512 / 64 */
/* for filenames */
-#define _SHORT_NAME_MAX 16
-#define QNX4_NAME_MAX 48
+#define QNX4_SHORT_NAME_MAX 16
+#define QNX4_NAME_MAX 48
/*
* This is the original qnx4 inode layout on disk.
*/
struct qnx4_inode_entry {
- char di_fname[16];
- off_t di_size;
- _xtnt_t di_first_xtnt;
- long di_xblk;
+ char di_fname[QNX4_SHORT_NAME_MAX];
+ qnx4_off_t di_size;
+ qnx4_xtnt_t di_first_xtnt;
+ unsigned long di_xblk;
time_t di_ftime;
time_t di_mtime;
time_t di_atime;
time_t di_ctime;
- _nxtnt_t di_num_xtnts;
+ qnx4_nxtnt_t di_num_xtnts;
mode_t di_mode;
- muid_t di_uid;
- mgid_t di_gid;
- nlink_t di_nlink;
+ qnx4_muid_t di_uid;
+ qnx4_mgid_t di_gid;
+ qnx4_nlink_t di_nlink;
char di_zero[4];
- _ftype_t di_type;
+ qnx4_ftype_t di_type;
unsigned char di_status;
};
struct qnx4_link_info {
char dl_fname[QNX4_NAME_MAX];
- long dl_inode_blk;
+ unsigned long dl_inode_blk;
unsigned char dl_inode_ndx;
unsigned char dl_spare[10];
unsigned char dl_status;
};
struct qnx4_xblk {
- long xblk_next_xblk;
- long xblk_prev_xblk;
+ unsigned long xblk_next_xblk;
+ unsigned long xblk_prev_xblk;
unsigned char xblk_num_xtnts;
char xblk_spare[3];
long xblk_num_blocks;
- _xtnt_t xblk_xnts[_MAX_XTNTS_PER_XBLK];
+ qnx4_xtnt_t xblk_xtnts[QNX4_MAX_XTNTS_PER_XBLK];
char xblk_signature[8];
- _xtnt_t xblk_first_xtnt;
+ qnx4_xtnt_t xblk_first_xtnt;
};
struct qnx4_super_block {
extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry);
extern unsigned long qnx4_count_free_inodes(struct super_block *sb);
extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
+extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
extern struct buffer_head *qnx4_bread(struct inode *, int, int);
extern struct inode_operations qnx4_file_inode_operations;
extern struct inode_operations qnx4_dir_inode_operations;
extern struct inode_operations qnx4_symlink_inode_operations;
-extern int qnx4_is_free(struct super_block *sb, int block);
-extern int qnx4_set_bitmap(struct super_block *sb, int block, int busy);
+extern int qnx4_is_free(struct super_block *sb, long block);
+extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
extern void qnx4_truncate(struct inode *inode);
extern void qnx4_free_inode(struct inode *inode);
extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry);
extern int qnx4_sync_file(struct file *file, struct dentry *dentry);
extern int qnx4_sync_inode(struct inode *inode);
-extern int qnx4_bmap(struct inode *inode, int block);
+extern int qnx4_get_block(struct inode *inode, long iblock, struct buffer_head *bh, int create);
#endif /* __KERNEL__ */
#ifndef _LINUX_SS_H
#define _LINUX_SS_H
-/* For RegisterCallback */
-typedef struct ss_callback_t {
- void (*handler)(void *info, u_int events);
- void *info;
-} ss_callback_t;
-
/* Definitions for card status flags for GetStatus */
#define SS_WRPROT 0x0001
#define SS_CARDLOCK 0x0002
* Socket operations.
*/
struct pccard_operations {
- int (*register_callback)(u_short sock, ss_callback_t *call);
- int (*inquire_socket)(u_short sock, socket_cap_t *cap);
- int (*get_status)(u_short sock, u_int *value);
- int (*get_socket)(u_short sock, socket_state_t *state);
- int (*set_socket)(u_short sock, socket_state_t *state);
- int (*get_io_map)(u_short sock, struct pccard_io_map *io);
- int (*set_io_map)(u_short sock, struct pccard_io_map *io);
- int (*get_mem_map)(u_short sock, struct pccard_mem_map *mem);
- int (*set_mem_map)(u_short sock, struct pccard_mem_map *mem);
- int (*get_bridge)(u_short sock, struct cb_bridge_map *m);
- int (*set_bridge)(u_short sock, struct cb_bridge_map *m);
- void (*proc_setup)(u_short sock, struct proc_dir_entry *base);
+ int (*register_callback)(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
+ int (*inquire_socket)(unsigned int sock, socket_cap_t *cap);
+ int (*get_status)(unsigned int sock, u_int *value);
+ int (*get_socket)(unsigned int sock, socket_state_t *state);
+ int (*set_socket)(unsigned int sock, socket_state_t *state);
+ int (*get_io_map)(unsigned int sock, struct pccard_io_map *io);
+ int (*set_io_map)(unsigned int sock, struct pccard_io_map *io);
+ int (*get_mem_map)(unsigned int sock, struct pccard_mem_map *mem);
+ int (*set_mem_map)(unsigned int sock, struct pccard_mem_map *mem);
+ int (*get_bridge)(unsigned int sock, struct cb_bridge_map *m);
+ int (*set_bridge)(unsigned int sock, struct cb_bridge_map *m);
+ void (*proc_setup)(unsigned int sock, struct proc_dir_entry *base);
};
/*