S: USA
N: Juan Jose Ciarlante
-W: http://juanjox.linuxhq.com/
+W: http://juanjox.kernelnotes.org/
E: jjciarla@raiz.uncu.edu.ar
E: jjo@mendoza.gov.ar
D: Network driver alias support
ipfwadm.
To use masq forwarding you will need to obtain "ipmasqadm,"
-available from http://juanjox.linuxhq.com/ .
+available from http://juanjox.kernelnotes.org/ .
DHCP clients for 2.0 do not work with the new networking code in the
2.2 kernel. You will need to upgrade your dhcpcd / dhcpclient.
========
The 2.9.1.0.25 release:
-ftp://ftp.varesearch.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz
+ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz
Installation notes:
-ftp://ftp.varesearch.com/pub/support/hjl/binutils/2.9.1/release.binutils-2.9.1.0.25
+ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/release.binutils-2.9.1.0.25
The 2.9.5.0.16 release:
-ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.16.tar.bz2
+ftp://ftp.valinux.com/pub/support/hjl/binutils/binutils-2.9.5.0.16.tar.bz2
Installation notes:
-ftp://ftp.varesearch.com/pub/support/hjl/binutils/release.binutils-2.9.5.0.16
+ftp://ftp.valinux.com/pub/support/hjl/binutils/release.binutils-2.9.5.0.16
Bin86
=====
=====
The egcs-1.1.2 release:
-ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2
-ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2
-ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.x86.tar.bz2
+ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2
+ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2
+ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.x86.tar.bz2
Installation notes:
-ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/release.egcs-1.1.2
+ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/release.egcs-1.1.2
Gnu C 2.7.2.3 source:
ftp://ftp.gnu.org/gnu/gcc/gcc-2.7.2.3.tar.gz
===========
The 0.4.2 release:
-http://juanjox.linuxhq.com/ipmasqadm-0.4.2.tar.gz
+http://juanjox.kernelnotes.org/ipmasqadm-0.4.2.tar.gz
DHCP clients
============
Old kernels: zImage/Image support only. Some very early kernels
may not even support a command line.
-Protocol 2.00: Added bzImage and initrd support, as well as a
- formalized way to communicate between the boot loader
- and the kernel.
+Protocol 2.00: (Kernel 1.3.73) Added bzImage and initrd support, as
+ well as a formalized way to communicate between the
+ boot loader and the kernel. setup.S made relocatable,
+ although the traditional setup area still assumed
+ writable.
-Protocol 2.01: Added a heap overrun warning.
+Protocol 2.01: (Kernel 1.3.76) Added a heap overrun warning.
-Protocol 2.02: New command line protocol. Lower the
- conventional-memory ceiling. zImage deprecated but
- still supported.
+Protocol 2.02: (Kernel 2.4.0-test3-pre3) New command line protocol.
+ Lower the conventional memory ceiling. No overwrite
+ of the traditional setup area, thus making booting
+ safe for systems which use the EBDA from SMM or 32-bit
+ BIOS entry points. zImage deprecated but still
+ supported.
**** MEMORY LAYOUT
supported by the protocol version in use.
Most boot loaders will simply load the kernel at its target address
-directly. Such a boot loader do not need to worry about filling in
+directly. Such boot loaders do not need to worry about filling in
most of the fields in the header. The following fields should be
filled out, however:
memcpy(0x90000, base_ptr, (setup_sects+1)*512);
/* Copy the command line */
memcpy(0x99000, base_ptr+0x9000, 256);
+
+ base_ptr = 0x90000; /* Relocated */
}
/* It is recommended to clear memory up to the 32K mark */
sp should be set up properly, normally pointing to the top of the
heap. In our example from above, we would do:
+ /* Note: in the case of the "old" kernel protocol, base_ptr must
+ be == 0x90000 at this point; see the previous sample code */
+
seg = base_ptr >> 4;
cli(); /* Enter with interrupts disabled! */
+ /* Set up the real-mode kernel stack */
_SS = seg;
_SP = 0x9000; /* Load SP right after loading SS! */
+
_DS = _ES = _FS = _GS = seg;
jmp_far(seg+0x20, 0); /* Run the kernel */
If your boot sector accesses a floppy drive, it is recommended to
switch off the floppy motor before running the kernel, since the
kernel boot leaves interrupts off and thus the motor will not be
-switched off.
+switched off, especially if the loaded kernel has the floppy driver as
+a demand-loaded module!
**** ADVANCED BOOT TIME HOOKS
S: Maintained
SMB FILESYSTEM
-P: Andrew Tridgell
-M: tridge@samba.org
+P: Urban Widmark
+M: urban@svenskatest.se
W: http://samba.org/
L: samba@samba.org
S: Maintained
UMSDOS FILESYSTEM
P: Matija Nalis
-M: mnalis@jagor.srce.hr
+M: mnalis-umsdos@voyager.hr
L: linux-kernel@vger.rutgers.edu
S: Maintained
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 17
-EXTRAVERSION = pre13
+EXTRAVERSION = pre14
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
AS =$(CROSS_COMPILE)as
LD =$(CROSS_COMPILE)ld
-CC =$(CROSS_COMPILE)gcc -D__KERNEL__ -I$(HPATH)
+CC =$(CROSS_COMPILE)cc -D__KERNEL__ -I$(HPATH)
CPP =$(CC) -E
AR =$(CROSS_COMPILE)ar
NM =$(CROSS_COMPILE)nm
modules_install:
@( \
MODLIB=$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE); \
+ mkdir -p $$MODLIB; \
+ rm -f $$MODLIB/build; \
+ ln -s `pwd` $$MODLIB/build; \
cd modules; \
MODULES=""; \
inst_mod() { These="`cat $$1`"; MODULES="$$MODULES $$These"; \
mkdir -p $$MODLIB/$$2; cp $$These $$MODLIB/$$2; \
echo Installing modules under $$MODLIB/$$2; \
}; \
- mkdir -p $$MODLIB; \
\
if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \
if [ -f NET_MODULES ]; then inst_mod NET_MODULES net; fi; \
define_bool CONFIG_ALPHA_EV4 y
define_bool CONFIG_ALPHA_APECS y
fi
+if [ "$CONFIG_ALPHA_CABRIOLET" = "y" ]
+then
+ define_bool CONFIG_ALPHA_EB64P y
+fi
if [ "$CONFIG_ALPHA_EB164" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \
-o "$CONFIG_ALPHA_ALCOR" = "y" -o "$CONFIG_ALPHA_XLT" = "y" \
-o "$CONFIG_ALPHA_TAKARA" = "y" ]
-o "$CONFIG_ALPHA_TAKARA" = "y" -o "$CONFIG_ALPHA_EB164" = "y" \
-o "$CONFIG_ALPHA_ALCOR" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \
-o "$CONFIG_ALPHA_LX164" = "y" -o "$CONFIG_ALPHA_SX164" = "y" \
- -o "$CONFIG_ALPHA_NAUTILUS" = "y" ]
+ -o "$CONFIG_ALPHA_NAUTILUS" = "y" ]
then
bool 'Use SRM as bootloader' CONFIG_ALPHA_SRM
# if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
{
&eb64p_mv,
&cabriolet_mv,
- NULL /* AlphaPCI64 */
+ &cabriolet_mv /* AlphaPCI64 */
};
static struct alpha_machine_vector *eb66_vecs[] __initlocaldata =
pci_fixup: cabriolet_pci_fixup,
kill_arch: generic_kill_arch,
};
+#ifndef CONFIG_ALPHA_EB64P
ALIAS_MV(cabriolet)
#endif
+#endif
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164)
struct alpha_machine_vector eb164_mv __initmv = {
#include <asm/pgtable.h>
#include <asm/core_apecs.h>
#include <asm/core_lca.h>
+#include <asm/hwrpb.h>
#include "proto.h"
#include "irq.h"
static void __init
eb64p_init_irq(void)
{
-#ifdef CONFIG_ALPHA_GENERIC
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
/*
* CABRIO SRM may not set variation correctly, so here we test
* the high word of the interrupt summary register for the RAZ
*/
if (inw(0x806) != 0xffff) {
extern struct alpha_machine_vector cabriolet_mv;
-#if 1
- printk("eb64p_init_irq: resetting for CABRIO\n");
-#endif
+
+ printk("Detected Cabriolet: correcting HWRPB.\n");
+
+ hwrpb->sys_variation |= 2L << 10;
+ hwrpb_update_checksum(hwrpb);
+
alpha_mv = cabriolet_mv;
alpha_mv.init_irq();
return;
unsigned long startn = 0, n, flags;
const char *start = NULL, *msg = NULL;
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
/*
* Skip over leading whitespace
{
byte args[4], *argbuf = args;
int argsize = 4;
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES;
if (NULL == (void *) arg)
return ide_do_drive_cmd(drive, &rq, ide_wait);
if (copy_from_user(args, (void *)arg, 4))
case HDIO_SCAN_HWIF:
{
int args[3];
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES;
if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))
return -EFAULT;
if (ide_register(args[0], args[1], args[2]) == -1)
if (hash - data->hash_table > data->nr_zones)
{
- printk(KERN_DEBUG "raid0_map: invalid block %ul\n", block);
+ printk(KERN_DEBUG "raid0_map: invalid block %li\n", block);
return -1;
}
* Version 0.1 -- December, 1998. Initial version.
* Version 0.2 -- March, 1999. Some more routines. Bugfixes. Etc.
* Version 0.5 -- August, 1999. Some more fixes. Reformat for Linus.
- */
+ *
+ * BitWizard is actively maintaining this file. We sometimes find
+ * that someone submitted changes to this file. We really appreciate
+ * your help, but please submit changes through us. We're doing our
+ * best to be responsive. -- REW
+ * */
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/mm.h>
#include <asm/semaphore.h>
+#include <asm/uaccess.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/compatmac.h>
#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n")
#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit " __FUNCTION__ "\n")
-
-
#if NEW_WRITE_LOCKING
#define DECL /* Nothing */
#define LOCKIT down (& port->port_write_sem);
#define RELEASEIT restore_flags (flags)
#endif
+#ifdef MODULE
+MODULE_PARM(gs_debug, "i");
+#endif
#ifdef DEBUG
static void my_hd (unsigned char *addr, int len)
void gs_put_char(struct tty_struct * tty, unsigned char ch)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
DECL
- /* func_enter (); */
+ func_enter ();
+
+ if (!tty) return;
+
+ port = tty->driver_data;
+
+ if (!port) return;
+
+ if (! (port->flags & ASYNC_INITIALIZED)) return;
/* Take a lock on the serial tranmit buffer! */
LOCKIT;
port->xmit_cnt++; /* Characters in buffer */
RELEASEIT;
- /* func_exit ();*/
+ func_exit ();
}
int gs_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
int c, total = 0;
int t;
- /* func_enter (); */
+ func_enter ();
+
+ if (!tty) return 0;
+
+ port = tty->driver;
+
+ if (!port) return 0;
if (! (port->flags & ASYNC_INITIALIZED))
return 0;
port->flags |= GS_TX_INTEN;
port->rd->enable_tx_interrupts (port);
}
- /* func_exit (); */
+ func_exit ();
return total;
}
#else
if (!port || !port->xmit_buf || !tmp_buf)
return -EIO;
- /* printk ("from_user = %d.\n", from_user); */
save_flags(flags);
if (from_user) {
- /* printk ("Going into the semaphore\n"); */
down(&tmp_buf_sem);
- /* printk ("got out of the semaphore\n"); */
while (1) {
c = count;
struct gs_port *port = tty->driver_data;
int ret;
- /* func_enter (); */
+ func_enter ();
ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
if (ret < 0)
ret = 0;
- /* func_exit (); */
+ func_exit ();
return ret;
}
int gs_real_chars_in_buffer(struct tty_struct *tty)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
func_enter ();
if (!tty) return 0;
if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
- func_exit();
+ func_exit();
return -EINVAL; /* This is an error which we don't know how to handle. */
}
- gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 1\n");
rcib = gs_real_chars_in_buffer(port->tty);
- gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 2\n");
-
if(rcib <= 0) {
gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
func_exit();
return rv;
}
- gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 3\n");
-
/* stop trying: now + twice the time it would normally take + seconds */
end_jiffies = jiffies;
if (timeout != MAX_SCHEDULE_TIMEOUT)
void gs_flush_buffer(struct tty_struct *tty)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
unsigned long flags;
func_enter ();
+
+ if (!tty) return;
+
+ port = tty->driver_data;
+
+ if (!port) return;
+
/* XXX Would the write semaphore do? */
save_flags(flags); cli();
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
restore_flags(flags);
wake_up_interruptible(&tty->write_wait);
- wake_up_interruptible(&tty->poll_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
void gs_flush_chars(struct tty_struct * tty)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
func_enter ();
+
+ if (!tty) return;
+
+ port = tty->driver_data;
+
+ if (!port) return;
+
if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
!port->xmit_buf) {
func_exit ();
void gs_stop(struct tty_struct * tty)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
func_enter ();
+
+ if (!tty) return;
+
+ port = tty->driver_data;
+
+ if (!port) return;
+
if (port->xmit_cnt &&
port->xmit_buf &&
(port->flags & GS_TX_INTEN) ) {
void gs_start(struct tty_struct * tty)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
+
+ if (!tty) return;
+
+ port = tty->driver_data;
+
+ if (!port) return;
if (port->xmit_cnt &&
port->xmit_buf &&
void gs_shutdown_port (struct gs_port *port)
{
long flags;
+
func_enter();
+
+ if (!port) return;
+
if (!(port->flags & ASYNC_INITIALIZED))
return;
void gs_hangup(struct tty_struct *tty)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
func_enter ();
+ if (!tty) return;
+
+ port = tty->driver_data;
tty = port->tty;
if (!tty) return;
struct gs_port *port = private_;
struct tty_struct *tty;
+ func_enter ();
+
+ if (!port) return;
+
tty = port->tty;
- if(!tty) return;
+
+ if (!tty) return;
if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
wake_up_interruptible(&tty->write_wait);
- wake_up_interruptible(&tty->poll_wait);
}
func_exit ();
}
struct tty_struct *tty;
func_enter ();
+
+ if (!port) return 0;
+
tty = port->tty;
+ if (!tty) return 0;
+
gs_dprintk (GS_DEBUG_BTR, "Entering block_till_ready.\n");
/*
* If the device is in the middle of being closed, then block
do_clocal = 1;
}
- gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n");
-
/*
* Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
* exit, either normal or abnormal.
*/
retval = 0;
+
add_wait_queue(&port->open_wait, &wait);
gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n");
-
cli();
if (!tty_hung_up_p(filp))
port->count--;
struct gs_port *port;
func_enter ();
- port = (struct gs_port *) tty->driver_data;
- gs_dprintk (GS_DEBUG_CLOSE, "tty=%p, port=%p port->tty=%p\n",
- tty, port, port->tty);
+ if (!tty) return;
- if(! port) {
- func_exit();
- return;
- }
+ port = (struct gs_port *) tty->driver_data;
+
+ if (!port) return;
if (!port->tty) {
/* This seems to happen when this is called from vhangup. */
port->tty = tty;
}
-
save_flags(flags); cli();
if (tty_hung_up_p(filp)) {
void gs_set_termios (struct tty_struct * tty,
struct termios * old_termios)
{
- struct gs_port *port = tty->driver_data;
+ struct gs_port *port;
int baudrate, tmp, rv;
struct termios *tiosp;
func_enter();
- tiosp = tty->termios;
+ if (!tty) return;
+
+ port = tty->driver_data;
+ if (!port) return;
+
+ tiosp = tty->termios;
if (gs_debug & GS_DEBUG_TERMIOS) {
gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
#ifdef CONFIG_VIDEO_BT848
extern int i2c_tuner_init(void);
-extern int msp3400c_init(void);
#endif
+extern int msp3400c_init(void);
#ifdef CONFIG_VIDEO_BUZ
extern int saa7111_init(void);
extern int saa7185_init(void);
* base. Also line nunber as such is meaningless but we use it for our
* array index so it is fixed also.
*/
- if ( ns.irq != ip2config.irq
+ if ( ns.irq != ip2config.irq[pCh->port_index]
|| (int) ns.port != ((int) pCh->pMyBord->i2eBase)
|| ns.baud_base != pCh->BaudBase
|| ns.line != pCh->port_index ) {
extern void wdt_init(void);
extern void acq_init(void);
extern void wdt60xx_init(void);
+extern void sbc60xxwdt_init(void);
extern void dtlk_init(void);
extern void pcwatchdog_init(void);
extern int rtc_init(void);
extern int rio_ismodem (kdev_t device);
extern void rio_udelay (int usecs);
+extern void rio_start_card_running (struct Host * HostP);
+
#endif /* __func_h_def */
uchar Mode; /* Control stuff */
uchar Slot; /* Slot */
volatile caddr_t Caddr; /* KV address of DPRAM */
- volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */
+ volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */
paddr_t PaddrP; /* Phys. address of DPRAM */
char Name[MAX_NAME_LEN]; /* The name of the host */
uint UniqueNum; /* host unique number */
- semtype HostLock; /* Lock structure for MPX */
- /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */
+ spinlock_t HostLock; /* Lock structure for MPX */
+ /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */
/*struct lockb HostLock; *//* Lock structure for MPX */
uint WorkToBeDone; /* set to true each interrupt */
uint InIntr; /* Being serviced? */
- uint IntSrvDone; /* host's interrupt has been serviced */
+ uint IntSrvDone;/* host's interrupt has been serviced */
int (*Copy)( caddr_t, caddr_t, int ); /* copy func */
struct timer_list timer;
/*
#define SEM_SIGIGNORE 0x1234
-typedef struct semaphore semtype;
-
-
#ifdef DEBUG_SEM
#define swait(a,b) printk ("waiting: " __FILE__ " line %d\n", __LINE__)
#define ssignal(sem) printk ("signalling: " __FILE__ " line %d\n", __LINE__)
more than 512 ports.... */
-/* ************************************************************** */
-/* * This section can be removed when 2.0 becomes outdated.... * */
-/* ************************************************************** */
-
-#if LINUX_VERSION_CODE < 0x020100 /* Less than 2.1.0 */
-#define TWO_ZERO
-#else
-#if LINUX_VERSION_CODE < 0x020209 /* less than 2.2.x */
-#warning "Please use a recent 2.2.x kernel. "
-#endif
-#endif
-
-
-#ifdef TWO_ZERO
-
-/* Here is the section that makes the 2.2 compatible driver source
- work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2,
- and provide for compatibility stuff here if possible. */
-
-#include <linux/bios32.h>
-
-#define Get_user(a,b) a = get_user(b)
-#define Put_user(a,b) 0,put_user(a,b)
-#define copy_to_user(a,b,c) memcpy_tofs(a,b,c)
-
-static inline int copy_from_user(void *to,const void *from, int c)
-{
- memcpy_fromfs(to, from, c);
- return 0;
-}
-
-#define pci_present pcibios_present
-#define pci_read_config_word pcibios_read_config_word
-#define pci_read_config_dword pcibios_read_config_dword
-
-static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
-{
- unsigned char t;
- pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
- return t;
-}
-
-static inline void *ioremap(unsigned long base, long length)
-{
- if (base < 0x100000) return (void *)base;
- return vremap (base, length);
-}
-
-#define my_iounmap(x, b) (((long)x<0x100000)?0:vfree ((void*)x))
-
-#define capable(x) suser()
-
-#define queue_task queue_task_irq_off
-#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer)
-#define signal_pending(current) (current->signal & ~current->blocked)
-#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0)
-#define time_after(t1,t2) (((long)t1-t2) > 0)
-
-
-#define test_and_set_bit(nr, addr) set_bit(nr, addr)
-#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
-
-/* Not yet implemented on 2.0 */
-#define ASYNC_SPD_SHI -1
-#define ASYNC_SPD_WARP -1
-
-
-/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
- to the "name" field that does exist. As long as the assignments are
- done in the right order, there is nothing to worry about. */
-#define driver_name name
-
-/* Should be in a header somewhere. They are in tty.h on 2.2 */
-#define TTY_HW_COOK_OUT 14 /* Flag to tell ntty what we can handle */
-#define TTY_HW_COOK_IN 15 /* in hardware - output and input */
-
-/* The return type of a "close" routine. */
-#define INT void
-#define NO_ERROR /* Nothing */
-
-#else
-
-/* The 2.2.x compatibility section. */
-#include <asm/uaccess.h>
-
-#define Get_user(a,b) get_user(a,b)
-#define Put_user(a,b) put_user(a,b)
-#define get_irq(pdev) pdev->irq
-
-#define INT int
-#define NO_ERROR 0
-
-#define my_iounmap(x,b) (iounmap((char *)(b)))
-
-#endif
-
-/* ************************************************************** */
-/* * End of compatibility section.. * */
-/* ************************************************************** */
-
-
-
/* Why the hell am I defining these here? */
#define RIO_TYPE_NORMAL 1
#define RIO_TYPE_CALLOUT 2
NULL
};
-
-/*
- This driver can spew a whole lot of debugging output at you. If you
- need maximum performance, you should disable the DEBUG define. To
- aid in debugging in the field, I'm leaving the compile-time debug
- features enabled, and disable them "runtime". That allows me to
- instruct people with problems to enable debugging without requiring
- them to recompile...
-*/
-#define DEBUG
-
-#ifdef DEBUG
-#define rio_dprintk(f, str...) if (rio_debug & f) printk (str)
-#else
-#define rio_dprintk(f, str...) /* nothing */
-#endif
-
-
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
-#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n")
-
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
- "(port %d)\n", port->line)
-
-
-
-
/*
* Firmware loader driver specific routines
*
*/
static struct file_operations rio_fw_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- rio_fw_ioctl,
- NULL, /* mmap */
- rio_fw_open,
-#ifndef TWO_ZERO
- NULL, /* flush */
-#endif
- rio_fw_release,
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
+ open: rio_fw_open,
+ release: rio_fw_release,
+ ioctl: rio_fw_ioctl,
};
struct miscdevice rio_fw_device = {
KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
if (!port) {
- printk(badinfo, kdevname(device), routine);
+ printk (badinfo, kdevname(device), routine);
return 1;
}
if (port->magic != RIO_MAGIC) {
- printk(badmagic, kdevname(device), routine);
+ printk (badmagic, kdevname(device), routine);
return 1;
}
unsigned char *addr = ad;
for (i=0;i<len;i+=16) {
- printk ("%08x ", (int) addr+i);
+ rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i);
for (j=0;j<16;j++) {
- printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+ rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":"");
}
for (j=0;j<16;j++) {
ch = addr[j+i];
- printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+ rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
}
- printk ("\n");
+ rio_dprintk (RIO_DEBUG_PARAM, "\n");
}
}
#else
void rio_reset_interrupt (struct Host *HostP)
{
+ func_enter();
+
switch( HostP->Type ) {
case RIO_AT:
case RIO_MCA:
case RIO_PCI:
WBYTE(HostP->ResetInt , 0xff);
}
+
+ func_exit();
}
static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
{
struct Host *HostP;
+ func_enter ();
- HostP = &p->RIOHosts[(long)ptr];
- /* func_enter (); */
+ HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */
+
rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n",
irq, HostP->Ivec);
}
}
#endif
-
+ rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
if (HostP->Ivec == irq) {
/* Tell the card we've noticed the interrupt. */
rio_reset_interrupt (HostP);
clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);
rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n",
irq, HostP->Ivec);
- /* func_exit (); */
+ func_exit ();
}
{
func_enter ();
- rio_interrupt (0, (void *)data, NULL);
+ rio_interrupt (0, &p->RIOHosts[data], NULL);
p->RIOHosts[data].timer.expires = jiffies + rio_poll;
add_timer (&p->RIOHosts[data].timer);
#if 0
port->gs.flags &= ~ GS_ACTIVE;
if (!port->gs.tty) {
- printk ("No tty.\n");
+ rio_dprintk (RIO_DBUG_TTY, "No tty.\n");
return;
}
if (!port->gs.tty->termios) {
- printk ("No termios.\n");
+ rio_dprintk (RIO_DEBUG_TTY, "No termios.\n");
return;
}
if (port->gs.tty->termios->c_cflag & HUPCL) {
}
-
/* ********************************************************************** *
* Here are the routines that actually *
* interface with the rest of the system *
if (rio_debug & RIO_DEBUG_PROBE)
my_hd ((char *)&vpdp, 0x20);
+
+ func_exit();
return &vpdp;
}
/* However, the RIO driver allows users to configure their first
RTA as the ports numbered 504-511. We therefore need to allocate
the whole range. :-( -- REW */
-
+
#define RI_SZ sizeof(struct rio_info)
#define HOST_SZ sizeof(struct Host)
#define PORT_SZ sizeof(struct Port *)
port->gs.close_delay = HZ/2;
port->gs.closing_wait = 30 * HZ;
port->gs.rd = &rio_real_driver;
+
}
#else
/* We could postpone initializing them to when they are configured. */
#endif
+
+
if (rio_debug & RIO_DEBUG_INIT) {
my_hd (&rio_real_driver, sizeof (rio_real_driver));
}
return -ENOMEM;
}
-
+#ifdef MODULE
static void rio_release_drivers(void)
{
func_enter();
tty_unregister_driver (&rio_driver);
func_exit();
}
+#endif
#ifdef TWO_ZERO
#define PDEV unsigned char pci_bus, unsigned pci_fun
unsigned int t;
#define CNTRL_REG_OFFSET 0x50
-#define CNTRL_REG_GOODVALUE 0x00260000
+#define CNTRL_REG_GOODVALUE 0x18260000
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
pci_read_config_dword (pdev, 0x2c, &tint);
tshort = (tint >> 16) & 0xffff;
rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
- /* rio_dprintk (RIO_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */
if (tshort != 0x0100) {
rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n",
tshort);
hp = &p->RIOHosts[p->RIONumHosts];
hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
hp->Ivec = get_irq (pdev);
- if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
hp->CardP = (struct DpRam *)
hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
hp->Type = RIO_PCI;
hp->Copy = rio_pcicopy;
- hp->Mode = RIO_PCI_DEFAULT_MODE;
-
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+ rio_reset_interrupt (hp);
+ rio_start_card_running (hp);
+
rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
(void *)p->RIOHosts[p->RIONumHosts].PaddrP,
p->RIOHosts[p->RIONumHosts].Caddr);
if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
p->RIOHosts[p->RIONumHosts].Caddr,
RIO_PCI, 0 ) == RIO_SUCCESS) {
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-#if 1
- fix_rio_pci (pdev);
-#endif
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- found++;
+ rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n");
+ WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+ p->RIOHosts[p->RIONumHosts].UniqueNum =
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
+ rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+ p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+ fix_rio_pci (pdev);
+ p->RIOLastPCISearch = RIO_SUCCESS;
+ p->RIONumHosts++;
+ found++;
} else {
- my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr);
+ my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP,
+ p->RIOHosts[p->RIONumHosts].Caddr);
}
-
+
#ifdef TWO_ZERO
} /* We have two variants with the opening brace, so to prevent */
#else
} /* Emacs from getting confused we have two closing braces too. */
#endif
-
/* Then look for the older PCI card.... : */
#ifndef TWO_ZERO
+
/* These older PCI cards have problems (only byte-mode access is
supported), which makes them a bit awkward to support.
They also have problems sharing interrupts. Be careful.
hp = &p->RIOHosts[p->RIONumHosts];
hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
hp->Ivec = get_irq (pdev);
- if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
hp->Ivec |= 0x8000; /* Mark as non-sharable */
hp->CardP = (struct DpRam *)
hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
hp->Type = RIO_PCI;
hp->Copy = rio_pcicopy;
- hp->Mode = RIO_PCI_DEFAULT_MODE;
-
- rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+
+ rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
+ rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
+
+ rio_reset_interrupt (hp);
+ rio_start_card_running (hp);
+ rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
(void *)p->RIOHosts[p->RIONumHosts].PaddrP,
p->RIOHosts[p->RIONumHosts].Caddr);
if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
hp->CardP = (struct DpRam *)
hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
hp->Type = RIO_AT;
- hp->Copy = rio_pcicopy;
+ hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
+ * -- YES! this is now a normal copy. Only the
+ * old PCI card uses the special PCI copy.
+ * Moreover, the ISA card will work with the
+ * special PCI copy anyway. -- REW */
hp->Mode = 0;
vpdp = get_VPD_PROM (hp);
-
+ rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n");
okboard = 0;
if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) ||
(strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) ||
if (hp->Ivec) {
int mode = SA_SHIRQ;
if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;}
- if (request_irq (hp->Ivec, rio_interrupt, mode, "rio", (void *)i)) {
- printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
- hp->Ivec = 0;
+ rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode);
+ retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp);
+ rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
+ if (retval) {
+ printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+ hp->Ivec = 0;
}
rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+ if (hp->Ivec != 0){
+ rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
+ hp->Mode |= RIO_PCI_INT_ENABLE;
+ } else
+ hp->Mode &= !RIO_PCI_INT_ENABLE;
+ rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
+ rio_start_card_running (hp);
}
/* Init the timer "always" to make sure that it can safely be
deleted when we unload... */
}
if (found) {
- printk (KERN_INFO "rio: total of %d boards detected.\n", found);
+ rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
if (misc_register(&rio_fw_device) < 0) {
printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) {
RIOHostReset (hp->Type, hp->CardP, hp->Slot);
if (hp->Ivec) {
- free_irq (hp->Ivec, (void *)i);
+ free_irq (hp->Ivec, hp);
rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
}
/* It is safe/allowed to del_timer a non-active timer */
* Version 1.0 -- July, 1999.
*
*/
+#include <linux/config.h>
#define RIO_NBOARDS 4
#define RIO_PORTSPERBOARD 128
#define rio_memcpy_fromio memcpy_fromio
#endif
+#define DEBUG
+
+
+/*
+ This driver can spew a whole lot of debugging output at you. If you
+ need maximum performance, you should disable the DEBUG define. To
+ aid in debugging in the field, I'm leaving the compile-time debug
+ features enabled, and disable them "runtime". That allows me to
+ instruct people with problems to enable debugging without requiring
+ them to recompile...
+*/
+
+#ifdef DEBUG
+#define rio_dprintk(f, str...) if (rio_debug & f) printk (str)
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
+#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n")
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
+ "(port %d)\n", port->line)
+#else
+#define rio_dprintk(f, str...) /* nothing */
+#define func_enter()
+#define func_exit()
+#define func_enter2()
+#endif
+
#endif
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#include "cmdblk.h"
#include "route.h"
-
static uchar
RIOAtVec2Ctrl[] =
{
{
int offset;
+ func_enter ();
+
/* Linux doesn't allow you to disable interrupts during a
"copyin". (Crash when a pagefault occurs). */
/* disable(oldspl); */
rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code Too Large!\n"));
p->RIOError.Error = HOST_FILE_TOO_LARGE;
/* restore(oldspl); */
+ func_exit ();
return ENOMEM;
}
rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code : BUSY BUSY BUSY!\n"));
p->RIOError.Error = BOOT_IN_PROGRESS;
/* restore(oldspl); */
+ func_exit ();
return EBUSY;
}
rio_dprint(RIO_DEBUG_BOOT, ("Bad data copy from user space\n"));
p->RIOError.Error = COPYIN_FAILED;
/* restore(oldspl); */
+ func_exit ();
return EFAULT;
}
p->RIOBootCount = rbp->Count;
/* restore(oldspl); */
+ func_exit();
return 0;
}
+void rio_start_card_running (struct Host * HostP)
+{
+ func_enter ();
+
+ switch ( HostP->Type ) {
+ case RIO_AT:
+ rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n"));
+ WBYTE(HostP->Control,
+ BOOT_FROM_RAM | EXTERNAL_BUS_ON
+ | HostP->Mode
+ | RIOAtVec2Ctrl[HostP->Ivec & 0xF] );
+ break;
+
+#ifdef FUTURE_RELEASE
+ case RIO_MCA:
+ /*
+ ** MCA handles IRQ vectors differently, so we don't write
+ ** them to this register.
+ */
+ rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n"));
+ WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode);
+ break;
+
+ case RIO_EISA:
+ /*
+ ** EISA is totally different and expects OUTBZs to turn it on.
+ */
+ rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n");
+ OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM );
+ break;
+#endif
+
+ case RIO_PCI:
+ /*
+ ** PCI is much the same as MCA. Everything is once again memory
+ ** mapped, so we are writing to memory registers instead of io
+ ** ports.
+ */
+ rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n"));
+ WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
+ break;
+ default:
+ rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type));
+ break;
+ }
+/*
+ printk (KERN_INFO "Done with starting the card\n");
+ func_exit ();
+*/
+ return;
+}
/*
** Load in the host boot code - load it directly onto all halted hosts
for ( host=0; host<p->RIONumHosts; host++ ) {
rio_dprint(RIO_DEBUG_BOOT, ("Attempt to boot host %d\n",host));
HostP = &p->RIOHosts[host];
+
+ rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
+ HostP->Type, HostP->Mode, HostP->Ivec ) );
+
if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) {
rio_dprint(RIO_DEBUG_BOOT, ("%s %d already running\n","Host",host));
if ( p->RIOConf.HostLoadBase < rbp->Count ) {
rio_dprint(RIO_DEBUG_BOOT, ("Bin too large\n"));
p->RIOError.Error = HOST_FILE_TOO_LARGE;
+ func_exit ();
return EFBIG;
}
/*
if ( !DownCode ) {
rio_dprint(RIO_DEBUG_BOOT, ("No system memory available\n"));
p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
+ func_exit ();
return ENOMEM;
}
bzero(DownCode, rbp->Count);
if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) {
rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
p->RIOError.Error = COPYIN_FAILED;
+ func_exit ();
return EFAULT;
}
else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) {
rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
p->RIOError.Error = COPYIN_FAILED;
+ func_exit ();
return EFAULT;
}
rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
HostP->Type, HostP->Mode, HostP->Ivec ) );
- switch ( HostP->Type ) {
- case RIO_AT:
- rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n"));
- WBYTE(HostP->Control,
- BOOT_FROM_RAM | EXTERNAL_BUS_ON
- | HostP->Mode
- | RIOAtVec2Ctrl[HostP->Ivec & 0xF] );
- break;
+ rio_start_card_running(HostP);
-#ifdef FUTURE_RELEASE
- case RIO_MCA:
- /*
- ** MCA handles IRQ vectors differently, so we don't write
- ** them to this register.
- */
- rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n"));
- WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode);
- break;
-
- case RIO_EISA:
- /*
- ** EISA is totally different and expects OUTBZs to turn it on.
- */
- rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n");
- OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM );
- break;
-#endif
-
- case RIO_PCI:
- /*
- ** PCI is much the same as MCA. Everything is once again memory
- ** mapped, so we are writing to memory registers instead of io
- ** ports.
- */
- rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n"));
- WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
- break;
- default:
- rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type));
- break;
- }
rio_dprint(RIO_DEBUG_BOOT, ("Set control port\n"));
/*
** pointer:
*/
for ( wait_count=0; (wait_count<p->RIOConf.StartupTime)&&
- (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) {
+ (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) {
rio_dprint(RIO_DEBUG_BOOT, ("Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR)));
delay(HostP, HUNDRED_MS);
+
}
/*
p->RIOSystemUp++;
rio_dprint(RIO_DEBUG_BOOT, ("Done everything %x\n", HostP->Ivec));
+ func_exit ();
return 0;
}
#endif
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#include <asm/system.h>
#include <asm/string.h>
#include <asm/semaphore.h>
-#include <asm/spinlock.h>
-
#include <linux/termios.h>
#include <linux/serial.h>
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
int retval = 0;
unsigned long flags;
+ func_enter ();
+
/* Confuse teh compiler to think that we've initialized these */
Host=0;
PortP = NULL;
}
rio_dprint(RIO_DEBUG_CTRL, ("INVALID DAEMON IOCTL 0x%x\n",cmd));
p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+
+ func_exit ();
return EINVAL;
}
struct rio_info {
int mode; /* Intr or polled, word/byte */
- semtype RIOIntrSem; /* Interrupt thread sem */
+ spinlock_t RIOIntrSem; /* Interrupt thread sem */
int current_chan; /* current channel */
int RIOFailed; /* Not initialised ? */
int RIOInstallAttempts; /* no. of rio-install() calls */
(int)p->RIOHosts, sizeof(struct Host) ) );
for( host=0; host<RIO_HOSTS; host++ ) {
- p->RIOHosts[host].HostLock = -1; /* Let the first guy takes it */
+ spin_lock_init (&p->RIOHosts[host].HostLock);
p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */
}
/*
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
rio_dprint (RIO_DEBUG_INTR, ("(%d/%d)\n",
PortP->gs.wakeup_chars, PortP->gs.xmit_cnt));
wake_up_interruptible(&PortP->gs.tty->write_wait);
- wake_up_interruptible(&PortP->gs.tty->poll_wait);
}
}
#endif
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#endif
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#endif
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#define __EXPLICIT_DEF_H__
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#include "list.h"
#include "sam.h"
-
#if 0
static void ttyseth_pv(struct Port *, struct ttystatics *,
struct termios *sg, int);
unsigned long flags;
int retval = 0;
+ func_enter ();
+
+ /* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
+ is going to oops.
+ */
+ tty->driver_data = NULL;
+
SysPort = rio_minor (tty->device);
Modem = rio_ismodem (tty->device);
if ( p->RIOFailed ) {
rio_dprint(RIO_DEBUG_TTY, ("System initialisation failed\n"));
pseterr(ENXIO);
- return 0;
+ func_exit ();
+ return -ENXIO;
}
rio_dprint(RIO_DEBUG_TTY, ("port open SysPort %d (%s) (mapped:%d)\n",
if (SysPort >= RIO_PORTS) { /* out of range ? */
rio_dprint(RIO_DEBUG_TTY, ("Illegal port number %d\n",SysPort));
pseterr(ENXIO);
- return 0;
+ func_exit();
+ return -ENXIO;
}
/*
** Grab pointer to the port stucture
*/
PortP = p->RIOPortp[SysPort]; /* Get control struc */
-
+ rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP);
if ( !PortP->Mapped ) { /* we aren't mapped yet! */
/*
** The system doesn't know which RTA this port
** corresponds to.
*/
rio_dprint(RIO_DEBUG_TTY, ("port not mapped into system\n"));
+ func_exit ();
pseterr(ENXIO);
- return 0;
+ return -ENXIO;
}
tty->driver_data = PortP;
if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) {
rio_dprint(RIO_DEBUG_TTY, ("Host not running\n"));
pseterr(ENXIO);
- return 0;
+ func_exit ();
+ return -ENXIO;
}
/*
do {
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
rio_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n"));
+ func_exit ();
return -EINTR;
}
if (repeat_this -- <= 0) {
rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
RIOPreemptiveCmd(p, PortP, FCLOSE );
pseterr(EINTR);
+ func_exit ();
return -EIO;
}
} while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
} else {
rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
pseterr(ENXIO);
+ func_exit ();
return 0;
}
}
while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
if (!PortP->WaitUntilBooted) {
rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
+ func_exit ();
return -ENXIO;
}
*/
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
rio_dprint(RIO_DEBUG_TTY, ("RTA_wait_for_boot: EINTR in delay \n"));
+ func_exit ();
return -EINTR;
}
if (repeat_this -- <= 0) {
rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
+ func_exit ();
return -EIO;
}
}
}
#if 0
retval = gs_init_port(&PortP->gs);
- if (retval)
- return retval;
+ if (retval){
+ func_exit ();
+ return retval;
+ }
#endif
/*
rio_dprint(RIO_DEBUG_TTY, ("Port unmapped while closing!\n"));
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
retval = -ENXIO;
+ func_exit ();
return retval;
}
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish broken by signal\n"));
RIOPreemptiveCmd(p, PortP, FCLOSE );
+ func_exit ();
return -EINTR;
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
tp->tm.c_state &= ~WOPEN;
PortP->State &= ~RIO_WOPEN;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit ();
return -EINTR;
}
}
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
rio_dprint(RIO_DEBUG_TTY, ("Returning from open\n"));
+ func_exit ();
return 0;
}
uint Id; /* Id number */
uint BaseSysPort; /* SysPort of first tty on this RTA */
uint ModTypes; /* Modules on this RTA */
- semtype RupLock; /* Lock structure for MPX */
+ spinlock_t RupLock; /* Lock structure for MPX */
/* struct lockb RupLock; */ /* Lock structure for MPX */
};
*
* Revision history:
* $Log: sx.c,v $
- * Revision 1.32 2000/03/07 90:00:00 wolff,pvdl
+ * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff
+ * - Fixed module and port counting
+ * - Fixed signal handling
+ * - Fixed an Ooops
+ *
+ * Revision 1.32 2000/03/07 09:00:00 wolff,pvdl
* - Fixed some sx_dprintk typos
* - added detection for an invalid board/module configuration
*
* */
-#define RCS_ID "$Id: sx.c,v 1.32 2000/03/07 17:01:02 wolff, pvdl Exp $"
-#define RCS_REV "$Revision: 1.32 $"
+#define RCS_ID "$Id: sx.c,v 1.33 2000/03/08 10:01:02 wolff, pvdl Exp $"
+#define RCS_REV "$Revision: 1.33 $"
#include <linux/module.h>
*/
static struct file_operations sx_fw_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select */
- sx_fw_ioctl,
- NULL, /* mmap */
- sx_fw_open,
-#ifndef TWO_ZERO
- NULL, /* flush */
-#endif
- sx_fw_release,
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
+ open: sx_fw_open,
+ release: sx_fw_release,
+ ioctl: sx_fw_ioctl
};
struct miscdevice sx_fw_device = {
if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS);
sx_write_channel_byte (port, hi_op, t);
sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
+
func_exit ();
}
if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
- sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) \n",
- c, SERIAL_XMIT_SIZE- port->gs.xmit_tail);
+ sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%ld) \n",
+ c, (long)SERIAL_XMIT_SIZE- port->gs.xmit_tail);
/* If for one reason or another, we can't copy more data, we're done! */
if (c == 0) break;
sx_disable_tx_interrupts (port);
}
- if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
+ if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
port->gs.tty->ldisc.write_wakeup)
(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
port->gs.wakeup_chars);
wake_up_interruptible(&port->gs.tty->write_wait);
- wake_up_interruptible(&port->gs.tty->poll_wait);
}
clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
struct tty_struct *tty;
int copied=0;
- /* func_enter2 (); */
+ func_enter2 ();
tty = port->gs.tty;
while (1) {
rx_op = sx_read_channel_byte (port, hi_rxopos);
/* tty_schedule_flip (tty); */
}
- /* func_exit (); */
+ func_exit ();
}
/* Inlined: it is called only once. Remove the inline if you add another
sx_interrupt (0, board, NULL);
+ init_timer(&board->timer);
+
board->timer.expires = jiffies + sx_poll;
add_timer (&board->timer);
func_exit ();
func_enter();
port->gs.flags &= ~ GS_ACTIVE;
- if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
+ if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) {
sx_setsignals (port, 0, 0);
sx_reconfigure_port(port);
}
* interface with the rest of the system *
* ********************************************************************** */
-
static int sx_fw_open(struct inode *inode, struct file *filp)
{
func_enter ();
}
+
static int sx_open (struct tty_struct * tty, struct file * filp)
{
struct sx_port *port;
tty->driver_data = port;
port->gs.tty = tty;
+ if (!port->gs.count)
+ MOD_INC_USE_COUNT;
port->gs.count++;
sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n");
if (retval) {
port->gs.count--;
+ if (port->gs.count) MOD_DEC_USE_COUNT;
return retval;
}
port->gs.flags |= GS_ACTIVE;
sx_setsignals (port, 1,1);
- sx_dprintk (SX_DEBUG_OPEN, "before inc_use_count (count=%d.\n",
- port->gs.count);
- if (port->gs.count == 1) {
- MOD_INC_USE_COUNT;
- }
- sx_dprintk (SX_DEBUG_OPEN, "after inc_use_count\n");
-
#if 0
if (sx_debug & SX_DEBUG_OPEN)
my_hd ((unsigned char *)port, sizeof (*port));
if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
- MOD_DEC_USE_COUNT;
port->gs.count--;
+ if (!port->gs.count) MOD_DEC_USE_COUNT;
return -EIO;
}
retval, port->gs.count);
if (retval) {
- MOD_DEC_USE_COUNT;
- port->gs.count--;
+ /*
+ * Don't lower gs.count here because sx_close() will be called later
+ */
+
return retval;
}
/* tty->low_latency = 1; */
exit minicom. I expect an "oops". -- REW */
static void sx_hungup (void *ptr)
{
-/*
- func_enter ();
- MOD_DEC_USE_COUNT;
- func_exit ();
-*/
- /*
- * Got this from the 2.4.0-test1 serie. The port was closed before
- * the lines were set in the proper condition. -- pvdl
- */
struct sx_port *port = ptr;
func_enter ();
- /*
- * Set the lines in the proper codition before closing the port.
- * Got the from 2.4.0-test1 series. -- pvdl
- */
+ /* Don't force the SX card to close. mgetty doesn't like it !!!!!! -- pvdl */
+ /* For some reson we added this code. Don't know why anymore ;-) -- pvdl */
+ /*
sx_setsignals (port, 0, 0);
sx_reconfigure_port(port);
- sx_send_command (port, HS_CLOSE, -1, HS_IDLE_CLOSED);
+ sx_send_command (port, HS_CLOSE, 0, 0);
if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) {
if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) {
} else
sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n");
}
-
+ */
MOD_DEC_USE_COUNT;
func_exit ();
}
sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
5 * HZ - to - 1, port->gs.count);
+ if(port->gs.count) {
+ sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
+ port->gs.count = 0;
+ }
+
MOD_DEC_USE_COUNT;
func_exit ();
}
func_enter();
/* This is preceded by downloading the download code. */
- /*
- * The board should be set to initialized to make sure
- * we can boot the other cards. --pvdl
- */
+
board->flags |= SX_BOARD_INITIALIZED;
if (read_sx_byte (board, 0))
#ifdef NEW_WRITE_LOCKING
port->gs.port_write_sem = MUTEX;
#endif
+ /*
+ * Initializing wait queue
+ */
+ /*
+ init_waitqueue_head(&port->gs.open_wait);
+ init_waitqueue_head(&port->gs.close_wait);
+ */
port++;
}
}
return 0;
}
-
+#ifdef MODULE
static void sx_release_drivers(void)
{
func_enter();
tty_unregister_driver(&sx_callout_driver);
func_exit();
}
+#endif
#ifdef TWO_ZERO
#define PDEV unsigned char pci_bus, unsigned pci_fun
while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
pdev))) {
+ /*
+ if (pci_enable_device(pdev))
+ continue;
+ */
#else
for (i=0;i< SX_NBOARDS;i++) {
if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX,
&tint);
else
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
- &tint);
- board->hw_base = tint & PCI_BASE_ADDRESS_MEM_MASK;
+ &tint);
board->base2 =
board->base = (ulong) ioremap(board->hw_base, WINDOW_LEN (board));
+ if (!board->base) {
+ printk(KERN_ERR "ioremap failed\n");
+ /* XXX handle error */
+ }
+
/* Most of the stuff on the CF board is offset by
0x18000 .... */
if (IS_CF_BOARD (board)) board->base += 0x18000;
#ifdef CONFIG_HWC_CONSOLE
extern long hwc_console_init(long);
#endif
+extern int rio_init(void);
+extern int sx_init(void);
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int);
static void i2ob_end_request(struct request *);
-static void i2ob_request(struct request * q);
+static void i2ob_request(void);
static int do_i2ob_revalidate(kdev_t, int);
static int i2ob_query_device(struct i2ob_device *, int, int, void*, int);
static int i2ob_evt(void *);
static int evt_pid = 0;
static int evt_running = 0;
+static int scan_unit = 0;
static void i2ob_new_device(struct i2o_controller *, struct i2o_device *);
static void i2ob_del_device(struct i2o_controller *, struct i2o_device *);
}
- if(msg->function == I2O_CMD_UTIL_EVT_REGISTER)
- {
- spin_lock(&i2ob_evt_lock);
- memcpy(&evt_msg, m, msg->size);
- spin_unlock(&i2ob_evt_lock);
- wake_up_interruptible(&i2ob_evt_wait);
- return;
- }
+ if(msg->function == I2O_CMD_UTIL_EVT_REGISTER)
+ {
+ spin_lock(&i2ob_evt_lock);
+ memcpy(&evt_msg, m, msg->size);
+ spin_unlock(&i2ob_evt_lock);
+ wake_up_interruptible(&i2ob_evt_wait);
+ return;
+ }
if(!dev->i2odev)
{
/*
return;
}
- /*
- * Lets see what is cooking. We stuffed the
- * request in the context.
- */
+ /*
+ * Lets see what is cooking. We stuffed the
+ * request in the context.
+ */
- ireq=&i2ob_queue[m[3]];
- st=m[4]>>24;
+ ireq=&i2ob_queue[m[3]];
+ st=m[4]>>24;
- if(st!=0)
- {
- char *bsa_errors[] =
- {
+ if(st!=0)
+ {
+ char *bsa_errors[] = {
"Success",
"Media Error",
"Failure communicating to device",
"Device is write protected",
"Device has reset",
"Volume has changed, waiting for acknowledgement"
- };
- printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, bsa_errors[m[4]&0XFFFF]);
+ };
- if(m[4]&0x00FF0000)
- printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF);
- printk("\n");
+ printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, bsa_errors[m[4]&0XFFFF]);
- ireq->req->errors++;
+ if(m[4]&0x00FF0000)
+ printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF);
+ printk("\n");
- if (ireq->req->errors < MAX_I2OB_RETRIES)
+ ireq->req->errors++;
+ if (ireq->req->errors < MAX_I2OB_RETRIES)
+ {
+ u32 retry_msg;
+ printk(KERN_ERR "i2ob: attempting retry %d for request %p\n",ireq->req->errors+1,ireq->req);
+
+ /*
+ * Get a message for this retry.
+ */
+ retry_msg = i2ob_get(dev);
+
+ /*
+ * If we cannot get a message then
+ * forget the retry and fail the
+ * request. Note that since this is
+ * being called from the interrupt
+ * handler, a request has just been
+ * completed and there will most likely
+ * be space on the inbound message
+ * fifo so this won't happen often.
+ */
+ if(retry_msg!=0xFFFFFFFF)
{
- u32 retry_msg;
-
- printk(KERN_ERR "i2ob: attempting retry %d for request %p\n",ireq->req->errors+1,ireq->req);
-
- /*
- * Get a message for this retry.
+ /*
+ * Decrement the queue depth since
+ * this request has completed and
+ * it will be incremented again when
+ * i2ob_send is called below.
*/
- retry_msg = i2ob_get(dev);
-
- /*
- * If we cannot get a message then
- * forget the retry and fail the
- * request. Note that since this is
- * being called from the interrupt
- * handler, a request has just been
- * completed and there will most likely
- * be space on the inbound message
- * fifo so this won't happen often.
+ atomic_dec(&queue_depth);
+ /*
+ * Send the request again.
*/
- if(retry_msg!=0xFFFFFFFF)
- {
- /*
- * Decrement the queue depth since
- * this request has completed and
- * it will be incremented again when
- * i2ob_send is called below.
- */
- atomic_dec(&queue_depth);
-
- /*
- * Send the request again.
- */
- i2ob_send(retry_msg, dev,ireq,i2ob[unit].start_sect, (unit&0xF0));
- /*
- * Don't fall through.
- */
- return;
- }
- }
- }
- else
- ireq->req->errors = 0;
+ i2ob_send(retry_msg, dev,ireq,i2ob[unit].start_sect, (unit&0xF0));
+ /*
+ * Don't fall through.
+ */
+ return;
+ }
+ }
+ }
+ else
+ ireq->req->errors = 0;
/*
* Dequeue the request. We use irqsave locks as one day we
*/
atomic_dec(&queue_depth);
- i2ob_request(NULL);
+ i2ob_request();
spin_unlock_irqrestore(&io_request_lock, flags);
}
/*
* Restart any requests.
*/
- i2ob_request(NULL);
+ i2ob_request();
/*
* Free the lock.
* we use it.
*/
-static void i2ob_request(struct request * q)
+static void i2ob_request(void)
{
unsigned long flags;
struct request *req;
CURRENT = CURRENT->next;
req->sem = NULL;
i2ob_end_request(req);
+ continue;
}
- else
- {
/* Get a message */
m = i2ob_get(dev);
ireq->req = req;
i2ob_send(m, dev, ireq, i2ob[unit].start_sect, (unit&0xF0));
- }
}
}
static int i2ob_scan(int bios)
{
int i;
- int unit = 0;
int warned = 0;
- struct i2o_device *d, *b;
+ struct i2o_device *d, *b=NULL;
struct i2o_controller *c;
struct i2ob_device *dev;
bios?"Boot d":"D");
continue;
}
- if(unit<MAX_I2OB<<4)
+ if(scan_unit<MAX_I2OB<<4)
{
/*
* Get the device and fill in the
* Tid and controller.
*/
- dev=&i2ob_dev[unit];
+ dev=&i2ob_dev[scan_unit];
dev->i2odev = d;
dev->controller = c;
dev->unit = c->unit;
dev->tid = d->lct_data.tid;
- if(i2ob_install_device(c,d,unit))
+ if(i2ob_install_device(c,d,scan_unit))
printk(KERN_WARNING "Could not install I2O block device\n");
else
{
- unit+=16;
+ scan_unit+=16;
i2ob_dev_count++;
/* We want to know when device goes away */
i2o_device_notify_on(d, &i2o_block_handler);
else
{
if(!warned++)
- printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", unit>>4);
+ printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit>>4);
}
i2o_release_device(d, &i2o_block_handler);
}
i2o_unlock_controller(c);
}
+ return 0;
}
static void i2ob_probe(void)
#include <linux/version.h>
#endif
+#ifndef LinuxVersionCode
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#endif
#include <linux/types.h>
#include <linux/kdev_t.h>
extern void capi_init(void);
extern void capidrv_init(void);
#endif
+extern void act2000_init(void);
void
isdn_cards_init(void)
*/
#include <linux/ppp_defs.h> /* for PPP_PROTOCOL */
+#include <linux/isdn_ppp.h>
extern int isdn_ppp_read(int, struct file *, char *, int);
extern int isdn_ppp_write(int, struct file *, const char *, int);
extern int isdn_ppp_open(int, struct file *);
static int pmu_has_adb, pmu_has_backlight;
static unsigned char *gpio_reg = NULL;
static int gpio_irq = -1;
+static int irq_flag = 0;
int asleep;
pmu_kind = PMU_KEYLARGO_BASED;
pmu_has_adb = (find_type_devices("adb") != NULL);
- pmu_has_backlight = (find_type_devices("backlight") != NULL);
+ pmu_has_backlight = 0; /* Not driven by PMU */
gpiop = find_devices("gpio");
if (gpiop && gpiop->n_addrs) {
/* Enable backlight */
pmu_enable_backlight(1);
+
+ /* Make sure PMU settle down before continuing */
+ do {
+ pmu_poll();
+ } while (pmu_state != idle);
}
static int __openfirmware
int nloop = 0;
unsigned long flags;
- /* Currently, we use brute-force cli() for syncing with GPIO
- * interrupt. I'll make this smarter later, along with some
- * spinlocks for SMP */
- save_flags(flags);cli();
- ++disable_poll;
- while ((intr = in_8(&via[IFR])) != 0) {
- if (++nloop > 1000) {
- printk(KERN_DEBUG "PMU: stuck in intr loop, "
- "intr=%x pmu_state=%d\n", intr, pmu_state);
- break;
+ /* This is my 2 cents brain dead synchronisation mecanism */
+ if (test_and_set_bit(0, &irq_flag))
+ return;
+
+ while(test_and_clear_bit(0, &irq_flag)) {
+ ++disable_poll;
+ while ((intr = in_8(&via[IFR])) != 0) {
+ if (++nloop > 1000) {
+ printk(KERN_DEBUG "PMU: stuck in intr loop, "
+ "intr=%x pmu_state=%d\n", intr, pmu_state);
+ break;
+ }
+ if (intr & SR_INT)
+ pmu_sr_intr(regs);
+ else if (intr & CB1_INT) {
+ adb_int_pending = 1;
+ out_8(&via[IFR], CB1_INT);
+ }
+ intr &= ~(SR_INT | CB1_INT);
+ if (intr != 0) {
+ out_8(&via[IFR], intr);
+ }
}
- if (intr & SR_INT)
- pmu_sr_intr(regs);
- else if (intr & CB1_INT) {
+ if (gpio_reg && (in_8(gpio_reg + 0x9) & 0x02) == 0)
adb_int_pending = 1;
- out_8(&via[IFR], CB1_INT);
- }
- intr &= ~(SR_INT | CB1_INT);
- if (intr != 0) {
- out_8(&via[IFR], intr);
- }
- }
- if (gpio_reg && (in_8(gpio_reg + 0x9) & 0x02) == 0)
- adb_int_pending = 1;
-
- if (pmu_state == idle) {
- if (adb_int_pending) {
- pmu_state = intack;
- send_byte(PMU_INT_ACK);
- adb_int_pending = 0;
- } else if (current_req) {
- pmu_start();
+
+ /* A spinlock would be nicer ... */
+ save_flags(flags);
+ cli();
+ if (pmu_state == idle) {
+ if (adb_int_pending) {
+ pmu_state = intack;
+ send_byte(PMU_INT_ACK);
+ adb_int_pending = 0;
+ } else if (current_req) {
+ pmu_start();
+ }
}
+ restore_flags(flags);
+ --disable_poll;
}
- --disable_poll;
- restore_flags(flags);
}
+
static void __openfirmware
gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
{
extern int eepro100_probe(struct device *);
extern int el3_probe(struct device *);
extern int at1500_probe(struct device *);
+extern int bond_init(struct device *);
extern int pcnet32_probe(struct device *);
extern int at1700_probe(struct device *);
extern int fmv18x_probe(struct device *);
extern int lance_probe(struct device *dev);
extern int rcpci_probe(struct device *);
extern int dmfe_probe(struct device *);
+extern int sktr_probe(struct device *dev);
/* Gigabit Ethernet adapters */
extern int yellowfin_probe(struct device *dev);
* Copyright 1999, Thomas Davis, tadavis@lbl.gov.
* Licensed under the GPL. Based on dummy.c, and eql.c devices.
*
- * bond.c: a bonding/etherchannel/sun trunking net driver
+ * bonding.c: a bonding/etherchannel/sun trunking net driver
*
* This is useful to talk to a Cisco 5500, running Etherchannel, aka:
* Linux Channel Bonding
typedef card_t port_t;
-#define sca_in(reg, card) readb(card->win0base+C101_SCA+reg)
-#define sca_out(value, reg, card) writeb(value, card->win0base+C101_SCA+reg)
-#define sca_inw(reg, card) readw(card->win0base+C101_SCA+reg)
-#define sca_outw(value, reg, card) writew(value, card->win0base+C101_SCA+reg)
+#define sca_in(reg, card) readb((card)->win0base+C101_SCA+(reg))
+#define sca_out(value, reg, card) writeb(value, (card)->win0base+C101_SCA+(reg))
+#define sca_inw(reg, card) readw((card)->win0base+C101_SCA+(reg))
+#define sca_outw(value, reg, card) writew(value, (card)->win0base+C101_SCA+(reg))
#define port_to_card(port) (port)
#define log_node(port) (0)
#define phy_node(port) (0)
#define winsize(card) (C101_WINDOW_SIZE)
-#define win0base(card) (card->win0base)
-#define winbase(card) (card->win0base+0x2000)
-#define get_port(card, port) (port == 0 ? card : NULL)
+#define win0base(card) ((card)->win0base)
+#define winbase(card) ((card)->win0base+0x2000)
+#define get_port(card, port) ((port) == 0 ? (card) : NULL)
-static __inline__ u8 get_page(card_t *card)
+static __inline__ u8 sca_get_page(card_t *card)
{
return card->page;
}
}
}
+ lp->stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
dev_kfree_skb(skb);
-
} else { /* return unused page to the free memory queue */
outb(page, EWRK3_FMQ);
}
** Update stats
*/
lp->stats.rx_packets++;
+ lp->stats.rx_bytes += pkt_len;
for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) {
if (pkt_len < i * EWRK3_PKT_BIN_SZ) {
lp->pktStats.bins[i]++;
if (power_up) {
out_le32(gm->sysregs + 0x20/4,
in_le32(gm->sysregs + 0x20/4) | 0x02000000);
- udelay(10);
+ udelay(20);
if (gm->pci_devfn != 0xff) {
u16 cmd;
gm->phy_type = 0;
out_le32(gm->sysregs + 0x20/4,
in_le32(gm->sysregs + 0x20/4) & ~0x02000000);
+ udelay(20);
}
}
GM_OUT(GM_RX_CONF,
(RX_OFFSET << GM_RX_CONF_FBYTE_OFF_SHIFT) |
(0x22 << GM_RX_CONF_CHK_START_SHIFT) |
+ (GM_RX_CONF_DMA_THR_DEFAULT << GM_RX_CONF_DMA_THR_SHIFT) |
NRX_CONF);
/* Configure other bits of MAC */
ring = (struct gmac_dma_desc *) gm->txring;
memset(ring, 0, NTX * sizeof(struct gmac_dma_desc));
+ gm->next_rx = 0;
+ gm->next_tx = 0;
+ gm->tx_gone = 0;
+
/* set pointers in chip */
mb();
GM_OUT(GM_RX_DESC_HI, 0);
unsigned long crc;
int multicast_hash = 0;
int multicast_all = 0;
-
+ int promisc = 0;
+
/* Lock out others. */
set_bit(0, (void *) &dev->tbusy);
- gm->promisc = 0;
-
if (dev->flags & IFF_PROMISC)
- gm->promisc = 1;
+ promisc = 1;
else if ((dev->flags & IFF_ALLMULTI) /* || (dev->mc_count > XXX) */) {
multicast_all = 1;
} else {
multicast_hash = 1;
}
- if (gm->promisc)
+ if (promisc)
GM_BIS(GM_MAC_RX_CONFIG, GM_MAC_RX_CONF_RX_ALL);
else
GM_BIC(GM_MAC_RX_CONFIG, GM_MAC_RX_CONF_RX_ALL);
gm->full_duplex = 0;
gm->phy_status = 0;
- gm->promisc = 0;
/* Find a PHY */
if (!mii_lookup_and_reset(gm))
/* Configure the PHY */
mii_setup_phy(gm);
- /* Initialize the MAC */
- gmac_mac_init(gm, dev->dev_addr);
-
/* Initialize the descriptor rings */
gmac_init_rings(gm, 0);
+ /* Initialize the MAC */
+ gmac_mac_init(gm, dev->dev_addr);
+
/* Initialize the multicast tables & promisc mode if any */
gmac_set_multicast(dev);
gmac_tx_timeout(struct device *dev)
{
struct gmac *gm = (struct gmac *) dev->priv;
- int i;
+ int i, timeout;
unsigned long flags;
save_flags(flags);
gm->rx_buff[i] = 0;
}
}
+ /* Perform a software reset */
+ GM_OUT(GM_RESET, GM_RESET_TX | GM_RESET_RX);
+ for (timeout = 100; timeout > 0; --timeout) {
+ mdelay(10);
+ if ((GM_IN(GM_RESET) & (GM_RESET_TX | GM_RESET_RX)) == 0) {
+ /* Mask out all chips interrupts */
+ GM_OUT(GM_IRQ_MASK, 0xffffffff);
+ break;
+ }
+ }
+ if (!timeout)
+ printk(KERN_ERR "%s reset chip failed !\n", dev->name);
/* Create fresh rings */
gmac_init_rings(gm, 1);
+ /* re-initialize the MAC */
+ gmac_mac_init(gm, dev->dev_addr);
+ /* re-initialize the multicast tables & promisc mode if any */
+ gmac_set_multicast(dev);
/* Restart PHY auto-poll */
mii_interrupt(gm);
/* Restart chip */
int i = gm->next_rx;
volatile struct gmac_dma_desc *dp;
struct sk_buff *skb, *new_skb;
- int len, flags, drop;
+ int len, flags, drop, last;
unsigned char *data;
u16 csum;
-
+
+ last = -1;
for (;;) {
dp = &gm->rxring[i];
if (ld_le32(&dp->size) & RX_SZ_OWN)
++gm->stats.rx_packets;
}
+ last = i;
if (++i >= NRX)
i = 0;
}
gm->next_rx = i;
+ if (last >= 0) {
+ mb();
+ GM_OUT(GM_RX_KICK, last & 0xfffffffc);
+ }
}
static void
}
status = GM_IN(GM_IRQ_STATUS);
- GM_OUT(GM_IRQ_ACK, status);
+ if (status & (GM_IRQ_BUS_ERROR | GM_IRQ_MIF))
+ GM_OUT(GM_IRQ_ACK, status & (GM_IRQ_BUS_ERROR | GM_IRQ_MIF));
if (status & (GM_IRQ_RX_TAG_ERR | GM_IRQ_BUS_ERROR)) {
printk(KERN_ERR "%s: IRQ Error status: 0x%08x\n",
#define GM_RX_PTH_UNITS 64
/* -- 0x4100 RW Rx Kick
- * d: 0x00000000 Written by the host with the last tx descriptor number +1 to send
- * Must be a multiple of 4
+ * d: 0x00000000 The last valid RX descriptor is the one right before the value of the
+ * register. Initially set to 0 on reset. RX descriptors must be posted
+ * in multiples of 4. The first descriptor should be cache-line aligned
+ * for best performance.
*/
#define GM_RX_KICK (0x4100 | REG_SZ_16)
/* -- 0x4104 RW Rx Completion
- * d: 0x00000000 Written by the gmac with the last tx descriptor number +1 sent
+ * d: 0x00000000 All descriptors upto but excluding the register value are ready to be
+ * processed by the host.
*/
#define GM_RX_COMP (0x4104 | REG_SZ_16)
*
* Defines the values used for receive interrupt blanking.
* For INTR_TIME field, every count is 2048 PCI clock time. For 66 Mhz, each
- * count is about 16 us.
+ * count is about 15 ns.
*/
#define GM_RX_BLANK (0x4108 | REG_SZ_32)
/*
/* -- 0x4120 RO Rx fifo size
*
- * This 11-bit RO register indicates the size, in 64-bit multiples, of the
+ * This 11-bit RO register indicates the size, in 64-byte multiples, of the
* RX FIFO. Software should use it to properly configure the PAUSE thresholds.
* The value read is 0x140, indicating a 20kbyte RX FIFO.
* -------------------------------------------------------------------------
int phy_type;
int phy_status; /* Cached PHY status */
int full_duplex; /* Current set to full duplex */
- int promisc;
struct net_device_stats stats;
u8 pci_bus;
u8 pci_devfn;
u8 stat;
#ifndef ALL_PAGES_ALWAYS_MAPPED
- u8 page = get_page(card);
+ u8 page = sca_get_page(card);
#endif
while((stat = sca_intr_status(card)) != 0) {
#ifdef DEBUG_RINGS
default:
#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
- page=get_page(card);
+ page=sca_get_page(card);
openwin(card, 0);
#endif
#ifndef MODULE
static int version_printed=0;
#endif
-static const char* version = "HDLC support routines revision: 1.0a1";
+static const char* version = "HDLC support routines revision: 1.0";
#define CISCO_MULTICAST 0x8f /* Cisco multicast address */
skb_push(skb, sizeof(hdlc_header));
data=(hdlc_header*)skb->data;
- data->address = CISCO_MULTICAST;
+ if (type == CISCO_KEEPALIVE)
+ data->address = CISCO_MULTICAST;
+ else
+ data->address = CISCO_UNICAST;
data->control = 0;
data->protocol = htons(type);
switch(mode & ~MODE_SOFT) {
case MODE_CISCO:
- result = hdlc->set_mode ?
- hdlc->set_mode(hdlc, MODE_HDLC) : 0;
- break;
-
case MODE_PPP:
- result = hdlc->set_mode ?
- hdlc->set_mode(hdlc, MODE_PPP) : 0;
- break;
-
- case MODE_X25:
- result = hdlc->set_mode ?
- hdlc->set_mode(hdlc, MODE_X25) : 0;
break;
-
+
case MODE_FR_ANSI:
case MODE_FR_CCITT:
case MODE_FR_ANSI | MODE_DCE:
hdlc_to_dev(hdlc)->addr_len=2;
*(u16*)hdlc_to_dev(hdlc)->dev_addr=htons(LMI_DLCI);
dlci_to_q922(hdlc_to_dev(hdlc)->broadcast, LMI_DLCI);
- result = hdlc->set_mode ?
- hdlc->set_mode(hdlc, MODE_HDLC) : 0;
break;
default:
return -EINVAL;
}
+
+ result = hdlc->set_mode ?
+ hdlc->set_mode(hdlc, MODE_HDLC) : 0;
}
if (result)
-#define sca_reg(reg, card) (0x8000 | card->io | \
+#define sca_reg(reg, card) (0x8000 | (card)->io | \
((reg)&0x0F) | (((reg)&0xF0) << 6))
#define sca_in(reg, card) readb(sca_reg(reg, card))
#define sca_out(value, reg, card) writeb(value, sca_reg(reg, card))
#define sca_inw(reg, card) readw(sca_reg(reg, card))
#define sca_outw(value, reg, card) writew(value, sca_reg(reg, card))
-#define port_to_card(port) (port->card)
-#define log_node(port) (port->log_node)
-#define phy_node(port) (port->phy_node)
+#define port_to_card(port) ((port)->card)
+#define log_node(port) ((port)->log_node)
+#define phy_node(port) ((port)->phy_node)
#define winsize(card) (USE_WINDOWSIZE)
-#define winbase(card) (card->winbase)
-#define get_port(card, port) (card->ports[port].valid ? \
- &card->ports[port] : NULL)
+#define winbase(card) ((card)->winbase)
+#define get_port(card, port) ((card)->ports[port].valid ? \
+ &(card)->ports[port] : NULL)
-static __inline__ u8 get_page(card_t *card)
+static __inline__ u8 sca_get_page(card_t *card)
{
return inb(card->io+N2_PSR) & PSR_PAGEBITS;
}
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <net/slhc_vj.h>
#ifdef CONFIG_INET
/* Entire module is for IP only */
#include <asm/uaccess.h>
#include <linux/mm.h>
#include <net/checksum.h>
-#include <net/slhc_vj.h>
#include <asm/unaligned.h>
int last_retran;
#include <linux/tasks.h>
#include <linux/parport.h>
+#include <linux/parport_pc.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
Written By: Adam Radford <linux@3ware.com>
+ Modifications By: Joel Jacobson <linux@3ware.com>
+
Copyright (C) 1999-2000 3ware Inc.
Kernel compatablity By: Andre Hedrick <andre@suse.com>
For more information, goto:
http://www.3ware.com
+
+ History
+ -------
+ 0.1.000 - Initial release.
+ 0.4.000 - Added support for Asynchronous Event Notification through
+ ioctls for 3DM.
+ 1.0.000 - Added DPO & FUA bit support for WRITE_10 & WRITE_6 cdb
+ to disable drive write-cache before writes.
+ 1.1.000 - Fixed performance bug with DPO & FUA not existing for WRITE_6.
+ 1.2.000 - Added support for clean shutdown notification/feature table.
+ 1.02.00.001 - Added support for full command packet posts through ioctls
+ for 3DM.
+ Bug fix so hot spare drives don't show up.
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/smp.h>
+#include <linux/reboot.h>
#include <asm/spinlock.h>
#include <asm/errno.h>
static int tw_copy_info(TW_Info *info, char *fmt, ...);
static void tw_copy_mem_info(TW_Info *info, char *data, int len);
static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int tw_halt(struct notifier_block *nb, ulong event, void *buf);
+
+/* Notifier block to get a notify on system shutdown/halt/reboot */
+static struct notifier_block tw_notifier = {
+ tw_halt, NULL, 0
+};
struct proc_dir_entry tw_scsi_proc_entry = {
PROC_SCSI_3W_XXXX,
};
/* Globals */
-char *tw_driver_version="1.1.000";
+char *tw_driver_version="1.02.00.001";
TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
int tw_device_extension_count = 0;
if (command_packet->status != 0) {
if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
/* Bad response */
- printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, flags = 0x%x.\n", command_packet->flags);
+ printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
return 1;
} else {
/* We know this is a 3w-1x00, and doesn't support aen's */
TW_Device_Extension *tw_dev2;
struct pci_dev *tw_pci_dev = pci_devices;
u32 status_reg_value;
+ unsigned char c = 1;
dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n");
while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, TW_DEVICE_ID, tw_pci_dev))) {
continue;
}
- error = tw_initconnection(tw_dev);
+ error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
if (error) {
printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initconnection for card %d.\n", numcards);
release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE);
/* Free the temporary device extension */
if (tw_dev)
kfree(tw_dev);
+ /* Tell the firmware we support shutdown notification*/
+ tw_setfeature(tw_dev, 2, 1, &c);
}
if (numcards == 0)
printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n");
+ else
+ register_reboot_notifier(&tw_notifier);
return numcards;
} /* End tw_findcards() */
}
} /* End tw_free_device_extension() */
+/* Clean shutdown routine */
+static int tw_halt(struct notifier_block *nb, ulong event, void *buf)
+{
+ int i;
+
+ for (i=0;i<tw_device_extension_count;i++) {
+ printk(KERN_NOTICE "3w-xxxx: Notifying card #%d\n", i);
+ tw_shutdown_device(tw_device_extension_list[i]);
+ }
+ unregister_reboot_notifier(&tw_notifier);
+
+ return NOTIFY_OK;
+} /* End tw_halt() */
+
/* This function will send an initconnection command to controller */
-int tw_initconnection(TW_Device_Extension *tw_dev)
+int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
{
u32 command_que_addr, command_que_value;
u32 status_reg_addr, status_reg_value;
command_packet->byte3.host_id = 0x0;
command_packet->status = 0x0;
command_packet->flags = 0x0;
- command_packet->byte6.message_credits = TW_INIT_MESSAGE_CREDITS;
+ command_packet->byte6.message_credits = message_credits;
command_packet->byte8.init_connection.response_queue_pointer = 0x0;
command_que_value = tw_dev->command_packet_physical_address[request_id];
}
if (command_packet->status != 0) {
/* bad response */
- printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, flags = 0x%x.\n", command_packet->flags);
+ printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
return 1;
}
break; /* Response was okay, so we exit */
}
if (command_packet->status != 0) {
/* bad response */
- printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, flags = 0x%x.\n", command_packet->flags);
+ printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
return 1;
}
found = 1;
if (is_unit_present[i] == 0) {
tw_dev->is_unit_present[i] = FALSE;
} else {
+ if (is_unit_present[i] & TW_UNIT_ONLINE) {
dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): Unit %d found.\n", i);
tw_dev->is_unit_present[i] = TRUE;
num_units++;
+ }
}
}
tw_dev->num_units = num_units;
request_id = response_que.u.response_id;
command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
if (command_packet->status != 0) {
- printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, flags = 0x%x.\n", command_packet->flags);
+ printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
}
if (tw_dev->state[request_id] != TW_S_POSTED) {
printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode);
/* Initialize command packet */
command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
if (command_packet == NULL) {
- printk(KERN_WARNING "3w-xxxx: twioctl(): Bad command packet virtual address.\n");
+ printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad command packet virtual address.\n");
tw_dev->state[request_id] = TW_S_COMPLETED;
tw_state_request_finish(tw_dev, request_id);
tw_dev->srb[request_id]->result = (DID_OK << 16);
tw_dev->srb[request_id]->result = (DID_OK << 16);
tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
return 0;
+ case TW_CMD_PACKET:
+ memcpy(command_packet, ioctl->data, sizeof(TW_Command));
+ command_packet->request_id = request_id;
+ tw_post_command_packet(tw_dev, request_id);
+
+ return 0;
default:
printk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);
tw_dev->state[request_id] = TW_S_COMPLETED;
return 1;
}
- error = tw_initconnection(tw_dev);
+ error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
if (error) {
printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
return 1;
/* Tell kernel scsi-layer we are gone */
scsi_unregister(tw_host);
+ /* Fake like we just shut down, so notify the card that
+ * we "shut down cleanly".
+ */
+ tw_halt(0, 0, 0); // parameters aren't actually used
+
return 0;
} /* End tw_scsi_release() */
if (is_unit_present[i] == 0) {
tw_dev->is_unit_present[i] = FALSE;
} else {
+ if (is_unit_present[i] & TW_UNIT_ONLINE) {
tw_dev->is_unit_present[i] = TRUE;
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete: Unit %d found.\n", i);
+ }
}
}
return 0;
} /* End tw_scsiop_test_unit_ready() */
+/* Set a value in the features table */
+int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
+ unsigned char *val)
+{
+ TW_Param *param;
+ TW_Command *command_packet;
+ TW_Response_Queue response_queue;
+ int request_id = 0;
+ u32 command_que_value, command_que_addr;
+ u32 status_reg_addr, status_reg_value;
+ u32 response_que_addr;
+ u32 param_value;
+ int imax, i;
+
+ /* Initialize SetParam command packet */
+ if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
+ printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet virtual address.\n");
+ return 1;
+ }
+ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+ memset(command_packet, 0, sizeof(TW_Sector));
+ param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+
+ command_packet->byte0.opcode = TW_OP_SET_PARAM;
+ command_packet->byte0.sgl_offset = 2;
+ param->table_id = 0x404; /* Features table */
+ param->parameter_id = parm;
+ param->parameter_size_bytes = param_size;
+ memcpy(param->data, val, param_size);
+
+ param_value = tw_dev->alignment_physical_address[request_id];
+ if (param_value == 0) {
+ printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ tw_state_request_finish(tw_dev, request_id);
+ tw_dev->srb[request_id]->result = (DID_OK << 16);
+ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+ }
+ command_packet->byte8.param.sgl[0].address = param_value;
+ command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
+
+ command_packet->size = 4;
+ command_packet->request_id = request_id;
+ command_packet->byte6.parameter_count = 1;
+
+ command_que_value = tw_dev->command_packet_physical_address[request_id];
+ if (command_que_value == 0) {
+ printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet physical address.\n");
+ return 1;
+ }
+ command_que_addr = tw_dev->registers.command_que_addr;
+ status_reg_addr = tw_dev->registers.status_reg_addr;
+ response_que_addr = tw_dev->registers.response_que_addr;
+
+ /* Send command packet to the board */
+ outl(command_que_value, command_que_addr);
+
+ /* Poll for completion */
+ imax = TW_POLL_MAX_RETRIES;
+ for (i=0;i<imax;i++) {
+ mdelay(10);
+ status_reg_value = inl(status_reg_addr);
+ if (tw_check_bits(status_reg_value)) {
+ printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
+ return 1;
+ }
+ if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+ response_queue.value = inl(response_que_addr);
+ request_id = (unsigned char)response_queue.u.response_id;
+ if (request_id != 0) {
+ /* unexpected request id */
+ printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected request id.\n");
+ return 1;
+ }
+ if (command_packet->status != 0) {
+ /* bad response */
+ printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+ return 1;
+ }
+ break; /* Response was okay, so we exit */
+ }
+ }
+
+ return 0;
+} /* End tw_setfeature() */
+
/* This function will setup the interrupt handler */
int tw_setup_irq(TW_Device_Extension *tw_dev)
{
return 0;
} /* End tw_setup_irq() */
+/* This function will tell the controller we're shutting down by sending
+ initconnection with a 1 */
+int tw_shutdown_device(TW_Device_Extension *tw_dev)
+{
+ int error;
+
+ /* Disable interrupts */
+ tw_disable_interrupts(tw_dev);
+
+ /* poke the board */
+ error = tw_initconnection(tw_dev, 1);
+ if (error) {
+ printk(KERN_WARNING "3w-xxxx: tw_shutdown_device(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+ } else {
+ printk(KERN_NOTICE "3w-xxxx shutdown succeeded\n");
+ }
+
+ /* Re-enable interrupts */
+ tw_enable_interrupts(tw_dev);
+
+ return 0;
+} /* End tw_shutdown_device() */
+
/* This function will soft reset the controller */
void tw_soft_reset(TW_Device_Extension *tw_dev)
{
3w-xxxx.h -- 3ware Storage Controller device driver for Linux.
Written By: Adam Radford <linux@3ware.com>
- Copyright (C) 1999 3ware Inc.
+ Modifications By: Joel Jacobson <linux@3ware.com>
+
+ Copyright (C) 1999, 2000 3ware Inc.
Kernel compatablity By: Andre Hedrick <andre@suse.com>
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
#define TW_OP_SET_PARAM 0x13
#define TW_OP_SECTOR_INFO 0x1a
#define TW_OP_AEN_LISTEN 0x1c
+#define TW_CMD_PACKET 0x1d
/* Asynchronous Event Notification (AEN) Codes */
#define TW_AEN_QUEUE_EMPTY 0x0000
#define TW_BLOCK_SIZE 0x200 /* 512-byte blocks */
#define TW_IOCTL 0x80
#define TW_MAX_AEN_TRIES 100
-
+#define TW_UNIT_ONLINE 1
#define TW_IN_INTR 1
/* Macros */
void tw_enable_interrupts(TW_Device_Extension *tw_dev);
int tw_findcards(Scsi_Host_Template *tw_host);
void tw_free_device_extension(TW_Device_Extension *tw_dev);
-int tw_initconnection(TW_Device_Extension *tw_dev);
+int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits);
int tw_initialize_device_extension(TW_Device_Extension *tw_dev);
int tw_initialize_units(TW_Device_Extension *tw_dev);
int tw_ioctl(TW_Device_Extension *tw_dev, int request_id);
int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id);
int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id);
int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id);
+int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, unsigned char *val);
int tw_setup_irq(TW_Device_Extension *tw_dev);
+int tw_shutdown_device(TW_Device_Extension *tw_dev);
void tw_soft_reset(TW_Device_Extension *tw_dev);
int tw_state_request_finish(TW_Device_Extension *tw_dev,int request_id);
int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id);
eh_strategy_handler : NULL, \
eh_abort_handler : tw_scsi_eh_abort, \
eh_device_reset_handler : NULL, \
+ eh_bus_reset_handler : NULL, \
+ eh_host_reset_handler : tw_scsi_eh_reset, \
abort : NULL, \
reset : NULL, \
slave_attach : NULL, \
if (info.sign != EATA_SIGNATURE) return FALSE;
if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
- printk("%s: config structure size (%ld bytes) too short, detaching.\n",
+ printk("%s: config structure size (%d bytes) too short, detaching.\n",
name, DEV2H(info.data_len));
return FALSE;
}
typedef struct {
struct pardevice *dev; /* Parport device entry */
int base; /* Actual port address */
+ int base_hi; /* Hi Base address for ECP-ISA chipset */
int mode; /* Transfer mode */
int host; /* Host number (for proc) */
Scsi_Cmnd *cur_cmd; /* Current queued command */
#define IMM_EMPTY \
{ dev: NULL, \
base: -1, \
+ base_hi: 0, \
mode: IMM_AUTODETECT, \
host: -1, \
cur_cmd: NULL, \
{IMM_EMPTY, IMM_EMPTY, IMM_EMPTY, IMM_EMPTY};
#define IMM_BASE(x) imm_hosts[(x)].base
+#define IMM_BASE_HI(x) imm_hosts[(x)].base_hi
int parbus_base[NO_HOSTS] =
{0x03bc, 0x0378, 0x0278, 0x0000};
}
retry_entry:
for (i = 0; pb; i++, pb = pb->next) {
- int modes, ppb;
+ int modes, ppb, ppb_hi;
imm_hosts[i].dev =
parport_register_device(pb, "imm", NULL, imm_wakeup,
}
}
ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
+ ppb_hi = IMM_BASE_HI(i) = imm_hosts[i].dev->port->base_hi;
w_ctr(ppb, 0x0c);
modes = imm_hosts[i].dev->port->modes;
if (modes & PARPORT_MODE_PCPS2)
imm_hosts[i].mode = IMM_PS2;
- if (modes & PARPORT_MODE_PCECPPS2) {
- w_ecr(ppb, 0x20);
+ if (ppb_hi && modes & PARPORT_MODE_PCECPPS2) {
+ w_ecr(ppb_hi, 0x20);
imm_hosts[i].mode = IMM_PS2;
}
- if (modes & PARPORT_MODE_PCECPEPP)
- w_ecr(ppb, 0x80);
+ if (ppb_hi && modes & PARPORT_MODE_PCECPEPP)
+ w_ecr(ppb_hi, 0x80);
/* Done configuration */
imm_pb_release(i);
return a;
}
+/*
+ * Clear EPP timeout bit.
+ */
static inline void epp_reset(unsigned short ppb)
{
int i;
w_str(ppb, i & 0xfe);
}
-static inline void ecp_sync(unsigned short ppb)
+/*
+ * Wait for empty ECP fifo (if we are in ECP fifo mode only)
+ */
+static inline void ecp_sync(unsigned short hostno)
{
- int i;
+ int i, ppb_hi=IMM_BASE_HI(hostno);
- if ((r_ecr(ppb) & 0xe0) != 0x80)
- return;
+ if (ppb_hi == 0) return;
- for (i = 0; i < 100; i++) {
- if (r_ecr(ppb) & 0x01)
- return;
- udelay(5);
+ if ((r_ecr(ppb_hi) & 0xe0) == 0x60) { /* mode 011 == ECP fifo mode */
+ for (i = 0; i < 100; i++) {
+ if (r_ecr(ppb_hi) & 0x01)
+ return;
+ udelay(5);
+ }
+ printk("imm: ECP sync failed as data still present in FIFO.\n");
}
- printk("imm: ECP sync failed as data still present in FIFO.\n");
}
static int imm_byte_out(unsigned short base, const char *buffer, int len)
w_ctr(ppb, 0xc);
r = !(r_str(ppb) & 0x01);
w_ctr(ppb, 0xc);
- ecp_sync(ppb);
+ ecp_sync(host_no);
break;
case IMM_NIBBLE:
w_ctr(ppb, 0x2c);
r = !(r_str(ppb) & 0x01);
w_ctr(ppb, 0x2c);
- ecp_sync(ppb);
+ ecp_sync(host_no);
break;
default:
return 1;
}
imm_disconnect(host_no);
- printk("imm: Communication established with ID %i using %s\n", loop,
+ printk("imm: Communication established at 0x%x with ID %i using %s\n", ppb, loop,
IMM_MODE_STRING[imm_hosts[host_no].mode]);
imm_connect(host_no, CONNECT_EPP_MAYBE);
imm_reset_pulse(IMM_BASE(host_no));
#define r_str(x) (unsigned char)inb((x)+1)
#define r_ctr(x) (unsigned char)inb((x)+2)
#define r_epp(x) (unsigned char)inb((x)+4)
-#define r_fifo(x) (unsigned char)inb((x)+0x400)
-#define r_ecr(x) (unsigned char)inb((x)+0x402)
+#define r_fifo(x) (unsigned char)inb((x)) /* x must be base_hi */
+ /* On PCI is: base+0x400 != base_hi */
+#define r_ecr(x) (unsigned char)inb((x)+2) /* x must be base_hi */
#define w_dtr(x,y) outb(y, (x))
#define w_str(x,y) outb(y, (x)+1)
#define w_epp(x,y) outb(y, (x)+4)
-#define w_fifo(x,y) outb(y, (x)+0x400)
-#define w_ecr(x,y) outb(y, (x)+0x402)
+#define w_fifo(x,y) outb(y, (x)) /* x must be base_hi */
+#define w_ecr(x,y) outb(y, (x)+0x2) /* x must be base_hi */
#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
#define w_ctr(x,y) outb_p(y, (x)+2)
#endif
+#ifndef VIRT_TO_BUS
#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i))
+#endif
#define ULONG unsigned long
#define USHORT unsigned short
#define UCHAR unsigned char
#endif
#endif
+#ifndef VIRT_TO_BUS
#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i))
+#endif
#define ULONG unsigned long
#define PVOID void *
#define USHORT unsigned short
}
retry_entry:
for (i = 0; pb; i++, pb = pb->next) {
- int modes, ppb;
+ int modes, ppb, ppb_hi;
ppa_hosts[i].dev =
parport_register_device(pb, "ppa", NULL, ppa_wakeup,
}
}
ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base;
+ ppb_hi = ppa_hosts[i].dev->port->base_hi;
w_ctr(ppb, 0x0c);
modes = ppa_hosts[i].dev->port->modes;
ppa_hosts[i].mode = PPA_PS2;
if (modes & PARPORT_MODE_PCECPPS2) {
- w_ecr(ppb, 0x20);
+ w_ecr(ppb_hi, 0x20);
ppa_hosts[i].mode = PPA_PS2;
}
if (modes & PARPORT_MODE_PCECPEPP)
- w_ecr(ppb, 0x80);
+ w_ecr(ppb_hi, 0x80);
/* Done configuration */
ppa_pb_release(i);
}
/*
- * output a string, in whatever mode is available, according to the
- * PPA protocol.
+ * Clear EPP Timeout Bit
*/
static inline void epp_reset(unsigned short ppb)
{
w_str(ppb, i & 0xfe);
}
-static inline void ecp_sync(unsigned short ppb)
+/*
+ * Wait for empty ECP fifo (if we are in ECP fifo mode only)
+ */
+static inline void ecp_sync(unsigned short hostno)
{
- int i;
+ int i, ppb_hi=ppa_hosts[hostno].dev->port->base_hi;
- if ((r_ecr(ppb) & 0xe0) != 0x80)
- return;
+ if (ppb_hi == 0) return;
- for (i = 0; i < 100; i++) {
- if (r_ecr(ppb) & 0x01)
- return;
- udelay(5);
+ if ((r_ecr(ppb_hi) & 0xe0) == 0x60) { /* mode 011 == ECP fifo mode */
+ for (i = 0; i < 100; i++) {
+ if (r_ecr(ppb_hi) & 0x01)
+ return;
+ udelay(5);
+ }
+ printk("ppa: ECP sync failed as data still present in FIFO.\n");
}
- printk("ppa: ECP sync failed as data still present in FIFO.\n");
}
static int ppa_byte_out(unsigned short base, const char *buffer, int len)
w_ctr(ppb, 0xc);
r = !(r_str(ppb) & 0x01);
w_ctr(ppb, 0xc);
- ecp_sync(ppb);
+ ecp_sync(host_no);
break;
default:
w_ctr(ppb, 0x2c);
r = !(r_str(ppb) & 0x01);
w_ctr(ppb, 0x2c);
- ecp_sync(ppb);
+ ecp_sync(host_no);
break;
default:
#define r_str(x) (unsigned char)inb((x)+1)
#define r_ctr(x) (unsigned char)inb((x)+2)
#define r_epp(x) (unsigned char)inb((x)+4)
-#define r_fifo(x) (unsigned char)inb((x)+0x400)
-#define r_ecr(x) (unsigned char)inb((x)+0x402)
+#define r_fifo(x) (unsigned char)inb((x)) /* x must be base_hi */
+ /* On PCI is base+0x400 != base_hi */
+#define r_ecr(x) (unsigned char)inb((x)+0x2) /* x must be base_hi */
#define w_dtr(x,y) outb(y, (x))
#define w_str(x,y) outb(y, (x)+1)
#define w_epp(x,y) outb(y, (x)+4)
-#define w_fifo(x,y) outb(y, (x)+0x400)
-#define w_ecr(x,y) outb(y, (x)+0x402)
+#define w_fifo(x,y) outb(y, (x)) /* x must be base_hi */
+#define w_ecr(x,y) outb(y, (x)+0x2)/* x must be base_hi */
#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
#define w_ctr(x,y) outb_p(y, (x)+2)
return ioctl_probe(dev->host, arg);
case SCSI_IOCTL_SEND_COMMAND:
if(!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if(!capable(CAP_SYS_RAWIO)) return -EACCES;
return scsi_ioctl_send_command((Scsi_Device *) dev,
(Scsi_Ioctl_Command *) arg);
case SCSI_IOCTL_DOORLOCK:
#include "constants.h"
#include "sd.h"
#include <linux/stat.h>
+#include <scsi/scsicam.h>
#include "dc390.h"
obj-$(CONFIG_SOUND_GUS) += gus.o ad1848.o
obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb.o uart401.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx.o sb.o uart401.o
-obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb.o uart401.o ac97.o
+obj-$(CONFIG_SOUND_YMPCI) += ymfsb.o sb.o uart401.o ac97.o
obj-$(CONFIG_SOUND_MAUI) += maui.o mpu401.o
obj-$(CONFIG_SOUND_MPU401) += mpu401.o
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
# Declare multi-part drivers.
list-multi := sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
- soundcore.o wavefront.o nm256.o via82cxxx.o \
+ soundcore.o wavefront.o nm256.o ymfsb.o via82cxxx.o \
sound-objs := \
dev_table.o soundcard.o sound_syms.o \
vidc_mod-objs := vidc.o vidc_audio.o vidc_fill.o vidc_mixer.o vidc_synth.o
wavefront-objs := wavfront.o wf_midi.o yss225.o
nm256-objs := nm256_audio.o ac97.o
-via82cxxx-objs := via82cxxx_audio.o ac97.o
+via82cxxx-objs := via82cxxx_audio.o ac97.o
+ymfsb-objs := ymf_sb.o ac97.o
# Extract lists of the multi-part drivers.
via82cxxx.o: $(via82cxxx-objs)
$(LD) -r -o $@ $(via82cxxx-objs)
+ymfsb.o: $(ymfsb-objs)
+ $(LD) -r -o $@ $(ymfsb-objs)
+
# Firmware files that need translation
#
# The translated files are protected by a file that keeps track
module_init(emu10k1_init_module);
module_exit(emu10k1_cleanup_module);
+
+#ifndef MODULE
+int __init init_emu10k1(void)
+{
+ return emu10k1_init_module();
+}
+#endif
outl(virt_to_bus(&dmabuf->channel->sg[0]), state->card->iobase+dmabuf->channel->port+OFF_BDBAR);
outb(16, state->card->iobase+dmabuf->channel->port+OFF_LVI);
outb(0, state->card->iobase+dmabuf->channel->port+OFF_CIV);
+
+ resync_dma_ptrs(state);
+
if (rec) {
i810_rec_setup(state);
} else {
dmabuf->ossfragshift = 0;
dmabuf->ossmaxfrags = 0;
dmabuf->subdivision = 0;
- i810_set_dac_rate(state, 48000);
+ i810_set_dac_rate(state, 8000);
}
if (file->f_mode & FMODE_READ) {
dmabuf->ossfragshift = 0;
dmabuf->ossmaxfrags = 0;
dmabuf->subdivision = 0;
- i810_set_adc_rate(state, 48000);
+ i810_set_adc_rate(state, 8000);
}
state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
return 0;
}
+ udelay(500);
+
inw(card->ac97base);
for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
#ifdef MODULE
int init_module(void)
#else
-int SILLY_MAKE_INIT(init_maestro(void))
+SILLY_MAKE_INIT(int init_maestro(void))
#endif
{
struct pci_dev *pcidev = NULL;
#ifdef CONFIG_SOUND_FUSION
extern int cs_probe(void);
#endif
+#ifdef CONFIG_SOUND_EMU10K1
+extern int init_emu10k1(void);
+#endif
/*
* Low level list operator. Scan the ordered list, find a hole and
#endif
#ifdef CONFIG_SOUND_FUSION
cs_probe();
+#endif
+#ifdef CONFIG_SOUND_EMU10K1
+ init_emu10k1();
#endif
return 0;
}
*
* Steve Beynon : Missing last directory entries fixed
* (stephen@askone.demon.co.uk) : 21st June 1996
+ *
+ * Go Taniguchi : Move sector and boundarie error fixed
+ * (go@turbolinux.co.jp) : Jul 21 2000
*
* isofs directory handling functions
*/
de = (struct iso_directory_record *) (bh->b_data + offset);
if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
- de_len = *(unsigned char *) de;
+ /* Check boundaries and get length. by GO! */
+ if (offset < bufsize) de_len = *(unsigned char *) de;
#ifdef DEBUG
- printk("de_len = %ld\n", de_len);
+ if (offset < bufsize) printk("de_len = %ld\n", de_len);
+ else printk("Move to next sector\n");
#endif
CDROM sector. If we are at the end of the directory, we
kick out of the while loop. */
- if ((de_len == 0) || (offset >= bufsize) ) {
+ if ((offset >= bufsize) || (de_len == 0) ) {
brelse(bh);
- if (de_len == 0) {
+ if (offset >= bufsize) { /*Check first. by GO!*/
+ offset -= bufsize;
+ filp->f_pos += offset;
+ } else {
filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+ ISOFS_BLOCK_SIZE);
offset = 0;
- } else {
- offset -= bufsize;
- filp->f_pos += offset;
}
if (filp->f_pos >= inode->i_size)
* If we are beyond the end of this file, don't give out any
* blocks.
*/
- if( b_off > inode->i_size )
+ if( b_off >= inode->i_size )
{
off_t max_legal_read_offset;
nc[0] = toupperif(*np, case_trans);
nc[1] = 0x00;
nls_in->char2uni(nc, &len, &uc.uni2, &uc.uni1);
- nls_out->uni2char(0x00, uc.uni2, np, 1, &len);
+ nls_out->uni2char(uc.uni1, uc.uni2, np, 1, &len);
np++;
}
}
nc[0] = *np;
nc[1] = 0;
nls_in->char2uni(nc, &len, &uc.uni2, &uc.uni1);
- nls_out->uni2char(0x00, uc.uni2, nc, 1, &len);
+ nls_out->uni2char(uc.uni1, uc.uni2, nc, 1, &len);
*np = tolowerif(nc[0], case_trans);
np++;
}
--- /dev/null
+ChangeLog for smbfs.
+
+2000-07-20 Urban Widmark <urban@svenskatest.se>
+
+ * proc.c: fix 2 places where bad server responses could cause an Oops.
+
+2000-07-15 Urban Widmark <urban@svenskatest.se>
+
+ * *.c: more debug printk fixes
+
+2000-06-24: Matt Maynard <matthewm@corel.com>
+
+ * dir.c: dentry->d_inode->i_mtime isn't updated for all servers
+ (NT?) and all operations (mv oldfile.txt newfile.txt) Removed for
+ less efficient but better working directory cache.
+ * proc.c: included aDIR smbclient fix for renaming directories on
+ OS/2 servers (win95/98?) (orig by John Janosik)
+
+2000-07-01 Urban Widmark <urban@svenskatest.se>
+
+ * *.c: replace ugly #ifdef's with less ugly debug macros.
+
+2000-03-?? Andrew Tridgell
+
+ * proc.c: removed support for old protocol levels. It didn't work
+ anyway and was cluttering things up a lot.
+
+2000-01-?? cpg@aladdin.de
+
+ * proc.c: added posix semantics for unlink
+
+1999-11-16 Andrew Tridgell
+
+ * proc.c: use level 260 for most conns, or level 1 for <NT1
+ * proc.c: don't sleep every time with win95 on a FINDNEXT
+ * proc.c: fixed loop_count bug
+ * proc.c: got rid of resume_key
+
+[there are a few missing here :) ]
+
+1997-09-28 Riccardo Facchetti
+
+ * proc.c: Fixed smb_d_path [now smb_build_path()] to be non-recursive
+
+1996-06-28 Yuri Per
+
+ * proc.c: Fixed long file name support (smb_proc_readdir_long)
+
+You are in the wrong end for adding new entries. New entries at the top.
* Routines to support directory cacheing using the page cache.
* Right now this only works for smbfs, but will be generalized
* for use with other filesystems.
+ *
+ * Please add a note about your changes to smbfs in the ChangeLog file.
*/
#include <linux/sched.h>
#include <asm/page.h>
-#define SMBFS_PARANOIA 1
-/* #define SMBFS_DEBUG_VERBOSE 1 */
-
#include "smb_debug.h"
struct inode * inode = dentry->d_inode;
struct cache_head * cachep;
- VERBOSE("smb_get_dircache: finding cache for %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ VERBOSE("finding cache for %s/%s\n", DENTRY_PATH(dentry));
cachep = (struct cache_head *) get_cached_page(inode, 0, 1);
if (!cachep)
goto out;
for (i = 0; i < cachep->pages; i++, index++) {
#ifdef SMBFS_PARANOIA
if (index->block)
- PARANOIA("smb_get_dircache: cache %s/%s has existing block!\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ PARANOIA("cache %s/%s has existing block!\n",
+ DENTRY_PATH(dentry));
#endif
offset = PAGE_SIZE + (i << PAGE_SHIFT);
block = (struct cache_block *) get_cached_page(inode,
struct cache_index * index = cachep->index;
int i;
- VERBOSE("smb_free_cache_blocks: freeing %d blocks\n", cachep->pages);
+ VERBOSE("freeing %d blocks\n", cachep->pages);
for (i = 0; i < cachep->pages; i++, index++)
{
if (index->block)
void
smb_free_dircache(struct cache_head * cachep)
{
- VERBOSE("smb_free_dircache: freeing cache\n");
+ VERBOSE("freeing cache\n");
smb_free_cache_blocks(cachep);
put_cached_page((unsigned long) cachep);
}
void
smb_init_dircache(struct cache_head * cachep)
{
- VERBOSE("smb_init_dircache: initializing cache, %d blocks\n",
- cachep->pages);
+ VERBOSE("initializing cache, %d blocks\n", cachep->pages);
smb_free_cache_blocks(cachep);
memset(cachep, 0, sizeof(struct cache_head));
}
unsigned int nent, offset, len = entry->len;
unsigned int needed = len + sizeof(struct cache_entry);
- VERBOSE("smb_add_to_cache: cache inode %p, status %d, adding %s at %ld\n",
- inode, cachep->status, entry->name, fpos);
+ VERBOSE("cache inode %p, status %d, adding %.*s at %ld\n",
+ inode, cachep->status, entry->len, entry->name, fpos);
/*
* Don't do anything if we've had an error ...
*/
block->cb_data.table[nent].offset = offset;
block->cb_data.table[nent].ino = entry->ino;
cachep->entries++;
- VERBOSE("smb_add_to_cache: added entry %s, len=%d, pos=%ld, entries=%d\n",
- entry->name, len, fpos, cachep->entries);
+ VERBOSE("added entry %.*s, len=%d, pos=%ld, entries=%d\n",
+ entry->len, entry->name, len, fpos, cachep->entries);
return;
}
/*
index++;
#ifdef SMBFS_PARANOIA
if (index->block)
- PARANOIA("smb_add_to_cache: new index already has block!\n");
+ PARANOIA("new index already has block!\n");
#endif
/*
{
index->block = block;
index->space = PAGE_SIZE;
- VERBOSE("smb_add_to_cache: inode=%p, pages=%d, block at %ld\n",
+ VERBOSE("inode=%p, pages=%d, block at %ld\n",
inode, cachep->pages, page_off);
goto add_entry;
}
unsigned int i, nent, offset = 0;
off_t next_pos = 2;
- VERBOSE("smb_find_in_cache: cache %p, looking for pos=%ld\n",
- cachep, pos);
+ VERBOSE("cache %p, looking for pos=%ld\n", cachep, pos);
for (i = 0; i < cachep->pages; i++, index++)
{
if (pos < next_pos)
entry->len = block->cb_data.table[nent].namelen;
offset = block->cb_data.table[nent].offset;
entry->name = &block->cb_data.names[offset];
- VERBOSE("smb_find_in_cache: found %s, len=%d, pos=%ld\n",
- entry->name, entry->len, pos);
+ VERBOSE("found %.*s, len=%d, pos=%ld\n",
+ entry->len, entry->name, entry->len, pos);
break;
}
return offset;
struct inode * inode = dentry->d_inode;
int result;
- VERBOSE("smb_refill_dircache: cache %s/%s, blocks=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- cachep->pages);
+ VERBOSE("cache %s/%s, blocks=%d\n", DENTRY_PATH(dentry), cachep->pages);
/*
* Fill the cache, starting at position 2.
*/
result = smb_proc_readdir(dentry, 2, cachep);
if (result < 0)
{
- PARANOIA("smb_refill_dircache: readdir failed, result=%d\n",
- result);
+ PARANOIA("readdir failed, result=%d\n", result);
goto out;
}
*/
if (!(inode->u.smbfs_i.cache_valid & SMB_F_CACHEVALID))
{
- PARANOIA("smb_refill_dircache: cache invalidated, retrying\n");
+ PARANOIA("cache invalidated, retrying\n");
goto retry;
}
cachep->valid = 1;
cachep->mtime = dentry->d_inode->i_mtime;
}
- VERBOSE("smb_refill_cache: cache %s/%s status=%d, entries=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- cachep->status, cachep->entries);
+ VERBOSE("cache %s/%s status=%d, entries=%d\n",
+ DENTRY_PATH(dentry), cachep->status, cachep->entries);
out:
return result;
* Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
* Copyright (C) 1997 by Volker Lendecke
*
+ * Please add a note about your changes to smbfs in the ChangeLog file.
*/
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/ctype.h>
#include <linux/smb_fs.h>
#include <linux/smbno.h>
-#define SMBFS_PARANOIA 1
-/* #define SMBFS_DEBUG_VERBOSE 1 */
-
#include "smb_debug.h"
#define SMBFS_MAX_AGE 5*HZ
struct cache_head *cachep = NULL;
int result;
- VERBOSE("smb_readdir: reading %s/%s, f_pos=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ VERBOSE("reading %s/%s, f_pos=%d\n", DENTRY_PATH(dentry),
(int) filp->f_pos);
result = 0;
goto out;
/*
* Make sure the cache is up-to-date.
+ *
+ * To detect changes on the server we refill on each "new" access.
+ *
+ * Directory mtime would be nice to use for finding changes,
+ * unfortunately some servers (NT4) doesn't update on local changes.
*/
- if (!cachep->valid ||
- (cachep->mtime != dentry->d_inode->i_mtime &&
- filp->f_pos == 2))
+ if (!cachep->valid || filp->f_pos == 2)
{
result = smb_refill_dircache(cachep, dentry);
if (result)
struct smb_sb_info *server = server_from_dentry(dentry);
int error = 0;
- VERBOSE("smb_dir_open: (%s/%s)\n", dentry->d_parent->d_name.name,
+ VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
file->f_dentry->d_name.name);
if (server->conn_pid)
error = smb_revalidate_inode(dentry);
valid = (age <= SMBFS_MAX_AGE);
#ifdef SMBFS_DEBUG_VERBOSE
if (!valid)
- VERBOSE("smb_lookup_validate: %s/%s not valid, age=%lu\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- age);
+ VERBOSE("%s/%s not valid, age=%lu\n", DENTRY_PATH(dentry), age);
#endif
- if (inode)
- {
- if (is_bad_inode(inode))
- {
- PARANOIA("smb_lookup_validate: %s/%s has dud inode\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ if (inode) {
+ if (is_bad_inode(inode)) {
+ PARANOIA("%s/%s has dud inode\n", DENTRY_PATH(dentry));
valid = 0;
} else if (!valid)
valid = (smb_revalidate_inode(dentry) == 0);
- } else
- {
- /*
- * What should we do for negative dentries?
- */
+ } else {
+ /*
+ * What should we do for negative dentries?
+ */
}
return valid;
}
-/*
- * XXX: It would be better to use the tolower from linux/ctype.h,
- * but _ctype is needed and it is not exported.
- */
-#define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))
-
static int
smb_hash_dentry(struct dentry *dir, struct qstr *this)
{
static void
smb_delete_dentry(struct dentry * dentry)
{
- if (dentry->d_inode)
- {
- if (is_bad_inode(dentry->d_inode))
- {
- PARANOIA("smb_delete_dentry: bad inode, unhashing %s/%s\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ if (dentry->d_inode) {
+ if (is_bad_inode(dentry->d_inode)) {
+ PARANOIA("bad inode, unhashing %s/%s\n",
+ DENTRY_PATH(dentry));
d_drop(dentry);
}
smb_close_dentry(dentry);
- } else
- {
- /* N.B. Unhash negative dentries? */
+ } else {
+ /* N.B. Unhash negative dentries? */
}
}
error = smb_proc_getattr(dentry, &finfo);
#ifdef SMBFS_PARANOIA
if (error && error != -ENOENT)
- PARANOIA("smb_lookup: find %s/%s failed, error=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- error);
+ PARANOIA("find %s/%s failed, error=%d\n",
+ DENTRY_PATH(dentry), error);
#endif
inode = NULL;
int error;
struct smb_fattr fattr;
- VERBOSE("smb_instantiate: file %s/%s, fileid=%u\n",
- dentry->d_parent->d_name.name, dentry->d_name.name, fileid);
+ VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid);
error = smb_proc_getattr(dentry, &fattr);
if (error)
goto out_close;
out_close:
if (have_id)
{
- PARANOIA("smb_instantiate: %s/%s failed, error=%d, closing %u\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- error, fileid);
+ PARANOIA("%s/%s failed, error=%d, closing %u\n",
+ DENTRY_PATH(dentry), error, fileid);
smb_close_fileid(dentry, fileid);
}
goto out;
__u16 fileid;
int error;
- VERBOSE("smb_create: creating %s/%s, mode=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name, mode);
+ VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode);
error = smb_proc_create(dentry, 0, CURRENT_TIME, &fileid);
- if (!error)
- {
+ if (!error) {
error = smb_instantiate(dentry, fileid, 1);
- } else
- {
- PARANOIA("smb_create: %s/%s failed, error=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- error);
+ } else {
+ PARANOIA("%s/%s failed, error=%d\n",
+ DENTRY_PATH(dentry), error);
}
return error;
}
error = smb_proc_unlink(new_dentry);
if (error)
{
- VERBOSE("smb_rename: unlink %s/%s, error=%d\n",
- new_dentry->d_parent->d_name.name,
- new_dentry->d_name.name, error);
+ VERBOSE("unlink %s/%s, error=%d\n",
+ DENTRY_PATH(new_dentry), error);
goto out;
}
/* FIXME */
* Copyright (C) 1995, 1996, 1997 by Paal-Kr. Engstad and Volker Lendecke
* Copyright (C) 1997 by Volker Lendecke
*
+ * Please add a note about your changes to smbfs in the ChangeLog file.
*/
#include <linux/sched.h>
#include <linux/smbno.h>
#include <linux/smb_fs.h>
-#define SMBFS_PARANOIA 1
-/* #define SMBFS_DEBUG_VERBOSE 1 */
-
#include "smb_debug.h"
-static inline int
-min(int a, int b)
-{
- return a < b ? a : b;
-}
static inline void
smb_unlock_page(struct page *page)
static int
smb_fsync(struct file *file, struct dentry * dentry)
{
- VERBOSE("smb_fsync: sync file %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry));
return 0;
}
clear_bit(PG_error, &page->flags);
- VERBOSE("smb_readpage_sync: file %s/%s, count=%d@%ld, rsize=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name, count,
- offset, rsize);
+ VERBOSE("file %s/%s, count=%d@%ld, rsize=%d\n",
+ DENTRY_PATH(dentry), count, offset, rsize);
result = smb_open(dentry, SMB_O_RDONLY);
if (result < 0)
{
- PARANOIA("smb_readpage_sync: %s/%s open failed, error=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- result);
+ PARANOIA("%s/%s open failed, error=%d\n",
+ DENTRY_PATH(dentry), result);
goto io_error;
}
DEBUG1("SMB: smb_readpage %08lx\n", page_address(page));
#ifdef SMBFS_PARANOIA
if (test_bit(PG_locked, &page->flags))
- DEBUG1("smb_readpage: page already locked!\n");
+ PARANOIA("page already locked!\n");
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
int result, written = 0;
offset += page->offset;
- VERBOSE("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- count, offset, wsize);
+ VERBOSE("file %s/%s, count=%d@%ld, wsize=%d\n",
+ DENTRY_PATH(dentry), count, offset, wsize);
do {
if (count < wsize)
/* N.B. what if result < wsize?? */
#ifdef SMBFS_PARANOIA
if (result < wsize)
- printk(KERN_DEBUG "smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
+ printk(KERN_DEBUG "short write, wsize=%d, result=%d\n",
+ wsize, result);
#endif
buffer += wsize;
offset += wsize;
#ifdef SMBFS_PARANOIA
if (test_bit(PG_locked, &page->flags))
- DEBUG1("smb_writepage: page already locked!\n");
+ PARANOIA("page already locked!\n");
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
{
struct dentry *dentry = file->f_dentry;
- DEBUG1("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- count, page->offset+offset, sync);
+ DEBUG1("(%s/%s %d@%ld, sync=%d)\n",
+ DENTRY_PATH(dentry), count, page->offset+offset, sync);
return smb_writepage_sync(dentry, page, offset, count);
}
struct dentry * dentry = file->f_dentry;
ssize_t status;
- VERBOSE("smb_file_read: file %s/%s, count=%lu@%lu\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
(unsigned long) count, (unsigned long) *ppos);
status = smb_revalidate_inode(dentry);
if (status)
{
- PARANOIA("smb_file_read: %s/%s validation failed, error=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- status);
+ PARANOIA("%s/%s validation failed, error=%d\n",
+ DENTRY_PATH(dentry), status);
goto out;
}
- VERBOSE("smb_file_read: before read, size=%ld, pages=%ld, flags=%x, atime=%ld\n",
+ VERBOSE("before read, size=%ld, pages=%ld, flags=%x, atime=%ld\n",
dentry->d_inode->i_size, dentry->d_inode->i_nrpages,
- dentry->d_inode->i_flags,
- dentry->d_inode->i_atime);
+ dentry->d_inode->i_flags, dentry->d_inode->i_atime);
+
status = generic_file_read(file, buf, count, ppos);
out:
return status;
struct dentry * dentry = file->f_dentry;
int status;
- VERBOSE("smb_file_mmap: file %s/%s, address %lu - %lu\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- vma->vm_start, vma->vm_end);
+ VERBOSE("file %s/%s, address %lu - %lu\n",
+ DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
status = smb_revalidate_inode(dentry);
if (status)
{
- PARANOIA("smb_file_mmap: %s/%s validation failed, error=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- status);
+ PARANOIA("%s/%s validation failed, error=%d\n",
+ DENTRY_PATH(dentry), status);
goto out;
}
status = generic_file_mmap(file, vma);
struct dentry * dentry = file->f_dentry;
ssize_t result;
- VERBOSE("smb_file_write: file %s/%s, count=%lu@%lu, pages=%ld\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ VERBOSE("file %s/%s, count=%lu@%lu, pages=%ld\n", DENTRY_PATH(dentry),
(unsigned long) count, (unsigned long) *ppos,
dentry->d_inode->i_nrpages);
result = smb_revalidate_inode(dentry);
if (result)
{
- PARANOIA("smb_file_write: %s/%s validation failed, error=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- result);
- goto out;
+ PARANOIA("%s/%s validation failed, error=%d\n",
+ DENTRY_PATH(dentry), result);
+ goto out;
}
result = smb_open(dentry, SMB_O_WRONLY);
if (count > 0)
{
result = generic_file_write(file, buf, count, ppos);
- VERBOSE("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
+ VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
(long) file->f_pos, dentry->d_inode->i_size,
dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
}
static int
smb_file_open(struct inode *inode, struct file * file)
{
- VERBOSE("smb_file_open: opening %s/%s, d_count=%d\n",
- file->f_dentry->d_parent->d_name.name,
- file->f_dentry->d_name.name, file->f_dentry->d_count);
+ VERBOSE("opening %s/%s, d_count=%d\n",
+ DENTRY_PATH(file->f_dentry), file->f_dentry->d_count);
return 0;
}
{
struct dentry * dentry = file->f_dentry;
- VERBOSE("smb_file_release: closing %s/%s, d_count=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- dentry->d_count);
-
+ VERBOSE("closing %s/%s, d_count=%d\n",
+ DENTRY_PATH(dentry), dentry->d_count);
+
if (dentry->d_count == 1)
- {
smb_close(inode);
- }
+
return 0;
}
int mode = inode->i_mode;
int error = 0;
- VERBOSE("smb_file_permission: mode=%x, mask=%x\n", mode, mask);
+ VERBOSE("mode=%x, mask=%x\n", mode, mask);
/* Look at user permissions */
mode >>= 6;
* Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
* Copyright (C) 1997 by Volker Lendecke
*
+ * Please add a note about your changes to smbfs in the ChangeLog file.
*/
#include <linux/config.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#define SMBFS_PARANOIA 1
-/* #define SMBFS_DEBUG_VERBOSE 1 */
-
#include "smb_debug.h"
static void smb_read_inode(struct inode *);
{
struct inode *result;
- DEBUG1("smb_iget: %p\n", fattr);
+ DEBUG1("fattr @ %p\n", fattr);
result = get_empty_inode();
result->i_sb = sb;
void
smb_invalidate_inodes(struct smb_sb_info *server)
{
- VERBOSE("smb_invalidate_inodes\n");
+ VERBOSE("\n");
shrink_dcache_sb(SB_of(server));
invalidate_inodes(SB_of(server));
}
* To limit damage, mark the inode as bad so that
* subsequent lookup validations will fail.
*/
- PARANOIA("smb_refresh_inode: %s/%s changed mode, %07o to %07o\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name,
+ PARANOIA("%s/%s changed mode, %07o to %07o\n",
+ DENTRY_PATH(dentry),
inode->i_mode, fattr.f_mode);
fattr.f_mode = inode->i_mode; /* save mode */
time_t last_time;
int error = 0;
- DEBUG1("smb_revalidate_inode\n");
+ DEBUG1("\n");
/*
* If this is a file opened with write permissions,
*/
if (time_before(jiffies, inode->u.smbfs_i.oldmtime + HZ/10))
{
- VERBOSE("smb_revalidate_inode: up-to-date, jiffies=%lu, oldtime=%lu\n",
+ VERBOSE("up-to-date, jiffies=%lu, oldtime=%lu\n",
jiffies, inode->u.smbfs_i.oldmtime);
goto out;
}
error = smb_refresh_inode(dentry);
if (error || inode->i_mtime != last_time)
{
- VERBOSE("smb_revalidate: %s/%s changed, old=%ld, new=%ld\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ VERBOSE("%s/%s changed, old=%ld, new=%ld\n",
+ DENTRY_PATH(dentry),
(long) last_time, (long) inode->i_mtime);
if (!S_ISDIR(inode->i_mode))
invalidate_inode_pages(inode);
static void
smb_put_inode(struct inode *ino)
{
- DEBUG1("smb_put_inode: count = %d\n", ino->i_count);
+ DEBUG1("count = %d\n", ino->i_count);
if (ino->i_count == 1)
ino->i_nlink = 0;
}
static void
smb_delete_inode(struct inode *ino)
{
- DEBUG1("smb_delete_inode\n");
+ DEBUG1("\n");
if (smb_close(ino))
- PARANOIA("smb_delete_inode: could not close inode %ld\n",
- ino->i_ino);
+ PARANOIA("could not close inode %ld\n", ino->i_ino);
clear_inode(ino);
}
}
if (server->conn_pid)
- kill_proc(server->conn_pid, SIGTERM, 1);
+ kill_proc(server->conn_pid, SIGTERM, 1);
kfree(server->mnt);
kfree(sb->u.smbfs_sb.temp_buf);
if (!mnt)
goto out_no_mount;
*mnt = *((struct smb_mount_data *) raw_data);
- /* ** temp ** pass config flags in file mode */
+ /* FIXME: ** temp ** pass config flags in file mode */
mnt->version = (mnt->file_mode >> 9);
mnt->file_mode &= (S_IRWXU | S_IRWXG | S_IRWXO);
mnt->file_mode |= S_IFREG;
printk(KERN_ERR "SMBFS: need mount version %d\n", SMB_MOUNT_VERSION);
goto out_fail;
out_no_data:
- printk(KERN_DEBUG "smb_read_super: missing data argument\n");
+ printk(KERN_ERR "smb_read_super: missing data argument\n");
out_fail:
sb->s_dev = 0;
MOD_DEC_USE_COUNT;
if ((attr->ia_valid & ATTR_SIZE) != 0)
{
- VERBOSE("smb_notify_change: changing %s/%s, old size=%ld, new size=%ld\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
+ DENTRY_PATH(dentry),
(long) inode->i_size, (long) attr->ia_size);
error = smb_open(dentry, O_WRONLY);
if (error)
*/
if ((attr->ia_valid & ATTR_MODE) != 0)
{
- VERBOSE("smb_notify_change: %s/%s mode change, old=%x, new=%lx\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- fattr.f_mode,attr->ia_mode);
+ VERBOSE("%s/%s mode change, old=%x, new=%lx\n",
+ DENTRY_PATH(dentry), fattr.f_mode,attr->ia_mode);
changed = 0;
if (attr->ia_mode & S_IWUSR)
{
int
init_module(void)
{
- DEBUG1("smbfs: init_module called\n");
+ DEBUG1("registering ...\n");
#ifdef DEBUG_SMB_MALLOC
smb_malloced = 0;
void
cleanup_module(void)
{
- DEBUG1("smbfs: cleanup_module called\n");
+ DEBUG1("unregistering ...\n");
unregister_filesystem(&smb_fs_type);
#ifdef DEBUG_SMB_MALLOC
printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced);
* Copyright (C) 1995, 1996 by Volker Lendecke
* Copyright (C) 1997 by Volker Lendecke
*
+ * Please add a note about your changes to smbfs in the ChangeLog file.
*/
#include <linux/errno.h>
unsigned int cmd, unsigned long arg)
{
struct smb_sb_info *server = SMB_SERVER(inode);
+ struct smb_conn_opt opt;
int result = -EINVAL;
- switch (cmd)
- {
+ switch (cmd) {
case SMB_IOC_GETMOUNTUID:
result = put_user(server->mnt->mounted_uid, (uid_t *) arg);
break;
case SMB_IOC_NEWCONN:
- {
- struct smb_conn_opt opt;
-
/* require an argument == the mount data, else it is EINVAL */
if (!arg)
- goto out;
+ break;
result = -EFAULT;
if (!copy_from_user(&opt, (void *)arg, sizeof(opt)))
result = smb_newconn(server, &opt);
break;
- }
default:
}
-out:
return result;
}
* Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
* Copyright (C) 1997 by Volker Lendecke
*
- * 28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per
- * 28/09/97 - Fixed smb_d_path [now smb_build_path()] to be non-recursive
- * by Riccardo Facchetti
- * 16/11/99 (tridge)
- * - use level 260 for most conns, or level 1 for <NT1
- * - don't sleep every time with win95 on a FINDNEXT
- * - fixed loop_count bug
- * - got rid of resume_key
- * Jan 2000, cpg@aladdin.de
- * - added posix semantics for unlink
- * March 2000, tridge
- * - removed support for old protocol levels. It didn't work anyway
- * and was cluttering things up a lot.
+ * Please add a note about your changes to smbfs in the ChangeLog file.
*/
#include <linux/types.h>
config option. */
#define SMBFS_POSIX_UNLINK 1
-#define SMBFS_PARANOIA 1
-/* #define SMBFS_DEBUG_TIMESTAMP 1 */
-/* #define SMBFS_DEBUG_VERBOSE 1 */
-
#include "smb_debug.h"
#define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN)
#define SMB_DIRINFO_SIZE 43
#define SMB_STATUS_SIZE 21
-/* This makes a dentry parent/child pair. Useful for debugging printk's */
-#define DENTRY_PATH(dentry) \
- (dentry)->d_parent->d_name.name,(dentry)->d_name.name
-
-
static int smb_proc_setattr_ext(struct smb_sb_info *, struct inode *,
struct smb_fattr *);
static int
smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
__u16 attr);
-
static int
-smb_proc_do_getattr(struct dentry *dir, struct smb_fattr *fattr,struct smb_sb_info *server);
+smb_proc_do_getattr(struct dentry *dir, struct smb_fattr *fattr,
+ struct smb_sb_info *server);
+
/* reverse a string inline. This is used by the dircache walking routines */
static void reverse_string(char *buf, int len) {
{
int overhead = SMB_HEADER_LEN + 5 * sizeof(__u16) + 2 + 1 + 2;
int size = smb_get_xmitsize(server, overhead);
- VERBOSE("smb_get_rsize: packet=%d, xmit=%d, size=%d\n",
+ VERBOSE("packet=%d, xmit=%d, size=%d\n",
server->packet_size, server->opt.max_xmit, size);
return size;
}
{
int overhead = SMB_HEADER_LEN + 5 * sizeof(__u16) + 2 + 1 + 2;
int size = smb_get_xmitsize(server, overhead);
- VERBOSE("smb_get_wsize: packet=%d, xmit=%d, size=%d\n",
+ VERBOSE("packet=%d, xmit=%d, size=%d\n",
server->packet_size, server->opt.max_xmit, size);
return size;
}
int error = server->err;
char *class = "Unknown";
- VERBOSE("smb_errno: errcls %d code %d from command 0x%x\n",
+ VERBOSE("errcls %d code %d from command 0x%x\n",
errcls, error, SMB_CMD(server->packet));
if (errcls == ERRDOS)
printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
goto out_restore;
}
- VERBOSE("smb_retry: signalled pid %d, waiting for new connection\n",
+ VERBOSE("signalled pid %d, waiting for new connection\n",
server->conn_pid);
/*
*/
interruptible_sleep_on_timeout(&server->wait, 5*HZ);
if (signal_pending(current))
- printk(KERN_INFO "smb_retry: caught signal\n");
+ printk(KERN_INFO "caught signal\n");
/*
* Check for a valid connection.
*/
if (server->state == CONN_VALID)
{
- PARANOIA("smb_retry: new pid=%d, generation=%d\n",
+ PARANOIA("sucessful, new pid=%d, generation=%d\n",
server->conn_pid, server->generation);
result = 1;
}
}
if (smb_valid_packet(s->packet) != 0)
{
- PARANOIA("smb_request_ok: invalid packet!\n");
+ PARANOIA("invalid packet!\n");
goto out;
}
struct file *filp;
int error;
- VERBOSE("smb_newconn: fd=%d, pid=%d\n", opt->fd, current->pid);
+ VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);
/*
* Make sure we don't already have a pid ...
#endif
}
- VERBOSE("smb_newconn: protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
+ VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
server->opt.protocol, server->opt.max_xmit, server->conn_pid,
server->opt.capabilities);
if (mode == read_write &&
(error == -EACCES || error == -ETXTBSY || error == -EROFS))
{
- VERBOSE("smb_proc_open: %s/%s R/W failed, error=%d, retrying R/O\n",
+ VERBOSE("%s/%s R/W failed, error=%d, retrying R/O\n",
DENTRY_PATH(dentry), error);
mode = read_only;
goto retry;
smb_unlock_server(server);
if (result)
{
- PARANOIA("smb_open: %s/%s open failed, result=%d\n",
+ PARANOIA("%s/%s open failed, result=%d\n",
DENTRY_PATH(dentry), result);
goto out;
}
if (inode->u.smbfs_i.access != wish &&
inode->u.smbfs_i.access != SMB_O_RDWR)
{
- PARANOIA("smb_open: %s/%s access denied, access=%x, wish=%x\n",
+ PARANOIA("%s/%s access denied, access=%x, wish=%x\n",
DENTRY_PATH(dentry), inode->u.smbfs_i.access, wish);
result = -EACCES;
}
*/
if (dentry->d_count <= 1)
{
- VERBOSE("smb_close_dentry: closing %s/%s, count=%d\n",
+ VERBOSE("closing %s/%s, count=%d\n",
DENTRY_PATH(dentry), dentry->d_count);
smb_proc_close_inode(server, ino);
}
smb_unlock_server(server);
}
- VERBOSE("smb_close_dentry: closed %s/%s, count=%d\n",
+ VERBOSE("closed %s/%s, count=%d\n",
DENTRY_PATH(dentry), dentry->d_count);
}
}
{
struct smb_sb_info *server = server_from_dentry(dentry);
__u16 returned_count, data_len;
- char *buf;
+ unsigned char *buf;
int result;
smb_lock_server(server);
buf = SMB_BUF(server->packet);
data_len = WVAL(buf, 1);
+
+ /* we can NOT simply trust the data_len given by the server ... */
+ if (data_len > server->packet_size - (buf+3 - server->packet)) {
+ printk(KERN_ERR "smb_proc_read: invalid data length!! "
+ "%d > %d - (%p - %p)\n",
+ data_len, server->packet_size, buf+3, server->packet);
+ result = -EIO;
+ goto out;
+ }
+
memcpy(data, buf+3, data_len);
- if (returned_count != data_len)
- {
+ if (returned_count != data_len) {
printk(KERN_NOTICE "smb_proc_read: returned != data_len\n");
printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n",
returned_count, data_len);
result = data_len;
out:
- VERBOSE("smb_proc_read: file %s/%s, count=%d, result=%d\n",
+ VERBOSE("file %s/%s, count=%d, result=%d\n",
DENTRY_PATH(dentry), count, result);
smb_unlock_server(server);
return result;
int result;
__u8 *p;
- VERBOSE("smb_proc_write: file %s/%s, count=%d@%ld, packet_size=%d\n",
+ VERBOSE("file %s/%s, count=%d@%ld, packet_size=%d\n",
DENTRY_PATH(dentry), count, offset, server->packet_size);
smb_lock_server(server);
retry:
p = smb_setup_header(server, SMBmv, 1, 0);
- WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);
+ WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
*p++ = 4;
p = smb_encode_path(server, p, old_dentry, NULL);
*p++ = 4;
}
+#if SMBFS_POSIX_UNLINK
/*
* Note: called with the server locked.
* removes readonly attribute from a file. Used by unlink to give posix semantics
}
return result;
}
+#endif
int
smb_proc_unlink(struct dentry *dentry)
result = p + WVAL(p, 0);
len = DVAL(p, 60);
- if (len > 255) len = 255;
+ if (len > SMB_MAXNAMELEN)
+ len = SMB_MAXNAMELEN;
/* NT4 null terminates */
entry->name = p + 94;
if (len && entry->name[len-1] == '\0')
len--;
entry->len = len;
- VERBOSE("smb_decode_long_dirent: info 260 at %p, len=%d, name=%s\n",
- p, entry->len, entry->name);
+ VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
+ p, entry->len, entry->len, entry->name);
return result;
}
smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
void *cachep)
{
- char *p, *mask, *param = server->temp_buf;
+ unsigned char *p;
+ char *mask, *param = server->temp_buf;
__u16 command;
int first, entries, entries_seen;
int info_level = 260;
mask_len = smb_encode_path(server, mask, dir, &star) - mask;
first = 1;
- VERBOSE("smb_proc_readdir_long: starting fpos=%d, mask=%s\n",
- fpos, mask);
+ VERBOSE("starting fpos=%d, mask=%s\n", fpos, mask);
/*
* We must reinitialize the dircache when retrying.
entries_seen = 2;
ff_eos = 0;
- while (ff_eos == 0)
- {
+ while (ff_eos == 0) {
loop_count += 1;
- if (loop_count > 10)
- {
+ if (loop_count > 10) {
printk(KERN_WARNING "smb_proc_readdir_long: "
"Looping in FIND_NEXT??\n");
entries = -EIO;
break;
}
- if (first != 0)
- {
+ if (first != 0) {
command = TRANSACT2_FINDFIRST;
WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
WSET(param, 2, max_matches); /* max count */
SMB_CONTINUE_BIT|SMB_CLOSE_IF_END);
WSET(param, 6, info_level);
DSET(param, 8, 0);
- } else
- {
+ } else {
/* we don't need the mask after the first bit */
mask_len = 0;
mask[0] = 0;
command = TRANSACT2_FINDNEXT;
- VERBOSE("smb_proc_readdir_long: handle=0x%X, mask=%s\n",
+ VERBOSE("handle=0x%X, mask=%s\n",
ff_dir_handle, mask);
WSET(param, 0, ff_dir_handle); /* search handle */
&resp_data_len, &resp_data,
&resp_param_len, &resp_param);
- if (result < 0)
- {
- if (smb_retry(server))
- {
- PARANOIA("smb_proc_readdir_long: error=%d, retrying\n", result);
+ if (result < 0) {
+ if (smb_retry(server)) {
+ PARANOIA("error=%d, retrying\n", result);
goto retry;
}
- PARANOIA("smb_proc_readdir_long: error=%d, breaking\n", result);
+ PARANOIA("error=%d, breaking\n", result);
entries = result;
break;
}
continue;
}
- if (server->rcls != 0)
- {
- PARANOIA("smb_proc_readdir_long: name=%s, entries=%d, rcls=%d, err=%d\n",
+ if (server->rcls != 0) {
+ PARANOIA("name=%s, entries=%d, rcls=%d, err=%d\n",
mask, entries, server->rcls, server->err);
entries = -smb_errno(server);
break;
}
/* parse out some important return info */
- if (first != 0)
- {
+ if (first != 0) {
ff_dir_handle = WVAL(resp_param, 0);
ff_searchcount = WVAL(resp_param, 2);
ff_eos = WVAL(resp_param, 4);
- } else
- {
+ } else {
ff_searchcount = WVAL(resp_param, 0);
ff_eos = WVAL(resp_param, 2);
}
if (ff_searchcount == 0)
- {
break;
- }
/* Now we are ready to parse smb directory entries. */
/* point to the data bytes */
p = resp_data;
- for (i = 0; i < ff_searchcount; i++)
- {
+ for (i = 0; i < ff_searchcount; i++) {
struct cache_dirent this_ent, *entry = &this_ent;
+ /* make sure we stay within the buffer */
+ if (p >= resp_data + resp_data_len) {
+ printk(KERN_ERR "smb_proc_readdir_long: "
+ "dirent pointer outside buffer! "
+ "%p %d@%p %d@%p\n",
+ p, resp_data_len, resp_data,
+ server->packet_size, server->packet);
+ result = -EIO; /* always a comm. error? */
+ goto unlock_return;
+ }
+
p = smb_decode_long_dirent(server, p, entry);
/* ignore . and .. from the server */
- if (entries_seen == 2 && entry->name[0] == '.')
- {
+ if (entries_seen == 2 && entry->name[0] == '.') {
if (entry->len == 1)
continue;
if (entry->name[1] == '.' && entry->len == 2)
continue;
}
- if (entries_seen >= fpos)
- {
+ if (entries_seen >= fpos) {
smb_add_to_cache(cachep, entry, entries_seen);
entries += 1;
}
entries_seen++;
}
- VERBOSE("smb_proc_readdir_long: received %d entries, eos=%d\n",
+ VERBOSE("received %d entries, eos=%d\n",
ff_searchcount, ff_eos);
first = 0;
loop_count = 0;
}
+unlock_return:
smb_unlock_server(server);
return entries;
}
p = smb_encode_path(server, p, dir, NULL);
smb_setup_bcc(server, p);
- if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0)
- {
+ if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) {
if (smb_retry(server))
goto retry;
goto out;
}
if (server->rcls != 0)
{
- VERBOSE("smb_proc_getattr_trans2: for %s: result=%d, rcls=%d, err=%d\n",
+ VERBOSE("for %s: result=%d, rcls=%d, err=%d\n",
¶m[6], result, server->rcls, server->err);
result = -smb_errno(server);
goto out;
result = -ENOENT;
if (resp_data_len < 22)
{
- PARANOIA("smb_proc_getattr_trans2: not enough data for %s, len=%d\n",
+ PARANOIA("not enough data for %s, len=%d\n",
¶m[6], resp_data_len);
goto out;
}
* get the file attribute
*/
static int
-smb_proc_do_getattr(struct dentry *dir, struct smb_fattr *fattr,struct smb_sb_info *server)
+smb_proc_do_getattr(struct dentry *dir, struct smb_fattr *fattr,
+ struct smb_sb_info *server)
{
int result;
struct smb_sb_info *server = server_from_dentry(dir);
int result;
- VERBOSE("smb_proc_setattr: setting %s/%s, open=%d\n",
- DENTRY_PATH(dir), smb_is_open(dir->d_inode));
+ VERBOSE("setting %s/%s, open=%d\n", DENTRY_PATH(dir),
+ smb_is_open(dir->d_inode));
smb_lock_server(server);
result = smb_proc_setattr_core(server, dir, fattr->attr);
struct inode *inode = dentry->d_inode;
int result;
- VERBOSE("smb_proc_settime: setting %s/%s, open=%d\n",
- DENTRY_PATH(dentry), smb_is_open(inode));
+ VERBOSE("setting %s/%s, open=%d\n", DENTRY_PATH(dentry),
+ smb_is_open(inode));
smb_lock_server(server);
/* setting the time on a Win95 server fails (tridge) */
- if (!(server->mnt->version & SMB_FIX_WIN95))
- {
+ if (!(server->mnt->version & SMB_FIX_WIN95)) {
if (smb_is_open(inode) &&
inode->u.smbfs_i.access != SMB_O_RDONLY)
result = smb_proc_setattr_ext(server, inode, fattr);
else
result = smb_proc_setattr_trans2(server, dentry, fattr);
- } else
- {
+ } else {
/*
* Fail silently on directories ... timestamp can't be set?
*/
result = 0;
- if (S_ISREG(inode->i_mode))
- {
+ if (S_ISREG(inode->i_mode)) {
/*
* Set the mtime by opening and closing the file.
* Note that the file is opened read-only, but this
result = -EACCES;
if (!smb_is_open(inode))
smb_proc_open(server, dentry, SMB_O_RDONLY);
- if (smb_is_open(inode))
- {
+ if (smb_is_open(inode)) {
inode->i_mtime = fattr->f_mtime;
result = smb_proc_close_inode(server, inode);
}
retry:
smb_setup_header(server, SMBdskattr, 0, 0);
- if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0)
- {
+ if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) {
if (smb_retry(server))
goto retry;
goto out;
* Defines some debug macros for smbfs.
*/
+/* This makes a dentry parent/child pair. Useful for debugging printk's */
+#define DENTRY_PATH(dentry) \
+ (dentry)->d_parent->d_name.name,(dentry)->d_name.name
+
/*
* safety checks that should never happen ???
* these are normally enabled.
*/
#ifdef SMBFS_PARANOIA
-#define PARANOIA(x...) printk(KERN_NOTICE ## x);
+#define PARANOIA(x...) printk(KERN_NOTICE __FUNCTION__ ": " ## x)
#else
#define PARANOIA(x...) do { ; } while(0)
#endif
/* lots of debug messages */
#ifdef SMBFS_DEBUG_VERBOSE
-#define VERBOSE(x...) printk(KERN_DEBUG ## x);
+#define VERBOSE(x...) printk(KERN_DEBUG __FUNCTION__ ": " ## x)
#else
#define VERBOSE(x...) do { ; } while(0)
#endif
* too common name.
*/
#ifdef SMBFS_DEBUG
-#define DEBUG1(x...) printk(KERN_DEBUG ## x);
+#define DEBUG1(x...) printk(KERN_DEBUG __FUNCTION__ ": " ## x)
#else
#define DEBUG1(x...) do { ; } while(0)
#endif
* Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
* Copyright (C) 1997 by Volker Lendecke
*
+ * Please add a note about your changes to smbfs in the ChangeLog file.
*/
#include <linux/sched.h>
#include <asm/uaccess.h>
-#define SMBFS_PARANOIA 1
-/* #define SMBFS_DEBUG_VERBOSE 1 */
-
#include "smb_debug.h"
static int
result = -EIO;
if (job->sk->dead)
{
- PARANOIA("smb_data_callback: sock dead!\n");
+ PARANOIA("sock dead!\n");
break;
}
result = _recvfrom(socket, (void *) peek_buf, 4,
MSG_DONTWAIT);
- DEBUG1("smb_data_callback: got SESSION KEEPALIVE\n");
+ DEBUG1("got SESSION KEEPALIVE\n");
if (result == -EAGAIN)
break;
struct data_callback* job;
job = kmalloc(sizeof(struct data_callback),GFP_ATOMIC);
if(job == 0) {
- printk("smb_data_ready(): lost SESSION KEEPALIVE due to OOM.\n");
+ printk("smb_data_ready: lost SESSION KEEPALIVE due to OOM.\n");
found_data(sk);
return;
}
{
#ifdef SMBFS_PARANOIA
if (!smb_valid_socket(file->f_dentry->d_inode))
- PARANOIA("smb_server_sock: bad socket!\n");
+ PARANOIA("bad socket!\n");
#endif
return &file->f_dentry->d_inode->u.socket_i;
}
sk = socket->sk;
if (sk == NULL)
{
- DEBUG1("smb_catch_keepalive: sk == NULL");
+ DEBUG1("sk == NULL");
server->data_ready = NULL;
goto out;
}
- DEBUG1("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n",
+ DEBUG1("sk->d_r = %x, server->d_r = %x\n",
(unsigned int) (sk->data_ready),
(unsigned int) (server->data_ready));
"server->data_ready == NULL\n");
goto out;
}
- pr_debug("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n",
- (unsigned int) (sk->data_ready),
- (unsigned int) (server->data_ready));
+ DEBUG1("sk->d_r = %x, server->d_r = %x\n",
+ (unsigned int) (sk->data_ready),
+ (unsigned int) (server->data_ready));
/*
* Restore the original callback atomically to avoid races ...
server->data_ready = NULL;
if (data_ready != smb_data_ready)
{
- printk("smb_dont_catch_keepalive: "
+ printk(KERN_ERR "smb_dont_catch_keepalive: "
"sk->data_ready != smb_data_ready\n");
}
error = 0;
{
struct file * file = server->sock_file;
- if (file)
- {
- VERBOSE("smb_close_socket: closing socket %p\n",
- server_sock(server));
+ if (file) {
+ VERBOSE("closing socket %p\n", server_sock(server));
#ifdef SMBFS_PARANOIA
if (server_sock(server)->sk->data_ready == smb_data_ready)
- PARANOIA("smb_close_socket: still catching keepalives!\n");
+ PARANOIA("still catching keepalives!\n");
#endif
server->sock_file = NULL;
fput(file);
}
if (result < 0)
{
- DEBUG1("smb_send_raw: sendto error = %d\n", -result);
+ DEBUG1("sendto error = %d\n", -result);
return result;
}
already_sent += result;
}
if (result < 0)
{
- DEBUG1("smb_receive_raw: recvfrom error = %d\n",
- -result);
+ DEBUG1("recvfrom error = %d\n", -result);
return result;
}
already_read += result;
if (result < 0)
{
- PARANOIA("smb_get_length: recv error = %d\n", -result);
+ PARANOIA("recv error = %d\n", -result);
return result;
}
switch (peek_buf[0])
break;
case 0x85:
- DEBUG1("smb_get_length: Got SESSION KEEP ALIVE\n");
+ DEBUG1("Got SESSION KEEP ALIVE\n");
goto re_recv;
default:
- PARANOIA("smb_get_length: Invalid NBT packet, code=%x\n",
- peek_buf[0]);
+ PARANOIA("Invalid NBT packet, code=%x\n", peek_buf[0]);
return -EIO;
}
result = smb_receive_raw(socket, packet + 4, len);
if (result < 0)
{
- VERBOSE("smb_receive: receive error: %d\n", result);
+ VERBOSE("receive error: %d\n", result);
goto out;
}
server->rcls = *(packet + smb_rcls);
#ifdef SMBFS_DEBUG_VERBOSE
if (server->rcls != 0)
- VERBOSE("smb_receive: rcls=%d, err=%d\n",
- server->rcls, server->err);
+ VERBOSE("rcls=%d, err=%d\n", server->rcls, server->err);
#endif
out:
return result;
*/
if (parm_count == parm_tot && data_count == data_tot)
{
- VERBOSE("smb_receive_trans2: fast track, parm=%u %u %u, data=%u %u %u\n",
+ VERBOSE("fast track, parm=%u %u %u, data=%u %u %u\n",
parm_disp, parm_offset, parm_count,
data_disp, data_offset, data_count);
memcpy(*parm + parm_disp, base + parm_offset, parm_count);
memcpy(*data + data_disp, base + data_offset, data_count);
- PARANOIA("smb_receive_trans2: copied, parm=%u of %u, data=%u of %u\n",
+ PARANOIA("copied, parm=%u of %u, data=%u of %u\n",
parm_len, parm_tot, data_len, data_tot);
/*
server->packet_size = buf_len;
server->packet = rcv_buf;
rcv_buf = inbuf;
- } else
- {
- PARANOIA("smb_receive_trans2: copying data, old size=%d, new size=%u\n",
+ } else {
+ PARANOIA("copying data, old size=%d, new size=%u\n",
server->packet_size, buf_len);
memcpy(inbuf, rcv_buf, parm_len + data_len);
}
return result;
out_no_mem:
- PARANOIA("smb_receive_trans2: couldn't allocate data area\n");
+ printk(KERN_ERR "smb_receive_trans2: couldn't allocate data area\n");
result = -ENOMEM;
goto out;
out_too_long:
goto bad_conn;
len = smb_len(buffer) + 4;
- DEBUG1("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
+ DEBUG1("len = %d cmd = 0x%X\n", len, buffer[8]);
spin_lock_irqsave(¤t->sigmask_lock, flags);
sigpipe = sigismember(¤t->signal, SIGPIPE);
}
out:
- DEBUG1("smb_request: result = %d\n", result);
+ DEBUG1("result = %d\n", result);
return result;
bad_conn:
- PARANOIA("smb_request: result %d, setting invalid\n", result);
+ PARANOIA("result %d, setting invalid\n", result);
server->state = CONN_INVALID;
smb_invalidate_inodes(server);
- goto out;
+ goto out;
bad_no_packet:
printk(KERN_ERR "smb_request: no packet!\n");
goto out;
mm_segment_t fs;
int result;
- DEBUG1("smb_trans2_request: com=%d, ld=%d, lp=%d\n",
- trans2_command, ldata, lparam);
+ DEBUG1("com=%d, ld=%d, lp=%d\n", trans2_command, ldata, lparam);
/*
* These are initialized in smb_request_ok, but not here??
return result;
bad_conn:
- PARANOIA("smb_trans2_request: result=%d, setting invalid\n", result);
+ PARANOIA("result=%d, setting invalid\n", result);
server->state = CONN_INVALID;
smb_invalidate_inodes(server);
goto out;
There is no warning any more.
Both read-only and read-write stuff is fixed, both in
msdos-compatibile mode, and in umsdos EMD mode, and it seems stable.
-There are still few hardlink nuisances, but those are not fatal.
-
-I'd call it pre-release, and ask for as many people as possible to
-come and test it! See notes below for some more information, or if
-you are trying to use UMSDOS as root partition.
Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that
-will compile and work on 2.2.x kernels and glibc based systems may be found
-at http://cvs.linux.hr/
+will compile and work on 2.2.x+ kernels and glibc based systems, as well as
+kernel patches and other umsdos related information may be found at
+http://linux.voyager.hr/umsdos/
Legend: those lines marked with '+' on the beggining of line indicates it
passed all of my tests, and performed perfect in all of them.
-Current status (000123) - UMSDOS 0.85g:
+Current status (000729) - UMSDOS 0.85i:
(1) pure MSDOS (no --linux-.--- EMD file):
WRITE:
+ creat file - works
-+ delete file - works
++ unlink file - works
+ write file - works
+ rename file (same dir) - works
+ rename file (dif. dir) - works
+ read file - works
+ switching MSDOS/UMSDOS - works
+ switching UMSDOS/MSDOS - works
-- pseudo root things - works mostly. See notes below.
+- pseudo root things - works. See notes below.
+ resolve symlink - works
+ dereference symlink - works
+ dangling symlink - works
WRITE:
+ create symlink - works
-- create hardlink - works for same DIR (see notes)
++ create hardlink - works
+ create file - works
+ create special file - works
+ write to file - works
+ rename file (same dir) - works
+ rename file (dif. dir) - works
+ rename hardlink (same dir) - works
-- rename hardlink (dif. dir) -
++ rename hardlink (dif. dir) - works
+ rename symlink (same dir) - works
+ rename symlink (dif. dir) - works
+ rename dir (same dir) - works
+ rename dir (dif. dir) - works
+ delete file - works
+ notify_change (chown,perms) - works
-- delete hardlink - works for same DIR (see notes)
++ delete hardlink - works
+ mkdir - works
+ rmdir - works
+ umssyncing (many ioctls) - works
Note: creating and using pseudo-hardlinks is always non-perfect, especially
in filesystems that might be externally modified like umsdos. There is
example is specs file about it. Specifically, moving directory which
-contains hardlinks will break them.
-
-Note: (about pseudoroot) If you are currently trying to use UMSDOS as root
-partition (with linux installed in c:\linux) it will boot, but there may be
-some problems. Volunteers ready to test pseudoroot are needed (preferably
-ones with working backups or unimportant data). For example, '/DOS' pseudo
-directory is only partially re-implemented and buggy. It works most of the
-time, though. Update: should work ok in 0.84, although it still does not
-work correctly in combination with initrd featere. Working on this!
+contains hardlinks will break them in some cases.
Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in
pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice
versa. Thanks to Sorin Iordachescu <sorin@rodae.ro> for providing fix.
-
-Warning: (about hardlinks) - modifying hardlinks (esp. if they are in
-different directories) are currently somewhat broken, I'm working on it.
-Problem seems to be that code uses and updates EMD of directory where 'real
-hardlink' is stored, not EMD of directory where our pseudo-hardlink is
-located! I'm looking for ideas how to work around this in clean way, since
-without it modifying hardlinks in any but most simple ways is broken!
+See http://linux.voyager.hr/umsdos/hlbug.html for more info and upgrade
+procedure if you used broken versions...
------------------------------------------------------------------------------
I'm unfortunately somewhat out of time to read linux-kernel@vger, but I do
check for messages having "UMSDOS" in the subject, and read them. I might
miss some in all that volume, though. I should reply to any direct e-mail
-in few days. If I don't, probably I never got your message. You can try
-mnalis-umsdos@voyager.hr; however mnalis@jagor.srce.hr is preferable.
+in few days. If I don't, probably I never got your message.
Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: entering.\n"));
ret = umsdos_emd_dir_read (filp, (char *) entry, UMSDOS_REC_SIZE);
+
+ /* if this is an invalid entry (invalid name length), ignore it */
+ if( entry->name_len > UMSDOS_MAXNAME )
+ {
+ printk (KERN_WARNING "Ignoring invalid EMD entry with size %d\n", entry->name_len);
+ entry->name_len = 0;
+ ret = -ENAMETOOLONG; /* notify umssync(8) code that something is wrong */
+ }
+
+
if (ret == 0) { /* if no error */
/* Variable size record. Maybe, we have to read some more */
int recsize = umsdos_evalrecsize (entry->name_len);
,inode->i_count));
if (inode == pseudo_root) {
- printk (KERN_ERR "Umsdos: Oops releasing pseudo_root."
- " Notify jacques@solucorp.qc.ca\n");
+ printk (KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, inode->i_count);
}
if (inode->i_count == 1)
}
-int umsdos_notify_change_locked(struct dentry *, struct iattr *);
-/*
- * lock the parent dir before starting ...
- */
-int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
-{
- struct inode *dir = dentry->d_parent->d_inode;
- int ret;
-
- down(&dir->i_sem);
- ret = umsdos_notify_change_locked(dentry, attr);
- up(&dir->i_sem);
- return ret;
-}
-
/*
* Must be called with the parent lock held.
*/
}
+/*
+ * lock the parent dir before starting ...
+ * also handles hardlink converting
+ */
+int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *dir;
+ struct umsdos_info info;
+ struct dentry *temp, *old_dentry = NULL;
+ int ret;
+
+ ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len,
+ &info);
+ if (ret)
+ goto out;
+ ret = umsdos_findentry (dentry->d_parent, &info, 0);
+ if (ret) {
+printk("UMSDOS_notify_change: %s/%s not in EMD, ret=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, ret);
+ goto out;
+ }
+
+ if (info.entry.flags & UMSDOS_HLINK) {
+ /*
+ * In order to get the correct (real) inode, we just drop
+ * the original dentry.
+ */
+ d_drop(dentry);
+Printk(("UMSDOS_notify_change: hard link %s/%s, fake=%s\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname));
+
+ /* Do a real lookup to get the short name dentry */
+ temp = umsdos_covered(dentry->d_parent, info.fake.fname,
+ info.fake.len);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out;
+
+ /* now resolve the link ... */
+ temp = umsdos_solve_hlink(temp);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out;
+ old_dentry = dentry;
+ dentry = temp; /* so umsdos_notify_change_locked will operate on that */
+ }
+
+ dir = dentry->d_parent->d_inode;
+
+ down(&dir->i_sem);
+ ret = umsdos_notify_change_locked(dentry, attr);
+ up(&dir->i_sem);
+out:
+ if (old_dentry)
+ dput (dentry); /* if we had to use fake dentry for hardlinks, dput() it now */
+ return ret;
+}
+
+
/*
* Update the disk with the inode content
*/
UMSDOS_notify_change, /* notify_change */
UMSDOS_put_super, /* put_super */
NULL, /* write_super */
- fat_statfs, /* statfs */
+ UMSDOS_statfs, /* statfs */
NULL, /* remount_fs */
fat_clear_inode, /* clear_inode */
};
+
+int UMSDOS_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
+{
+ int ret;
+ struct statfs tmp;
+
+ ret = fat_statfs (sb, buf, bufsiz);
+ copy_from_user (&tmp, buf, bufsiz);
+ if (!ret) {
+ copy_from_user (&tmp, buf, bufsiz);
+ tmp.f_namelen = UMSDOS_MAXNAME;
+ copy_to_user (buf, &tmp, bufsiz);
+ }
+ return ret;
+}
+
+
/*
* Read the super block of an Extended MS-DOS FS.
*/
if (!res)
goto out_fail;
- printk (KERN_INFO "UMSDOS 0.85g "
+ printk (KERN_INFO "UMSDOS 0.85i "
"(compatibility level %d.%d, fast msdos)\n",
UMSDOS_VERSION, UMSDOS_RELEASE);
struct umsdos_info info;
ret = umsdos_emd_dir_readentry (&new_filp, &entry);
+
+ if (ret == -ENAMETOOLONG) {
+ printk (KERN_INFO "Fixing EMD entry with invalid size -- zeroing out\n");
+ fill_new_filp (&new_filp, demd);
+ new_filp.f_pos = f_pos;
+ new_filp.f_reada = 0;
+ memset (&entry, 0, sizeof (entry));
+ ret = umsdos_emd_dir_write (&new_filp, (char *) &entry, UMSDOS_REC_SIZE);
+ continue;
+ }
+
if (ret)
break;
if (entry.name_len <= 0)
if (ret == 0) {
struct iattr newattrs;
+ /* Do a real lookup to get the short name dentry */
+ temp = umsdos_covered(olddentry->d_parent,
+ old_info.fake.fname,
+ old_info.fake.len);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out_unlock2;
+
+ /* now resolve the link ... */
+ temp = umsdos_solve_hlink(temp);
+ ret = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out_unlock2;
+
#ifdef UMSDOS_PARANOIA
if (!oldinode->u.umsdos_i.i_is_hlink)
printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n",
olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino);
#endif
- oldinode->i_nlink++;
+ temp->d_inode->i_nlink++;
Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n",
olddentry->d_parent->d_name.name, olddentry->d_name.name,
oldinode->i_ino, oldinode->i_nlink));
newattrs.ia_valid = 0;
- ret = umsdos_notify_change_locked(olddentry, &newattrs);
+ ret = umsdos_notify_change_locked(temp, &newattrs);
+ if (ret == 0)
+ mark_inode_dirty(temp->d_inode);
+ dput(temp);
+out_unlock2:
}
if (olddir != dir)
up(&olddir->i_sem);
typedef __u8 byte_t;
typedef __u32 int32;
+
+#include <linux/ip.h>
+#include <linux/tcp.h>
/*
* "state" data for each active tcp conversation on the wire. This is
* basically a copy of the entire IP/TCP header from the last packet
extern void nubus_init(void);
#endif
+extern int irda_device_init(void);
+
/*
* Versions of gcc older than that listed below may actually compile
* and link okay, but the end product can have subtle run time bugs.
if(rt == NULL)
{
- rt = (struct atalk_route *)kmalloc(sizeof(struct atalk_route), GFP_KERNEL);
+ rt = (struct atalk_route *)kmalloc(sizeof(struct atalk_route), GFP_ATOMIC);
if(rt == NULL) {
SOCKHASH_UNLOCK();
return (-ENOBUFS);
for (; f; f = f->next) {
count++;
if (ip_rule_match(f,rif,ip,
- tcpsyn,src_port,dst_port,offset)) {
+ tcpsyn,src_port,dst_port,offset!=0)) {
if (!testing
&& !ip_fw_domatch(f, ip, rif, chain->label,
skb, slot,
extern int tekram_init(void);
extern int actisys_init(void);
extern int girbil_init(void);
+extern int toshoboe_init(void);
+extern int litelink_init(void);
static void __irda_task_delete(struct irda_task *task);
#ifdef CONFIG_IRDA_COMPRESSION
#ifdef CONFIG_IRDA_DEFLATE
-extern irda_deflate_init();
+extern irda_deflate_init(void);
#endif /* CONFIG_IRDA_DEFLATE */
#endif /* CONFIG_IRDA_COMPRESSION */
self->remote_credit);
len += sprintf(buf+len, "send credit: %d\n",
self->send_credit);
- len += sprintf(buf+len, " tx packets: %d, ",
+ len += sprintf(buf+len, " tx packets: %ld, ",
self->stats.tx_packets);
- len += sprintf(buf+len, "rx packets: %d, ",
+ len += sprintf(buf+len, "rx packets: %ld, ",
self->stats.rx_packets);
len += sprintf(buf+len, "tx_queue len: %d ",
skb_queue_len(&self->tx_queue));