summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-10 23:18:26 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-10 23:18:26 +0000
commitc7c4310f7fc1485925d800628bf50b3aeab535ef (patch)
treeb12aa4be0e8fb82aaaea97fb475e793e8a347c49 /drivers
parent1ffd1d069ca4c5ffe16fea6175dab1b9bbb15820 (diff)
Merge with Linux 2.4.0-test3-pre8. Linus has accepted most of what
I've sent him, so we're very close to full integration of the MIPS port into his sources.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/lvm-snap.c2
-rw-r--r--drivers/char/nvram.c130
-rw-r--r--drivers/i2c/i2c-core.c14
-rw-r--r--drivers/ide/ide.c7
-rw-r--r--drivers/net/hamradio/dmascc.c1239
-rw-r--r--drivers/video/aty128fb.c174
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c40
-rw-r--r--drivers/video/matrox/matroxfb_maven.c4
-rw-r--r--drivers/video/valkyriefb.c2
-rw-r--r--drivers/video/valkyriefb.h2
10 files changed, 839 insertions, 775 deletions
diff --git a/drivers/block/lvm-snap.c b/drivers/block/lvm-snap.c
index 2f01d3f7b..20e1c78cc 100644
--- a/drivers/block/lvm-snap.c
+++ b/drivers/block/lvm-snap.c
@@ -29,7 +29,7 @@
#include <linux/lvm.h>
-static char *lvm_snap_version = "LVM 0.8final (15/02/2000)\n";
+static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.8final (15/02/2000)\n";
extern const char *const lvm_name;
extern int lvm_blocksizes[];
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 42063cefa..a32cd18df 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -25,9 +25,12 @@
* the kernel and is not a module. Since the functions are used by some Atari
* drivers, this is the case on the Atari.
*
+ *
+ * 1.1 Cesar Barros: SMP locking fixes
+ * added changelog
*/
-#define NVRAM_VERSION "1.0"
+#define NVRAM_VERSION "1.1"
#include <linux/module.h>
#include <linux/config.h>
@@ -81,7 +84,7 @@
#endif
/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
- * interrupts disabled. Due to the index-port/data-port design of the RTC, we
+ * rtc_lock held. Due to the index-port/data-port design of the RTC, we
* don't want two different things trying to get to it at once. (e.g. the
* periodic 11 min sync from time.c vs. this driver.)
*/
@@ -96,11 +99,13 @@
#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+extern spinlock_t rtc_lock;
static int nvram_open_cnt = 0; /* #times opened */
static int nvram_open_mode; /* special open modes */
@@ -163,21 +168,20 @@ unsigned char nvram_read_byte( int i )
unsigned long flags;
unsigned char c;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
c = nvram_read_int( i );
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
return( c );
}
+/* This races nicely with trying to read with checksum checking (nvram_read) */
void nvram_write_byte( unsigned char c, int i )
{
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
nvram_write_int( c, i );
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
}
int nvram_check_checksum( void )
@@ -185,10 +189,9 @@ int nvram_check_checksum( void )
unsigned long flags;
int rv;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
rv = nvram_check_checksum_int();
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
return( rv );
}
@@ -196,10 +199,9 @@ void nvram_set_checksum( void )
{
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&rtc_lock, flags);
nvram_set_checksum_int();
- restore_flags(flags);
+ spin_unlock_irqrestore (&rtc_lock, flags);
}
#endif /* MACH == ATARI */
@@ -228,63 +230,67 @@ static long long nvram_llseek(struct file *file,loff_t offset, int origin )
static ssize_t nvram_read(struct file * file,
char * buf, size_t count, loff_t *ppos )
{
- unsigned long flags;
+ char contents [NVRAM_BYTES];
unsigned i = *ppos;
- char *tmp = buf;
-
- if (i != *ppos)
- return -EINVAL;
+ char *tmp;
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
- if (!nvram_check_checksum_int()) {
- restore_flags(flags);
- return( -EIO );
- }
+ if (!nvram_check_checksum_int())
+ goto checksum_err;
+
+ for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+ *tmp = nvram_read_int(i);
+
+ spin_unlock_irq (&rtc_lock);
+
+ copy_to_user_ret (buf, contents, tmp - contents, -EFAULT);
- for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp )
- put_user( nvram_read_int(i), tmp );
*ppos = i;
- restore_flags(flags);
- return( tmp - buf );
+ return (tmp - contents);
+
+checksum_err:
+ spin_unlock_irq (&rtc_lock);
+ return -EIO;
}
static ssize_t nvram_write(struct file * file,
const char * buf, size_t count, loff_t *ppos )
{
- unsigned long flags;
+ char contents [NVRAM_BYTES];
unsigned i = *ppos;
- const char *tmp = buf;
- char c;
-
- if (i != *ppos)
- return -EINVAL;
+ char * tmp;
- save_flags(flags);
- cli();
-
- if (!nvram_check_checksum_int()) {
- restore_flags(flags);
- return( -EIO );
- }
+ /* could comebody please help me indent this better? */
+ copy_from_user_ret (contents, buf, (NVRAM_BYTES - i) < count ?
+ (NVRAM_BYTES - i) : count,
+ -EFAULT);
+
+ spin_lock_irq (&rtc_lock);
+
+ if (!nvram_check_checksum_int())
+ goto checksum_err;
+
+ for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+ nvram_write_int (*tmp, i);
- for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) {
- get_user( c, tmp );
- nvram_write_int( c, i );
- }
nvram_set_checksum_int();
+
+ spin_unlock_irq (&rtc_lock);
+
*ppos = i;
- restore_flags(flags);
- return( tmp - buf );
+ return (tmp - contents);
+
+checksum_err:
+ spin_unlock_irq (&rtc_lock);
+ return -EIO;
}
static int nvram_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
{
- unsigned long flags;
int i;
switch( cmd ) {
@@ -293,14 +299,13 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
if (!capable(CAP_SYS_ADMIN))
return( -EACCES );
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
for( i = 0; i < NVRAM_BYTES; ++i )
nvram_write_int( 0, i );
nvram_set_checksum_int();
- restore_flags(flags);
+ spin_unlock_irq (&rtc_lock);
return( 0 );
case NVRAM_SETCKS: /* just set checksum, contents unchanged
@@ -309,10 +314,9 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
if (!capable(CAP_SYS_ADMIN))
return( -EACCES );
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
nvram_set_checksum_int();
- restore_flags(flags);
+ spin_unlock_irq (&rtc_lock);
return( 0 );
default:
@@ -355,16 +359,14 @@ static int nvram_read_proc( char *buffer, char **start, off_t offset,
static int nvram_read_proc( char *buffer, char **start, off_t offset,
int size, int *eof, void *data )
{
- unsigned long flags;
unsigned char contents[NVRAM_BYTES];
int i, len = 0;
off_t begin = 0;
-
- save_flags(flags);
- cli();
+
+ spin_lock_irq (&rtc_lock);
for( i = 0; i < NVRAM_BYTES; ++i )
contents[i] = nvram_read_int( i );
- restore_flags(flags);
+ spin_unlock_irq (&rtc_lock);
*eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size );
@@ -475,15 +477,13 @@ static char *gfx_types[] = {
static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len,
off_t *begin, off_t offset, int size )
{
- unsigned long flags;
int checksum;
int type;
- save_flags(flags);
- cli();
+ spin_lock_irq (&rtc_lock);
checksum = nvram_check_checksum_int();
- restore_flags(flags);
-
+ spin_unlock_irq (&rtc_lock);
+
PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " );
PRINT_PROC( "# floppies : %d\n",
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index f0b95fd0f..0bcb9eddc 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1115,26 +1115,26 @@ static int __init i2c_init(void)
extern int i2c_dev_init(void);
#endif
#ifdef CONFIG_I2C_ALGOBIT
- extern int algo_bit_init(void);
+ extern int i2c_algo_bit_init(void);
#endif
#ifdef CONFIG_I2C_BITLP
- extern int bitlp_init(void);
+ extern int i2c_bitlp_init(void);
#endif
#ifdef CONFIG_I2C_BITELV
- extern int bitelv_init(void);
+ extern int i2c_bitelv_init(void);
#endif
#ifdef CONFIG_I2C_BITVELLE
- extern int bitvelle_init(void);
+ extern int i2c_bitvelle_init(void);
#endif
#ifdef CONFIG_I2C_BITVIA
- extern int bitvia_init(void);
+ extern int i2c_bitvia_init(void);
#endif
#ifdef CONFIG_I2C_ALGOPCF
- extern int algo_pcf_init(void);
+ extern int i2c_algo_pcf_init(void);
#endif
#ifdef CONFIG_I2C_PCFISA
- extern int pcfisa_init(void);
+ extern int i2c_pcfisa_init(void);
#endif
/* This is needed for automatic patch generation: sensors code starts here */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 43838c6dd..88b3f8e4a 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -2858,13 +2858,16 @@ int __init ide_setup (char *s)
const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
const char max_hwif = '0' + (MAX_HWIFS - 1);
+
+ if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */
+ return 0; /* driver and not us */
+
if (strncmp(s,"ide",3) &&
strncmp(s,"idebus",6) &&
#ifdef CONFIG_BLK_DEV_VIA82CXXX
strncmp(s,"splitfifo",9) &&
#endif /* CONFIG_BLK_DEV_VIA82CXXX */
- strncmp(s,"hdxlun",6) &&
- (strncmp(s,"hd",2) && s[2] != '='))
+ strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0;
printk("ide_setup: %s", s);
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index c294323d1..7ed3785ff 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -1,8 +1,10 @@
/*
- * $Id: dmascc.c,v 1.3 1998/09/07 04:41:56 kudielka Exp $
+ * $Id: dmascc.c,v 1.27 2000/06/01 14:46:23 oe1kib Exp $
*
* Driver for high-speed SCC boards (those with DMA support)
- * Copyright (C) 1997 Klaus Kudielka
+ * Copyright (C) 1997-2000 Klaus Kudielka
+ *
+ * S5SCC/DMA support by Janko Koleznik S52HI
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,20 +19,22 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
*/
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/dmascc.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <linux/tqueue.h>
#include <linux/version.h>
@@ -40,68 +44,31 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/segment.h>
+#include <asm/uaccess.h>
#include <net/ax25.h>
#include "z8530.h"
-/* Linux 2.0 compatibility */
-
-#if LINUX_VERSION_CODE < 0x20100
-
-
-#define __init
-#define __initdata
-#define __initfunc(x) x
-
-#define MODULE_AUTHOR(x)
-#define MODULE_DESCRIPTION(x)
-#define MODULE_PARM(x,y)
-
-#define copy_to_user(x,y,z) memcpy_tofs(x,y,z)
-#define copy_from_user(x,y,z) memcpy_fromfs(x,y,z)
-#define test_and_set_bit(x,y) set_bit(x,y)
-#define register_netdevice(x) register_netdev(x)
-#define unregister_netdevice(x) unregister_netdev(x)
-#define dev_kfree_skb(x) dev_kfree_skb(x,FREE_WRITE)
-#define SET_DEV_INIT(x) (x=dmascc_dev_init)
-
-#define SHDLCE 0x01 /* WR15 */
-
-#define AUTOEOM 0x02 /* WR7' */
-#define RXFIFOH 0x08
-#define TXFIFOE 0x20
-
-static int dmascc_dev_init(struct net_device *dev)
-{
- return 0;
-}
-
-static void dev_init_buffers(struct net_device *dev)
-{
- int i;
-
- for (i = 0; i < DEV_NUMBUFFS; i++)
- skb_queue_head_init(&dev->buffs[i]);
-}
-
-
-#else
-
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-
-#define SET_DEV_INIT(x)
-
+/* Linux 2.2 and 2.3 compatibility */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14)
+#define net_device device
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
+#define netif_start_queue(dev) { dev->tbusy = 0; }
+#define netif_stop_queue(dev) { dev->tbusy = 1; }
+#define netif_wake_queue(dev) { dev->tbusy = 0; mark_bh(NET_BH); }
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47)
+#define netif_running(dev) (dev->flags & IFF_UP)
#endif
/* Number of buffers per channel */
-#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (2 recommended) */
-#define NUM_RX_BUF 2 /* NUM_RX_BUF >= 1 (2 recommended) */
-#define BUF_SIZE 2016
+#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (min. 2 recommended) */
+#define NUM_RX_BUF 6 /* NUM_RX_BUF >= 1 (min. 2 recommended) */
+#define BUF_SIZE 1576 /* BUF_SIZE >= mtu + hard_header_len */
/* Cards supported */
@@ -112,13 +79,18 @@ static void dev_init_buffers(struct net_device *dev)
0, 8, 3686400, 7372800 }
#define HW_TWIN { "Gracilis PackeTwin", 0x200, 0x10, 0x10, 32, \
0, 4, 6144000, 6144000 }
+#define HW_S5 { "S5SCC/DMA", 0x200, 0x10, 0x10, 32, \
+ 0, 8, 4915200, 9830400 }
+
+#define HARDWARE { HW_PI, HW_PI2, HW_TWIN, HW_S5 }
-#define HARDWARE { HW_PI, HW_PI2, HW_TWIN }
+#define TMR_0_HZ 25600 /* Frequency of timer 0 */
#define TYPE_PI 0
#define TYPE_PI2 1
#define TYPE_TWIN 2
-#define NUM_TYPES 3
+#define TYPE_S5 3
+#define NUM_TYPES 4
#define MAX_NUM_DEVS 32
@@ -188,16 +160,44 @@ static void dev_init_buffers(struct net_device *dev)
/* Status values */
-/* tx_state */
-#define TX_IDLE 0
-#define TX_OFF 1
-#define TX_TXDELAY 2
-#define TX_ACTIVE 3
-#define TX_SQDELAY 4
+#define IDLE 0
+#define TX_HEAD 1
+#define TX_DATA 2
+#define TX_PAUSE 3
+#define TX_TAIL 4
+#define RTS_OFF 5
+#define WAIT 6
+#define DCD_ON 7
+#define RX_ON 8
+#define DCD_OFF 9
+
+
+/* Ioctls */
+
+#define SIOCGSCCPARAM SIOCDEVPRIVATE
+#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1)
/* Data types */
+struct scc_param {
+ int pclk_hz; /* frequency of BRG input (don't change) */
+ int brg_tc; /* BRG terminal count; BRG disabled if < 0 */
+ int nrzi; /* 0 (nrz), 1 (nrzi) */
+ int clocks; /* see dmascc_cfg documentation */
+ int txdelay; /* [1/TMR_0_HZ] */
+ int txtimeout; /* [1/HZ] */
+ int txtail; /* [1/TMR_0_HZ] */
+ int waittime; /* [1/TMR_0_HZ] */
+ int slottime; /* [1/TMR_0_HZ] */
+ int persist; /* 1 ... 256 */
+ int dma; /* -1 (disable), 0, 1, 3 */
+ int txpause; /* [1/TMR_0_HZ] */
+ int rtsoff; /* [1/TMR_0_HZ] */
+ int dcdon; /* [1/TMR_0_HZ] */
+ int dcdoff; /* [1/TMR_0_HZ] */
+};
+
struct scc_hardware {
char *name;
int io_region;
@@ -211,10 +211,17 @@ struct scc_hardware {
};
struct scc_priv {
- struct enet_statistics stats;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+ char name[IFNAMSIZ];
+#endif
+ int type;
+ int chip;
+ struct net_device *dev;
struct scc_info *info;
+ struct net_device_stats stats;
int channel;
- int cmd, data, tmr;
+ int card_base, scc_cmd, scc_data;
+ int tmr_cnt, tmr_ctrl, tmr_mode;
struct scc_param param;
char rx_buf[NUM_RX_BUF][BUF_SIZE];
int rx_len[NUM_RX_BUF];
@@ -226,17 +233,13 @@ struct scc_priv {
int tx_len[NUM_TX_BUF];
int tx_ptr;
int tx_head, tx_tail, tx_count;
- int tx_sem, tx_state;
+ int state;
unsigned long tx_start;
- int status;
+ int rr0;
};
struct scc_info {
- int type;
- int chip;
- int open;
- int scc_base;
- int tmr_base;
+ int irq_used;
int twin_serial_cfg;
struct net_device dev[2];
struct scc_priv priv[2];
@@ -247,25 +250,33 @@ struct scc_info {
/* Function declarations */
int dmascc_init(void) __init;
-static int setup_adapter(int io, int h, int n) __init;
+static int setup_adapter(int card_base, int type, int n) __init;
+
+static void write_scc(struct scc_priv *priv, int reg, int val);
+static void write_scc_data(struct scc_priv *priv, int val, int fast);
+static int read_scc(struct scc_priv *priv, int reg);
+static int read_scc_data(struct scc_priv *priv);
-static inline void write_scc(int ctl, int reg, int val);
-static inline int read_scc(int ctl, int reg);
static int scc_open(struct net_device *dev);
static int scc_close(struct net_device *dev);
static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static int scc_send_packet(struct sk_buff *skb, struct net_device *dev);
-static struct enet_statistics *scc_get_stats(struct net_device *dev);
+static struct net_device_stats *scc_get_stats(struct net_device *dev);
static int scc_set_mac_address(struct net_device *dev, void *sa);
+
static void scc_isr(int irq, void *dev_id, struct pt_regs * regs);
static inline void z8530_isr(struct scc_info *info);
-static void rx_isr(struct net_device *dev);
-static void special_condition(struct net_device *dev, int rc);
+static void rx_isr(struct scc_priv *priv);
+static void special_condition(struct scc_priv *priv, int rc);
static void rx_bh(void *arg);
-static void tx_isr(struct net_device *dev);
-static void es_isr(struct net_device *dev);
-static void tm_isr(struct net_device *dev);
-static inline void delay(struct net_device *dev, int t);
+static void tx_isr(struct scc_priv *priv);
+static void es_isr(struct scc_priv *priv);
+static void tm_isr(struct scc_priv *priv);
+
+static inline void tx_on(struct scc_priv *priv);
+static inline void rx_on(struct scc_priv *priv);
+static inline void rx_off(struct scc_priv *priv);
+static void start_timer(struct scc_priv *priv, int t, int r15);
static inline unsigned char random(void);
@@ -287,7 +298,6 @@ static struct scc_info *first = NULL;
static unsigned long rand;
-
/* Module functions */
#ifdef MODULE
@@ -298,14 +308,12 @@ MODULE_DESCRIPTION("Driver for high-speed SCC boards");
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
-int init_module(void)
-{
+int init_module(void) {
return dmascc_init();
}
-void cleanup_module(void)
-{
+void cleanup_module(void) {
int i;
struct scc_info *info;
@@ -315,15 +323,17 @@ void cleanup_module(void)
/* Unregister devices */
for (i = 0; i < 2; i++) {
if (info->dev[i].name)
+ rtnl_lock();
unregister_netdevice(&info->dev[i]);
+ rtnl_unlock();
}
/* Reset board */
- if (info->type == TYPE_TWIN)
- outb_p(0, info->dev[0].base_addr + TWIN_SERIAL_CFG);
- write_scc(info->priv[0].cmd, R9, FHWRES);
+ if (info->priv[0].type == TYPE_TWIN)
+ outb(0, info->dev[0].base_addr + TWIN_SERIAL_CFG);
+ write_scc(&info->priv[0], R9, FHWRES);
release_region(info->dev[0].base_addr,
- hw[info->type].io_size);
+ hw[info->priv[0].type].io_size);
/* Free memory */
first = info->next;
@@ -335,8 +345,7 @@ void cleanup_module(void)
#else
-void __init dmascc_setup(char *str, int *ints)
-{
+void __init dmascc_setup(char *str, int *ints) {
int i;
for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
@@ -349,8 +358,7 @@ void __init dmascc_setup(char *str, int *ints)
/* Initialization functions */
-int __init dmascc_init(void)
-{
+int __init dmascc_init(void) {
int h, i, j, n;
int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
t1[MAX_NUM_DEVS];
@@ -402,18 +410,18 @@ int __init dmascc_init(void)
for (i = 0; i < hw[h].num_devs; i++)
if (base[i]) {
/* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
- outb_p(0x36, tcmd[i]);
- outb_p((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
- outb_p((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
+ outb(0x36, tcmd[i]);
+ outb((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
+ outb((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
/* Timer 1: LSB+MSB, Mode 0, HZ/10 */
- outb_p(0x70, tcmd[i]);
- outb_p((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
- outb_p((TMR_0_HZ/HZ*10) >> 8, t1[i]);
+ outb(0x70, tcmd[i]);
+ outb((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
+ outb((TMR_0_HZ/HZ*10) >> 8, t1[i]);
start[i] = jiffies;
delay[i] = 0;
counting[i] = 1;
/* Timer 2: LSB+MSB, Mode 0 */
- outb_p(0xb0, tcmd[i]);
+ outb(0xb0, tcmd[i]);
}
time = jiffies;
/* Wait until counter registers are loaded */
@@ -424,8 +432,8 @@ int __init dmascc_init(void)
for (i = 0; i < hw[h].num_devs; i++)
if (base[i] && counting[i]) {
/* Read back Timer 1: latch; read LSB; read MSB */
- outb_p(0x40, tcmd[i]);
- t_val = inb_p(t1[i]) + (inb_p(t1[i]) << 8);
+ outb(0x40, tcmd[i]);
+ t_val = inb(t1[i]) + (inb(t1[i]) << 8);
/* Also check whether counter did wrap */
if (t_val == 0 || t_val > TMR_0_HZ/HZ*10) counting[i] = 0;
delay[i] = jiffies - start[i];
@@ -452,31 +460,46 @@ int __init dmascc_init(void)
return -EIO;
}
-int __init setup_adapter(int io, int h, int n)
-{
+
+int __init setup_adapter(int card_base, int type, int n) {
int i, irq, chip;
struct scc_info *info;
struct net_device *dev;
struct scc_priv *priv;
unsigned long time;
unsigned int irqs;
- int tmr = io + hw[h].tmr_offset;
- int scc = io + hw[h].scc_offset;
- int cmd = scc + SCCA_CMD;
+ int tmr_base = card_base + hw[type].tmr_offset;
+ int scc_base = card_base + hw[type].scc_offset;
char *chipnames[] = CHIPNAMES;
- /* Reset 8530 */
- write_scc(cmd, R9, FHWRES | MIE | NV);
+ /* Allocate memory */
+ info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
+ if (!info) {
+ printk("dmascc: could not allocate memory for %s at %#3x\n",
+ hw[type].name, card_base);
+ return -1;
+ }
+
+ /* Initialize what is necessary for write_scc and write_scc_data */
+ memset(info, 0, sizeof(struct scc_info));
+ priv = &info->priv[0];
+ priv->type = type;
+ priv->card_base = card_base;
+ priv->scc_cmd = scc_base + SCCA_CMD;
+ priv->scc_data = scc_base + SCCA_DATA;
+
+ /* Reset SCC */
+ write_scc(priv, R9, FHWRES | MIE | NV);
/* Determine type of chip by enabling SDLC/HDLC enhancements */
- write_scc(cmd, R15, SHDLCE);
- if (!read_scc(cmd, R15)) {
+ write_scc(priv, R15, SHDLCE);
+ if (!read_scc(priv, R15)) {
/* WR7' not present. This is an ordinary Z8530 SCC. */
chip = Z8530;
} else {
/* Put one character in TX FIFO */
- write_scc(cmd, R8, 0);
- if (read_scc(cmd, R0) & Tx_BUF_EMP) {
+ write_scc_data(priv, 0, 0);
+ if (read_scc(priv, R0) & Tx_BUF_EMP) {
/* TX FIFO not full. This is a Z85230 ESCC with a 4-byte FIFO. */
chip = Z85230;
} else {
@@ -484,93 +507,76 @@ int __init setup_adapter(int io, int h, int n)
chip = Z85C30;
}
}
- write_scc(cmd, R15, 0);
+ write_scc(priv, R15, 0);
/* Start IRQ auto-detection */
sti();
irqs = probe_irq_on();
/* Enable interrupts */
- switch (h) {
- case TYPE_PI:
- case TYPE_PI2:
- outb_p(0, io + PI_DREQ_MASK);
- write_scc(cmd, R15, CTSIE);
- write_scc(cmd, R0, RES_EXT_INT);
- write_scc(cmd, R1, EXT_INT_ENAB);
- break;
- case TYPE_TWIN:
- outb_p(0, io + TWIN_DMA_CFG);
- inb_p(io + TWIN_CLR_TMR1);
- inb_p(io + TWIN_CLR_TMR2);
- outb_p(TWIN_EI, io + TWIN_SERIAL_CFG);
- break;
+ if (type == TYPE_TWIN) {
+ outb(0, card_base + TWIN_DMA_CFG);
+ inb(card_base + TWIN_CLR_TMR1);
+ inb(card_base + TWIN_CLR_TMR2);
+ outb((info->twin_serial_cfg = TWIN_EI), card_base + TWIN_SERIAL_CFG);
+ } else {
+ write_scc(priv, R15, CTSIE);
+ write_scc(priv, R0, RES_EXT_INT);
+ write_scc(priv, R1, EXT_INT_ENAB);
}
/* Start timer */
- outb_p(1, tmr + TMR_CNT1);
- outb_p(0, tmr + TMR_CNT1);
+ outb(1, tmr_base + TMR_CNT1);
+ outb(0, tmr_base + TMR_CNT1);
+
/* Wait and detect IRQ */
time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ);
irq = probe_irq_off(irqs);
/* Clear pending interrupt, disable interrupts */
- switch (h) {
- case TYPE_PI:
- case TYPE_PI2:
- write_scc(cmd, R1, 0);
- write_scc(cmd, R15, 0);
- write_scc(cmd, R0, RES_EXT_INT);
- break;
- case TYPE_TWIN:
- inb_p(io + TWIN_CLR_TMR1);
- outb_p(0, io + TWIN_SERIAL_CFG);
- break;
+ if (type == TYPE_TWIN) {
+ inb(card_base + TWIN_CLR_TMR1);
+ } else {
+ write_scc(priv, R1, 0);
+ write_scc(priv, R15, 0);
+ write_scc(priv, R0, RES_EXT_INT);
}
if (irq <= 0) {
printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n",
- hw[h].name, io, irq);
- return -1;
- }
-
- /* Allocate memory */
- info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
- if (!info) {
- printk("dmascc: could not allocate memory for %s at %#3x\n",
- hw[h].name, io);
+ hw[type].name, card_base, irq);
+ kfree_s(info, sizeof(struct scc_info));
return -1;
}
/* Set up data structures */
- memset(info, 0, sizeof(struct scc_info));
- info->type = h;
- info->chip = chip;
- info->scc_base = io + hw[h].scc_offset;
- info->tmr_base = io + hw[h].tmr_offset;
- info->twin_serial_cfg = 0;
for (i = 0; i < 2; i++) {
dev = &info->dev[i];
priv = &info->priv[i];
+ priv->type = type;
+ priv->chip = chip;
+ priv->dev = dev;
priv->info = info;
priv->channel = i;
- priv->cmd = info->scc_base + (i ? SCCB_CMD : SCCA_CMD);
- priv->data = info->scc_base + (i ? SCCB_DATA : SCCA_DATA);
- priv->tmr = info->tmr_base + (i ? TMR_CNT2 : TMR_CNT1);
- priv->param.pclk_hz = hw[h].pclk_hz;
+ priv->card_base = card_base;
+ priv->scc_cmd = scc_base + (i ? SCCB_CMD : SCCA_CMD);
+ priv->scc_data = scc_base + (i ? SCCB_DATA : SCCA_DATA);
+ priv->tmr_cnt = tmr_base + (i ? TMR_CNT2 : TMR_CNT1);
+ priv->tmr_ctrl = tmr_base + TMR_CTRL;
+ priv->tmr_mode = i ? 0xb0 : 0x70;
+ priv->param.pclk_hz = hw[type].pclk_hz;
priv->param.brg_tc = -1;
priv->param.clocks = TCTRxCP | RCRTxCP;
- priv->param.txdelay = TMR_0_HZ * 10 / 1000;
- priv->param.txtime = HZ * 3;
- priv->param.sqdelay = TMR_0_HZ * 1 / 1000;
- priv->param.slottime = TMR_0_HZ * 10 / 1000;
- priv->param.waittime = TMR_0_HZ * 100 / 1000;
- priv->param.persist = 32;
+ priv->param.persist = 256;
+ priv->param.dma = -1;
priv->rx_task.routine = rx_bh;
- priv->rx_task.data = dev;
+ priv->rx_task.data = priv;
dev->priv = priv;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+ if (sizeof(dev->name) == sizeof(char *)) dev->name = priv->name;
+#endif
sprintf(dev->name, "dmascc%i", 2*n+i);
- dev->base_addr = io;
+ dev->base_addr = card_base;
dev->irq = irq;
dev->open = scc_open;
dev->stop = scc_close;
@@ -580,7 +586,6 @@ int __init setup_adapter(int io, int h, int n)
dev->hard_header = ax25_encapsulate;
dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = scc_set_mac_address;
- SET_DEV_INIT(dev->init);
dev->type = ARPHRD_AX25;
dev->hard_header_len = 73;
dev->mtu = 1500;
@@ -589,203 +594,298 @@ int __init setup_adapter(int io, int h, int n)
memcpy(dev->broadcast, ax25_broadcast, 7);
memcpy(dev->dev_addr, ax25_test, 7);
dev_init_buffers(dev);
+ rtnl_lock();
if (register_netdevice(dev)) {
printk("dmascc: could not register %s\n", dev->name);
}
+ rtnl_unlock();
}
- request_region(io, hw[h].io_size, "dmascc");
+ request_region(card_base, hw[type].io_size, "dmascc");
info->next = first;
first = info;
- printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[h].name,
- chipnames[chip], io, irq);
+ printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name,
+ chipnames[chip], card_base, irq);
return 0;
}
/* Driver functions */
-static inline void write_scc(int ctl, int reg, int val)
-{
- outb_p(reg, ctl);
- outb_p(val, ctl);
+static void write_scc(struct scc_priv *priv, int reg, int val) {
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ if (reg) outb(reg, priv->scc_cmd);
+ outb(val, priv->scc_cmd);
+ return;
+ case TYPE_TWIN:
+ if (reg) outb_p(reg, priv->scc_cmd);
+ outb_p(val, priv->scc_cmd);
+ return;
+ default:
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ if (reg) outb_p(reg, priv->scc_cmd);
+ outb_p(val, priv->scc_cmd);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ return;
+ }
}
-static inline int read_scc(int ctl, int reg)
-{
- outb_p(reg, ctl);
- return inb_p(ctl);
+static void write_scc_data(struct scc_priv *priv, int val, int fast) {
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ outb(val, priv->scc_data);
+ return;
+ case TYPE_TWIN:
+ outb_p(val, priv->scc_data);
+ return;
+ default:
+ if (fast) outb_p(val, priv->scc_data);
+ else {
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ outb_p(val, priv->scc_data);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ }
+ return;
+ }
}
-static int scc_open(struct net_device *dev)
-{
+static int read_scc(struct scc_priv *priv, int reg) {
+ int rc;
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ if (reg) outb(reg, priv->scc_cmd);
+ return inb(priv->scc_cmd);
+ case TYPE_TWIN:
+ if (reg) outb_p(reg, priv->scc_cmd);
+ return inb_p(priv->scc_cmd);
+ default:
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ if (reg) outb_p(reg, priv->scc_cmd);
+ rc = inb_p(priv->scc_cmd);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ return rc;
+ }
+}
+
+
+static int read_scc_data(struct scc_priv *priv) {
+ int rc;
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ return inb(priv->scc_data);
+ case TYPE_TWIN:
+ return inb_p(priv->scc_data);
+ default:
+ save_flags(flags);
+ cli();
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ rc = inb_p(priv->scc_data);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ restore_flags(flags);
+ return rc;
+ }
+}
+
+
+static int scc_open(struct net_device *dev) {
struct scc_priv *priv = dev->priv;
struct scc_info *info = priv->info;
- int io = dev->base_addr;
- int cmd = priv->cmd;
+ int card_base = priv->card_base;
+
+ MOD_INC_USE_COUNT;
/* Request IRQ if not already used by other channel */
- if (!info->open) {
- if (request_irq(dev->irq, scc_isr, SA_INTERRUPT, "dmascc", info))
+ if (!info->irq_used) {
+ if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) {
+ MOD_DEC_USE_COUNT;
return -EAGAIN;
+ }
}
+ info->irq_used++;
/* Request DMA if required */
- if (dev->dma && request_dma(dev->dma, "dmascc")) {
- if (!info->open) free_irq(dev->irq, info);
- return -EAGAIN;
+ if (priv->param.dma >= 0) {
+ if (request_dma(priv->param.dma, "dmascc")) {
+ if (--info->irq_used == 0) free_irq(dev->irq, info);
+ MOD_DEC_USE_COUNT;
+ return -EAGAIN;
+ } else {
+ unsigned long flags = claim_dma_lock();
+ clear_dma_ff(priv->param.dma);
+ release_dma_lock(flags);
+ }
}
/* Initialize local variables */
priv->rx_ptr = 0;
priv->rx_over = 0;
priv->rx_head = priv->rx_tail = priv->rx_count = 0;
- priv->tx_state = TX_IDLE;
+ priv->state = IDLE;
priv->tx_head = priv->tx_tail = priv->tx_count = 0;
priv->tx_ptr = 0;
- priv->tx_sem = 0;
/* Reset channel */
- write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+ write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
/* X1 clock, SDLC mode */
- write_scc(cmd, R4, SDLC | X1CLK);
+ write_scc(priv, R4, SDLC | X1CLK);
/* DMA */
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
/* 8 bit RX char, RX disable */
- write_scc(cmd, R3, Rx8);
+ write_scc(priv, R3, Rx8);
/* 8 bit TX char, TX disable */
- write_scc(cmd, R5, Tx8);
+ write_scc(priv, R5, Tx8);
/* SDLC address field */
- write_scc(cmd, R6, 0);
+ write_scc(priv, R6, 0);
/* SDLC flag */
- write_scc(cmd, R7, FLAG);
- switch (info->chip) {
+ write_scc(priv, R7, FLAG);
+ switch (priv->chip) {
case Z85C30:
/* Select WR7' */
- write_scc(cmd, R15, SHDLCE);
+ write_scc(priv, R15, SHDLCE);
/* Auto EOM reset */
- write_scc(cmd, R7, AUTOEOM);
- write_scc(cmd, R15, 0);
+ write_scc(priv, R7, AUTOEOM);
+ write_scc(priv, R15, 0);
break;
case Z85230:
/* Select WR7' */
- write_scc(cmd, R15, SHDLCE);
- /* RX FIFO half full (interrupt only), Auto EOM reset,
- TX FIFO empty (DMA only) */
- write_scc(cmd, R7, AUTOEOM | (dev->dma ? TXFIFOE : RXFIFOH));
- write_scc(cmd, R15, 0);
+ write_scc(priv, R15, SHDLCE);
+ /* The following bits are set (see 2.5.2.1):
+ - Automatic EOM reset
+ - Interrupt request if RX FIFO is half full
+ This bit should be ignored in DMA mode (according to the
+ documentation), but actually isn't. The receiver doesn't work if
+ it is set. Thus, we have to clear it in DMA mode.
+ - Interrupt/DMA request if TX FIFO is completely empty
+ a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30
+ compatibility).
+ b) If cleared, DMA requests may follow each other very quickly,
+ filling up the TX FIFO.
+ Advantage: TX works even in case of high bus latency.
+ Disadvantage: Edge-triggered DMA request circuitry may miss
+ a request. No more data is delivered, resulting
+ in a TX FIFO underrun.
+ Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared.
+ The PackeTwin doesn't. I don't know about the PI, but let's
+ assume it behaves like the PI2.
+ */
+ if (priv->param.dma >= 0) {
+ if (priv->type == TYPE_TWIN) write_scc(priv, R7, AUTOEOM | TXFIFOE);
+ else write_scc(priv, R7, AUTOEOM);
+ } else {
+ write_scc(priv, R7, AUTOEOM | RXFIFOH);
+ }
+ write_scc(priv, R15, 0);
break;
}
/* Preset CRC, NRZ(I) encoding */
- write_scc(cmd, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
+ write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
/* Configure baud rate generator */
if (priv->param.brg_tc >= 0) {
/* Program BR generator */
- write_scc(cmd, R12, priv->param.brg_tc & 0xFF);
- write_scc(cmd, R13, (priv->param.brg_tc>>8) & 0xFF);
+ write_scc(priv, R12, priv->param.brg_tc & 0xFF);
+ write_scc(priv, R13, (priv->param.brg_tc>>8) & 0xFF);
/* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
PackeTwin, not connected on the PI2); set DPLL source to BRG */
- write_scc(cmd, R14, SSBR | DTRREQ | BRSRC | BRENABL);
+ write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL);
/* Enable DPLL */
- write_scc(cmd, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
+ write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
} else {
/* Disable BR generator */
- write_scc(cmd, R14, DTRREQ | BRSRC);
+ write_scc(priv, R14, DTRREQ | BRSRC);
}
/* Configure clocks */
- if (info->type == TYPE_TWIN) {
+ if (priv->type == TYPE_TWIN) {
/* Disable external TX clock receiver */
- outb_p((info->twin_serial_cfg &=
+ outb((info->twin_serial_cfg &=
~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
- io + TWIN_SERIAL_CFG);
+ card_base + TWIN_SERIAL_CFG);
}
- write_scc(cmd, R11, priv->param.clocks);
- if ((info->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
+ write_scc(priv, R11, priv->param.clocks);
+ if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
/* Enable external TX clock receiver */
- outb_p((info->twin_serial_cfg |=
+ outb((info->twin_serial_cfg |=
(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
- io + TWIN_SERIAL_CFG);
+ card_base + TWIN_SERIAL_CFG);
}
/* Configure PackeTwin */
- if (info->type == TYPE_TWIN) {
+ if (priv->type == TYPE_TWIN) {
/* Assert DTR, enable interrupts */
- outb_p((info->twin_serial_cfg |= TWIN_EI |
+ outb((info->twin_serial_cfg |= TWIN_EI |
(priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
- io + TWIN_SERIAL_CFG);
+ card_base + TWIN_SERIAL_CFG);
}
/* Read current status */
- priv->status = read_scc(cmd, R0);
- /* Enable SYNC, DCD, and CTS interrupts */
- write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
-
- /* Configure PI2 DMA */
- if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK);
+ priv->rr0 = read_scc(priv, R0);
+ /* Enable DCD interrupt */
+ write_scc(priv, R15, DCDIE);
netif_start_queue(dev);
- info->open++;
- MOD_INC_USE_COUNT;
return 0;
}
-static int scc_close(struct net_device *dev)
-{
+static int scc_close(struct net_device *dev) {
struct scc_priv *priv = dev->priv;
struct scc_info *info = priv->info;
- int io = dev->base_addr;
- int cmd = priv->cmd;
+ int card_base = priv->card_base;
netif_stop_queue(dev);
- info->open--;
- if (info->type == TYPE_TWIN)
+ if (priv->type == TYPE_TWIN) {
/* Drop DTR */
- outb_p((info->twin_serial_cfg &=
+ outb((info->twin_serial_cfg &=
(priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
- io + TWIN_SERIAL_CFG);
-
- /* Reset channel, free DMA */
- write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
- if (dev->dma) {
- if (info->type == TYPE_TWIN) outb_p(0, io + TWIN_DMA_CFG);
- free_dma(dev->dma);
+ card_base + TWIN_SERIAL_CFG);
}
- if (!info->open) {
- if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK);
- free_irq(dev->irq, info);
+ /* Reset channel, free DMA and IRQ */
+ write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+ if (priv->param.dma >= 0) {
+ if (priv->type == TYPE_TWIN) outb(0, card_base + TWIN_DMA_CFG);
+ free_dma(priv->param.dma);
}
+ if (--info->irq_used == 0) free_irq(dev->irq, info);
+
MOD_DEC_USE_COUNT;
return 0;
}
-static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- int rc;
+static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
struct scc_priv *priv = dev->priv;
switch (cmd) {
case SIOCGSCCPARAM:
- if(copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
- return -EFAULT;
+ if (copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
+ return -EFAULT;
return 0;
case SIOCSSCCPARAM:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (netif_running(dev))
- return -EAGAIN;
- if(copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
- return -EFAULT;
- dev->dma = priv->param.dma;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (netif_running(dev)) return -EAGAIN;
+ if (copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
+ return -EFAULT;
return 0;
default:
return -EINVAL;
@@ -793,165 +893,150 @@ static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
-static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
+static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) {
struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int cmd = priv->cmd;
unsigned long flags;
int i;
- /* Block a timer-based transmit from overlapping */
+ /* Temporarily stop the scheduler feeding us packets */
netif_stop_queue(dev);
-
+
/* Transfer data to DMA buffer */
i = priv->tx_head;
memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
priv->tx_len[i] = skb->len-1;
+ /* Clear interrupts while we touch our circular buffers */
save_flags(flags);
cli();
- /* Set the busy flag if we just filled up the last buffer */
+ /* Move the ring buffer's head */
priv->tx_head = (i + 1) % NUM_TX_BUF;
priv->tx_count++;
- if (priv->tx_count != NUM_TX_BUF)
- netif_wake_queue(dev);
+
+ /* If we just filled up the last buffer, leave queue stopped.
+ The higher layers must wait until we have a DMA buffer
+ to accept the data. */
+ if (priv->tx_count < NUM_TX_BUF) netif_wake_queue(dev);
/* Set new TX state */
- if (priv->tx_state == TX_IDLE) {
+ if (priv->state == IDLE) {
/* Assert RTS, start timer */
- priv->tx_state = TX_TXDELAY;
- if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
- write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
+ priv->state = TX_HEAD;
priv->tx_start = jiffies;
- delay(dev, priv->param.txdelay);
+ write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.txdelay, 0);
}
+ /* Turn interrupts back on and free buffer */
restore_flags(flags);
-
dev_kfree_skb(skb);
- priv->tx_sem = 0;
return 0;
}
-static struct enet_statistics *scc_get_stats(struct net_device *dev)
-{
+static struct net_device_stats *scc_get_stats(struct net_device *dev) {
struct scc_priv *priv = dev->priv;
return &priv->stats;
}
-static int scc_set_mac_address(struct net_device *dev, void *sa)
-{
+static int scc_set_mac_address(struct net_device *dev, void *sa) {
memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len);
return 0;
}
-static void scc_isr(int irq, void *dev_id, struct pt_regs * regs)
-{
+static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
struct scc_info *info = dev_id;
- int is, io = info->dev[0].base_addr;
- /* We're a fast IRQ handler and are called with interrupts disabled */
+ /* At this point interrupts are enabled, and the interrupt under service
+ is already acknowledged, but masked off.
- /* IRQ sharing doesn't make sense due to ISA's edge-triggered
- interrupts, hence it is safe to return if we have found and
- processed a single device. */
-
- /* Interrupt processing: We loop until we know that the IRQ line is
+ Interrupt processing: We loop until we know that the IRQ line is
low. If another positive edge occurs afterwards during the ISR,
another interrupt will be triggered by the interrupt controller
- as soon as the IRQ level is enabled again (see asm/irq.h). */
-
- switch (info->type) {
- case TYPE_PI:
- case TYPE_PI2:
- outb_p(0, io + PI_DREQ_MASK);
- z8530_isr(info);
- outb_p(1, io + PI_DREQ_MASK);
- return;
- case TYPE_TWIN:
- while ((is = ~inb_p(io + TWIN_INT_REG)) &
+ as soon as the IRQ level is enabled again (see asm/irq.h).
+
+ Bottom-half handlers will be processed after scc_isr(). This is
+ important, since we only have small ringbuffers and want new data
+ to be fetched/delivered immediately. */
+
+ if (info->priv[0].type == TYPE_TWIN) {
+ int is, card_base = info->priv[0].card_base;
+ while ((is = ~inb(card_base + TWIN_INT_REG)) &
TWIN_INT_MSK) {
if (is & TWIN_SCC_MSK) {
z8530_isr(info);
} else if (is & TWIN_TMR1_MSK) {
- inb_p(io + TWIN_CLR_TMR1);
- tm_isr(&info->dev[0]);
+ inb(card_base + TWIN_CLR_TMR1);
+ tm_isr(&info->priv[0]);
} else {
- inb_p(io + TWIN_CLR_TMR2);
- tm_isr(&info->dev[1]);
+ inb(card_base + TWIN_CLR_TMR2);
+ tm_isr(&info->priv[1]);
}
}
- /* No interrupts pending from the PackeTwin */
- return;
- }
+ } else z8530_isr(info);
}
-static inline void z8530_isr(struct scc_info *info)
-{
- int is, a_cmd;
-
- a_cmd = info->scc_base + SCCA_CMD;
+static inline void z8530_isr(struct scc_info *info) {
+ int is, i = 100;
- while ((is = read_scc(a_cmd, R3))) {
+ while ((is = read_scc(&info->priv[0], R3)) && i--) {
if (is & CHARxIP) {
- rx_isr(&info->dev[0]);
+ rx_isr(&info->priv[0]);
} else if (is & CHATxIP) {
- tx_isr(&info->dev[0]);
+ tx_isr(&info->priv[0]);
} else if (is & CHAEXT) {
- es_isr(&info->dev[0]);
+ es_isr(&info->priv[0]);
} else if (is & CHBRxIP) {
- rx_isr(&info->dev[1]);
+ rx_isr(&info->priv[1]);
} else if (is & CHBTxIP) {
- tx_isr(&info->dev[1]);
+ tx_isr(&info->priv[1]);
} else {
- es_isr(&info->dev[1]);
+ es_isr(&info->priv[1]);
}
+ write_scc(&info->priv[0], R0, RES_H_IUS);
+ i++;
+ }
+ if (i < 0) {
+ printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is);
}
/* Ok, no interrupts pending from this 8530. The INT line should
be inactive now. */
}
-static void rx_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- int cmd = priv->cmd;
-
- if (dev->dma) {
+static void rx_isr(struct scc_priv *priv) {
+ if (priv->param.dma >= 0) {
/* Check special condition and perform error reset. See 2.4.7.5. */
- special_condition(dev, read_scc(cmd, R1));
- write_scc(cmd, R0, ERR_RES);
+ special_condition(priv, read_scc(priv, R1));
+ write_scc(priv, R0, ERR_RES);
} else {
/* Check special condition for each character. Error reset not necessary.
Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
int rc;
- while (read_scc(cmd, R0) & Rx_CH_AV) {
- rc = read_scc(cmd, R1);
+ while (read_scc(priv, R0) & Rx_CH_AV) {
+ rc = read_scc(priv, R1);
if (priv->rx_ptr < BUF_SIZE)
- priv->rx_buf[priv->rx_head][priv->rx_ptr++] = read_scc(cmd, R8);
+ priv->rx_buf[priv->rx_head][priv->rx_ptr++] =
+ read_scc_data(priv);
else {
priv->rx_over = 2;
- read_scc(cmd, R8);
+ read_scc_data(priv);
}
- special_condition(dev, rc);
+ special_condition(priv, rc);
}
}
}
-static void special_condition(struct net_device *dev, int rc)
-{
- struct scc_priv *priv = dev->priv;
- int cb, cmd = priv->cmd;
+static void special_condition(struct scc_priv *priv, int rc) {
+ int cb;
unsigned long flags;
/* See Figure 2-15. Only overrun and EOF need to be checked. */
@@ -959,18 +1044,15 @@ static void special_condition(struct net_device *dev, int rc)
if (rc & Rx_OVR) {
/* Receiver overrun */
priv->rx_over = 1;
- if (!dev->dma) write_scc(cmd, R0, ERR_RES);
+ if (priv->param.dma < 0) write_scc(priv, R0, ERR_RES);
} else if (rc & END_FR) {
/* End of frame. Get byte count */
- if (dev->dma) {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- cb = BUF_SIZE - get_dma_residue(dev->dma) - 2;
- release_dma_lock(flags);
-
+ if (priv->param.dma >= 0) {
+ flags = claim_dma_lock();
+ cb = BUF_SIZE - get_dma_residue(priv->param.dma) - 2;
+ release_dma_lock(flags);
} else {
- cb = priv->rx_ptr - 2;
+ cb = priv->rx_ptr - 2;
}
if (priv->rx_over) {
/* We had an overrun */
@@ -980,36 +1062,32 @@ static void special_condition(struct net_device *dev, int rc)
priv->rx_over = 0;
} else if (rc & CRC_ERR) {
/* Count invalid CRC only if packet length >= minimum */
- if (cb >= 8) {
+ if (cb >= 15) {
priv->stats.rx_errors++;
priv->stats.rx_crc_errors++;
}
} else {
- if (cb >= 8) {
- /* Put good frame in FIFO */
- priv->rx_len[priv->rx_head] = cb;
- priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
- priv->rx_count++;
- if (priv->rx_count == NUM_RX_BUF) {
- /* Disable receiver if FIFO full */
- write_scc(cmd, R3, Rx8);
+ if (cb >= 15) {
+ if (priv->rx_count < NUM_RX_BUF - 1) {
+ /* Put good frame in FIFO */
+ priv->rx_len[priv->rx_head] = cb;
+ priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
+ priv->rx_count++;
+ /* Mark bottom half handler */
+ queue_task(&priv->rx_task, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ } else {
priv->stats.rx_errors++;
priv->stats.rx_over_errors++;
}
- /* Mark bottom half handler */
- queue_task(&priv->rx_task, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
}
}
/* Get ready for new frame */
- if (dev->dma) {
-
- flags=claim_dma_lock();
- set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(dev->dma, BUF_SIZE);
- enable_dma(dev->dma);
+ if (priv->param.dma >= 0) {
+ flags = claim_dma_lock();
+ set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+ set_dma_count(priv->param.dma, BUF_SIZE);
release_dma_lock(flags);
-
} else {
priv->rx_ptr = 0;
}
@@ -1017,12 +1095,8 @@ static void special_condition(struct net_device *dev, int rc)
}
-static void rx_bh(void *arg)
-{
- struct net_device *dev = arg;
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int cmd = priv->cmd;
+static void rx_bh(void *arg) {
+ struct scc_priv *priv = arg;
int i = priv->rx_tail;
int cb;
unsigned long flags;
@@ -1045,20 +1119,15 @@ static void rx_bh(void *arg)
data = skb_put(skb, cb+1);
data[0] = 0;
memcpy(&data[1], priv->rx_buf[i], cb);
- skb->dev = dev;
+ skb->dev = priv->dev;
skb->protocol = ntohs(ETH_P_AX25);
skb->mac.raw = skb->data;
netif_rx(skb);
priv->stats.rx_packets++;
+ priv->stats.rx_bytes += cb;
}
save_flags(flags);
cli();
- /* Enable receiver if RX buffers have been unavailable */
- if ((priv->rx_count == NUM_RX_BUF) && (priv->status & DCD)) {
- if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
- write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
- if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
- }
/* Move tail */
priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
priv->rx_count--;
@@ -1068,265 +1137,277 @@ static void rx_bh(void *arg)
}
-static void tx_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- int cmd = priv->cmd;
+static void tx_isr(struct scc_priv *priv) {
int i = priv->tx_tail, p = priv->tx_ptr;
/* Suspend TX interrupts if we don't want to send anything.
See Figure 2-22. */
if (p == priv->tx_len[i]) {
- write_scc(cmd, R0, RES_Tx_P);
+ write_scc(priv, R0, RES_Tx_P);
return;
}
/* Write characters */
- while ((read_scc(cmd, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
- write_scc(cmd, R8, priv->tx_buf[i][p++]);
+ while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
+ write_scc_data(priv, priv->tx_buf[i][p++], 0);
}
- priv->tx_ptr = p;
+ /* Reset EOM latch of Z8530 */
+ if (!priv->tx_ptr && p && priv->chip == Z8530)
+ write_scc(priv, R0, RES_EOM_L);
+
+ priv->tx_ptr = p;
}
-static void es_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int i, cmd = priv->cmd;
- int st, dst, res;
+static void es_isr(struct scc_priv *priv) {
+ int i, rr0, drr0, res;
unsigned long flags;
- /* Read status and reset interrupt bit */
- st = read_scc(cmd, R0);
- write_scc(cmd, R0, RES_EXT_INT);
- dst = priv->status ^ st;
- priv->status = st;
-
- /* Since the EOM latch is reset automatically, we assume that
- it has been zero if and only if we are in the TX_ACTIVE state.
- Otherwise we follow 2.4.9.6. */
+ /* Read status, reset interrupt bit (open latches) */
+ rr0 = read_scc(priv, R0);
+ write_scc(priv, R0, RES_EXT_INT);
+ drr0 = priv->rr0 ^ rr0;
+ priv->rr0 = rr0;
- /* Transmit underrun */
- if ((priv->tx_state == TX_ACTIVE) && (st & TxEOM)) {
+ /* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since
+ it might have already been cleared again by AUTOEOM. */
+ if (priv->state == TX_DATA) {
/* Get remaining bytes */
i = priv->tx_tail;
- if (dev->dma) {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- res = get_dma_residue(dev->dma);
+ if (priv->param.dma >= 0) {
+ disable_dma(priv->param.dma);
+ flags = claim_dma_lock();
+ res = get_dma_residue(priv->param.dma);
release_dma_lock(flags);
} else {
res = priv->tx_len[i] - priv->tx_ptr;
- if (res) write_scc(cmd, R0, RES_Tx_P);
priv->tx_ptr = 0;
}
- /* Remove frame from FIFO */
- priv->tx_tail = (i + 1) % NUM_TX_BUF;
- priv->tx_count--;
- /* Check if another frame is available and we are allowed to transmit */
- if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) {
- if (dev->dma) {
- flags=claim_dma_lock();
- set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
- set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
- enable_dma(dev->dma);
- release_dma_lock(flags);
- } else {
- /* If we have an ESCC, we are allowed to write data bytes
- immediately. Otherwise we have to wait for the next
- TX interrupt. See Figure 2-22. */
- if (info->chip == Z85230) {
- tx_isr(dev);
- }
- }
- } else {
- /* No frame available. Disable interrupts. */
- priv->tx_state = TX_SQDELAY;
- delay(dev, priv->param.sqdelay);
- write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
- }
- /* Update packet statistics */
+ /* Disable DREQ / TX interrupt */
+ if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+ outb(0, priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
if (res) {
+ /* Update packet statistics */
priv->stats.tx_errors++;
priv->stats.tx_fifo_errors++;
+ /* Other underrun interrupts may already be waiting */
+ write_scc(priv, R0, RES_EXT_INT);
+ write_scc(priv, R0, RES_EXT_INT);
} else {
+ /* Update packet statistics */
priv->stats.tx_packets++;
+ priv->stats.tx_bytes += priv->tx_len[i];
+ /* Remove frame from FIFO */
+ priv->tx_tail = (i + 1) % NUM_TX_BUF;
+ priv->tx_count--;
+ /* Inform upper layers */
+ netif_wake_queue(priv->dev);
+ }
+ /* Switch state */
+ write_scc(priv, R15, 0);
+ if (priv->tx_count &&
+ (jiffies - priv->tx_start) < priv->param.txtimeout) {
+ priv->state = TX_PAUSE;
+ start_timer(priv, priv->param.txpause, 0);
+ } else {
+ priv->state = TX_TAIL;
+ start_timer(priv, priv->param.txtail, 0);
}
- /* Inform upper layers */
- netif_wake_queue(dev);
}
/* DCD transition */
- if ((priv->tx_state < TX_TXDELAY) && (dst & DCD)) {
- /* Transmitter state change */
- priv->tx_state = TX_OFF;
- /* Enable or disable receiver */
- if (st & DCD) {
- if (dev->dma) {
- /* Program DMA controller */
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_mode(dev->dma, DMA_MODE_READ);
- set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(dev->dma, BUF_SIZE);
- enable_dma(dev->dma);
- release_dma_lock(flags);
- /* Configure PackeTwin DMA */
- if (info->type == TYPE_TWIN) {
- outb_p((dev->dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
- dev->base_addr + TWIN_DMA_CFG);
- }
- /* Sp. cond. intr. only, ext int enable */
- write_scc(cmd, R1, EXT_INT_ENAB | INT_ERR_Rx |
- WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
- } else {
- /* Intr. on all Rx characters and Sp. cond., ext int enable */
- write_scc(cmd, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
- WT_FN_RDYFN);
- }
- if (priv->rx_count < NUM_RX_BUF) {
- /* Enable receiver */
- write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+ if (drr0 & DCD) {
+ if (rr0 & DCD) {
+ switch (priv->state) {
+ case IDLE:
+ case WAIT:
+ priv->state = DCD_ON;
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.dcdon, 0);
}
} else {
- /* Disable DMA */
- if (dev->dma)
- {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- release_dma_lock(flags);
- }
- /* Disable receiver */
- write_scc(cmd, R3, Rx8);
- /* DMA disable, RX int disable, Ext int enable */
- write_scc(cmd, R1, EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN);
- /* Transmitter state change */
- if (random() > priv->param.persist)
- delay(dev, priv->param.slottime);
- else {
- if (priv->tx_count) {
- priv->tx_state = TX_TXDELAY;
- write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- priv->tx_start = jiffies;
- delay(dev, priv->param.txdelay);
- } else {
- priv->tx_state = TX_IDLE;
- }
+ switch (priv->state) {
+ case RX_ON:
+ rx_off(priv);
+ priv->state = DCD_OFF;
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.dcdoff, 0);
}
}
}
/* CTS transition */
- if ((info->type <= TYPE_PI2) && (dst & CTS) && (~st & CTS)) {
- /* Timer has expired */
- tm_isr(dev);
- }
+ if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN)
+ tm_isr(priv);
- /* /SYNC/HUNT transition */
- if ((dst & SYNC_HUNT) && (~st & SYNC_HUNT)) {
- /* Reset current frame and clear RX FIFO */
- while (read_scc(cmd, R0) & Rx_CH_AV) read_scc(cmd, R8);
- priv->rx_over = 0;
- if (dev->dma) {
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(dev->dma, BUF_SIZE);
- enable_dma(dev->dma);
- release_dma_lock(flags);
+}
+
+
+static void tm_isr(struct scc_priv *priv) {
+ switch (priv->state) {
+ case TX_HEAD:
+ case TX_PAUSE:
+ tx_on(priv);
+ priv->state = TX_DATA;
+ break;
+ case TX_TAIL:
+ write_scc(priv, R5, TxCRC_ENAB | Tx8);
+ priv->state = RTS_OFF;
+ if (priv->type != TYPE_TWIN) write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.rtsoff, 0);
+ break;
+ case RTS_OFF:
+ write_scc(priv, R15, DCDIE);
+ priv->rr0 = read_scc(priv, R0);
+ if (priv->rr0 & DCD) {
+ priv->stats.collisions++;
+ rx_on(priv);
+ priv->state = RX_ON;
} else {
- priv->rx_ptr = 0;
+ priv->state = WAIT;
+ start_timer(priv, priv->param.waittime, DCDIE);
+ }
+ break;
+ case WAIT:
+ if (priv->tx_count) {
+ priv->state = TX_HEAD;
+ priv->tx_start = jiffies;
+ write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.txdelay, 0);
+ } else {
+ priv->state = IDLE;
+ if (priv->type != TYPE_TWIN) write_scc(priv, R15, DCDIE);
}
+ break;
+ case DCD_ON:
+ case DCD_OFF:
+ write_scc(priv, R15, DCDIE);
+ priv->rr0 = read_scc(priv, R0);
+ if (priv->rr0 & DCD) {
+ rx_on(priv);
+ priv->state = RX_ON;
+ } else {
+ priv->state = WAIT;
+ start_timer(priv,
+ random()/priv->param.persist*priv->param.slottime,
+ DCDIE);
+ }
+ break;
}
}
-static void tm_isr(struct net_device *dev)
-{
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int cmd = priv->cmd;
+static inline void tx_on(struct scc_priv *priv) {
+ int i, n;
unsigned long flags;
- switch (priv->tx_state) {
- case TX_OFF:
- if (~priv->status & DCD) {
- if (random() > priv->param.persist) delay(dev, priv->param.slottime);
- else {
- if (priv->tx_count) {
- priv->tx_state = TX_TXDELAY;
- write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- priv->tx_start = jiffies;
- delay(dev, priv->param.txdelay);
- } else {
- priv->tx_state = TX_IDLE;
- }
- }
- }
- break;
- case TX_TXDELAY:
- priv->tx_state = TX_ACTIVE;
- if (dev->dma) {
- /* Program DMA controller */
-
- flags=claim_dma_lock();
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_mode(dev->dma, DMA_MODE_WRITE);
- set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
- set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
- enable_dma(dev->dma);
- release_dma_lock(flags);
-
- /* Configure PackeTwin DMA */
- if (info->type == TYPE_TWIN) {
- outb_p((dev->dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
- dev->base_addr + TWIN_DMA_CFG);
- }
- /* Enable interrupts and DMA. On the PackeTwin, the DTR//REQ pin
- is used for TX DMA requests, but we enable the WAIT/DMA request
- pin, anyway */
- write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
- } else {
- write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
- write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
- tx_isr(dev);
+ if (priv->param.dma >= 0) {
+ n = (priv->chip == Z85230) ? 3 : 1;
+ /* Program DMA controller */
+ flags = claim_dma_lock();
+ set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+ set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
+ set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
+ release_dma_lock(flags);
+ /* Enable TX underrun interrupt */
+ write_scc(priv, R15, TxUIE);
+ /* Configure DREQ */
+ if (priv->type == TYPE_TWIN)
+ outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+ priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
+ /* Write first byte(s) */
+ save_flags(flags);
+ cli();
+ for (i = 0; i < n; i++)
+ write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
+ enable_dma(priv->param.dma);
+ restore_flags(flags);
+ } else {
+ write_scc(priv, R15, TxUIE);
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+ tx_isr(priv);
+ }
+ /* Reset EOM latch if we do not have the AUTOEOM feature */
+ if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
+}
+
+
+static inline void rx_on(struct scc_priv *priv) {
+ unsigned long flags;
+
+ /* Clear RX FIFO */
+ while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
+ priv->rx_over = 0;
+ if (priv->param.dma >= 0) {
+ /* Program DMA controller */
+ flags = claim_dma_lock();
+ set_dma_mode(priv->param.dma, DMA_MODE_READ);
+ set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+ set_dma_count(priv->param.dma, BUF_SIZE);
+ release_dma_lock(flags);
+ enable_dma(priv->param.dma);
+ /* Configure PackeTwin DMA */
+ if (priv->type == TYPE_TWIN) {
+ outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+ priv->card_base + TWIN_DMA_CFG);
}
- if (info->chip == Z8530) write_scc(cmd, R0, RES_EOM_L);
- break;
- case TX_SQDELAY:
- /* Disable transmitter */
- write_scc(cmd, R5, TxCRC_ENAB | Tx8);
- /* Transmitter state change: Switch to TX_OFF and wait at least
- 1 slottime. */
- priv->tx_state = TX_OFF;
- if (~priv->status & DCD) delay(dev, priv->param.waittime);
+ /* Sp. cond. intr. only, ext int enable, RX DMA enable */
+ write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+ WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+ } else {
+ /* Reset current frame */
+ priv->rx_ptr = 0;
+ /* Intr. on all Rx characters and Sp. cond., ext int enable */
+ write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+ WT_FN_RDYFN);
}
+ write_scc(priv, R0, ERR_RES);
+ write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
}
-static inline void delay(struct net_device *dev, int t)
-{
- struct scc_priv *priv = dev->priv;
- int tmr = priv->tmr;
+static inline void rx_off(struct scc_priv *priv) {
+ /* Disable receiver */
+ write_scc(priv, R3, Rx8);
+ /* Disable DREQ / RX interrupt */
+ if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+ outb(0, priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+ /* Disable DMA */
+ if (priv->param.dma >= 0) disable_dma(priv->param.dma);
+}
+
+
+static void start_timer(struct scc_priv *priv, int t, int r15) {
+ unsigned long flags;
- outb_p(t & 0xFF, tmr);
- outb_p((t >> 8) & 0xFF, tmr);
+ outb(priv->tmr_mode, priv->tmr_ctrl);
+ if (t == 0) {
+ tm_isr(priv);
+ } else if (t > 0) {
+ save_flags(flags);
+ cli();
+ outb(t & 0xFF, priv->tmr_cnt);
+ outb((t >> 8) & 0xFF, priv->tmr_cnt);
+ if (priv->type != TYPE_TWIN) {
+ write_scc(priv, R15, r15 | CTSIE);
+ priv->rr0 |= CTS;
+ }
+ restore_flags(flags);
+ }
}
-static inline unsigned char random(void)
-{
+static inline unsigned char random(void) {
/* See "Numerical Recipes in C", second edition, p. 284 */
rand = rand * 1664525L + 1013904223L;
return (unsigned char) (rand >> 24);
}
-
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index cf3512043..0770f4448 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -75,9 +75,9 @@
#undef DEBUG
#ifdef DEBUG
-#define DBG(x) printk(KERN_DEBUG "aty128fb: %s\n",(x));
+#define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __FUNCTION__, ##args);
#else
-#define DBG(x)
+#define DBG(fmt, args...)
#endif
#ifndef CONFIG_PPC
@@ -104,10 +104,20 @@ static struct fb_var_screeninfo default_var = {
#ifndef MODULE
/* default modedb mode */
+/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
static struct fb_videomode defaultmode __initdata = {
- /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
- NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2,
- 0, FB_VMODE_NONINTERLACED
+ refresh: 60,
+ xres: 640,
+ yres: 480,
+ pixclock: 39722,
+ left_margin: 48,
+ right_margin: 16,
+ upper_margin: 33,
+ lower_margin: 10,
+ hsync_len: 96,
+ vsync_len: 2,
+ sync: 0,
+ vmode: FB_VMODE_NONINTERLACED
};
#endif /* MODULE */
@@ -141,32 +151,30 @@ static const struct aty128_chip_info aty128_pci_probe_list[] __initdata =
/* packed BIOS settings */
#ifndef CONFIG_PPC
-#pragma pack(1)
typedef struct {
- u8 clock_chip_type;
- u8 struct_size;
- u8 accelerator_entry;
- u8 VGA_entry;
- u16 VGA_table_offset;
- u16 POST_table_offset;
- u16 XCLK;
- u16 MCLK;
- u8 num_PLL_blocks;
- u8 size_PLL_blocks;
- u16 PCLK_ref_freq;
- u16 PCLK_ref_divider;
- u32 PCLK_min_freq;
- u32 PCLK_max_freq;
- u16 MCLK_ref_freq;
- u16 MCLK_ref_divider;
- u32 MCLK_min_freq;
- u32 MCLK_max_freq;
- u16 XCLK_ref_freq;
- u16 XCLK_ref_divider;
- u32 XCLK_min_freq;
- u32 XCLK_max_freq;
-} PLL_BLOCK;
-#pragma pack()
+ u8 clock_chip_type;
+ u8 struct_size;
+ u8 accelerator_entry;
+ u8 VGA_entry;
+ u16 VGA_table_offset;
+ u16 POST_table_offset;
+ u16 XCLK;
+ u16 MCLK;
+ u8 num_PLL_blocks;
+ u8 size_PLL_blocks;
+ u16 PCLK_ref_freq;
+ u16 PCLK_ref_divider;
+ u32 PCLK_min_freq;
+ u32 PCLK_max_freq;
+ u16 MCLK_ref_freq;
+ u16 MCLK_ref_divider;
+ u32 MCLK_min_freq;
+ u32 MCLK_max_freq;
+ u16 XCLK_ref_freq;
+ u16 XCLK_ref_divider;
+ u32 XCLK_min_freq;
+ u32 XCLK_max_freq;
+} __attribute__ ((packed)) PLL_BLOCK;
#endif /* !CONFIG_PPC */
/* onboard memory information */
@@ -194,12 +202,9 @@ static const struct aty128_meminfo sdr_sgram =
static const struct aty128_meminfo ddr_sgram =
{ 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
-static int currcon = 0;
-
-static char *aty128fb_name = "ATY Rage128";
+static const char *aty128fb_name = "ATY Rage128";
static char fontname[40] __initdata = { 0 };
-static char noaccel __initdata = 0;
-static unsigned int initdepth __initdata = 8;
+static int noaccel __initdata = 0;
#ifndef MODULE
static const char *mode_option __initdata = NULL;
@@ -291,13 +296,14 @@ struct fb_info_aty128 {
u32 cfb32[16];
#endif
} fbcon_cmap;
- int blitter_may_be_busy;
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
+ int currcon;
+ int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
};
@@ -515,10 +521,8 @@ aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
break;
}
-#ifdef DEBUG
if (reset) /* reset engine?? */
- DBG("PLL write timeout!");
-#endif
+ printk(KERN_DEBUG "aty128fb: PLL write timeout!");
}
@@ -645,9 +649,7 @@ aty128_reset_engine(const struct fb_info_aty128 *info)
/* use old pio mode */
aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
-#ifdef DEBUG
DBG("engine reset");
-#endif
}
@@ -1075,12 +1077,10 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
pll->feedback_divider = round_div(n, d);
pll->vclk = vclk;
-#ifdef DEBUG
- printk(KERN_DEBUG "var_to_pll: post %d feedback %d vlck %d output %d ref_divider %d\n",
- pll->post_divider, pll->feedback_divider, vclk, output_freq,
- c.ref_divider);
- printk(KERN_DEBUG "var_to_pll: vclk_per: %d\n", period_in_ps);
-#endif
+ DBG("post %d feedback %d vlck %d output %d ref_divider %d "
+ "vclk_per: %d\n", pll->post_divider,
+ pll->feedback_divider, vclk, output_freq,
+ c.ref_divider, period_in_ps);
return 0;
}
@@ -1134,9 +1134,8 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
m->Tr2w +
x;
-#ifdef DEBUG
- printk(KERN_DEBUG "aty128fb: x %x\n", x);
-#endif
+ DBG("x %x\n", x);
+
b = 0;
while (x) {
x >>= 1;
@@ -1155,10 +1154,9 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
return -EINVAL;
}
-#ifdef DEBUG
- printk(KERN_DEBUG "aty128fb: p: %x rloop: %x x: %x ron: %x roff: %x\n",
- p, m->Rloop, x, ron, roff);
-#endif
+ DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
+ p, m->Rloop, x, ron, roff);
+
dsp->dda_config = p << 16 | m->Rloop << 20 | x;
dsp->dda_on_off = ron << 16 | roff;
@@ -1543,7 +1541,12 @@ static int
aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- if (con == currcon) /* current console? */
+#if 1
+ fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
+#else
+ struct fb_info_aty128 fb = (struct fb_info_aty128 *)info;
+
+ if (con == fb->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -1551,6 +1554,7 @@ aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
}
+#endif
return 0;
}
@@ -1564,6 +1568,7 @@ aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
int err;
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
struct display *disp;
if (con >= 0)
@@ -1577,7 +1582,7 @@ aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
- if (con == currcon) /* current console? */
+ if (con == fb->currcon) /* current console? */
return fb_set_cmap(cmap, kspc, aty128_setcolreg, info);
else
fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
@@ -1632,24 +1637,6 @@ aty128fb_setup(char *options)
fontname[i] = 0;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
- } else if (!strncmp(this_opt, "depth:", 6)) {
- unsigned int depth = simple_strtoul(this_opt+6, NULL, 0);
- switch (depth) {
- case 0 ... 8:
- initdepth = 8;
- break;
- case 9 ... 16:
- initdepth = 16;
- break;
- case 17 ... 24:
- initdepth = 24;
- break;
- case 25 ... 32:
- initdepth = 32;
- break;
- default:
- initdepth = 8;
- }
}
#ifdef CONFIG_MTRR
else if(!strncmp(this_opt, "nomtrr", 6)) {
@@ -1762,7 +1749,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
#endif /* CONFIG_PPC */
{
if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
- &defaultmode, initdepth) == 0)
+ &defaultmode, 8) == 0)
var = default_var;
}
#endif /* MODULE */
@@ -1859,16 +1846,6 @@ aty128_pci_register(struct pci_dev *pdev,
u32 fb_addr, reg_addr, io_addr = 0;
int err;
-#if 0
- /* Request resources we're going to use */
- io_addr = pci_resource_start(pdev, 1);
- if (!request_region(io_addr, pci_resource_len(pdev, 1),
- "aty128fb IO")) {
- printk(KERN_ERR "aty128fb: cannot reserve I/O ports\n");
- goto err_out_none;
- }
-#endif
-
fb_addr = pci_resource_start(pdev, 0);
if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
"aty128fb FB")) {
@@ -1894,6 +1871,8 @@ aty128_pci_register(struct pci_dev *pdev,
/* Copy PCI device info into info->pdev */
info->pdev = pdev;
+ info->currcon = -1;
+
/* Virtualize mmio region */
info->regbase_phys = reg_addr;
info->regbase = ioremap(reg_addr, 0x1FFF);
@@ -1966,7 +1945,6 @@ err_free_mmio:
err_free_fb:
release_mem_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
-err_out_none:
return -ENODEV;
}
#endif /* CONFIG_PCI */
@@ -2072,13 +2050,12 @@ aty128_get_pllinfo(struct fb_info_aty128 *info)
if (bios_seg)
iounmap(bios_seg);
-#ifdef DEBUG
- printk(KERN_DEBUG "get_pllinfo: ppll_max %d ppll_min %d xclk %d "
- "ref_divider %d dotclock %d\n",
- info->constants.ppll_max, info->constants.ppll_min,
- info->constants.xclk, info->constants.ref_divider,
- info->constants.dotclock);
-#endif
+ DBG("ppll_max %d ppll_min %d xclk %d "
+ "ref_divider %d dotclock %d\n",
+ info->constants.ppll_max, info->constants.ppll_min,
+ info->constants.xclk, info->constants.ref_divider,
+ info->constants.dotclock);
+
return;
}
#endif /* !CONFIG_PPC */
@@ -2159,11 +2136,12 @@ aty128fbcon_switch(int con, struct fb_info *fb)
struct aty128fb_par par;
/* Do we have to save the colormap? */
- if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, 1, aty128_getcolreg, fb);
+ if (fb_display[info->currcon].cmap.len)
+ fb_get_cmap(&fb_display[info->currcon].cmap, 1,
+ aty128_getcolreg, fb);
/* set the current console */
- currcon = con;
+ info->currcon = con;
aty128_decode_var(&fb_display[con].var, &par, info);
aty128_set_par(&par, info);
@@ -2319,7 +2297,9 @@ aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static void
do_install_cmap(int con, struct fb_info *info)
{
- if (con != currcon)
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
+
+ if (con != fb->currcon)
return;
if (fb_display[con].cmap.len)
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index f4824762b..fff0a4f39 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -85,7 +85,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
int mode,
unsigned int pos) {
u_int32_t tmp;
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
switch (mode) {
case 15:
@@ -250,9 +250,9 @@ static void initMatroxDH(struct matroxfb_dh_fb_info* m2info, struct display* p)
static int matroxfb_dh_open(struct fb_info* info, int user) {
#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
- if (minfo) {
+ if (MINFO) {
if (ACCESS_FBINFO(dead)) {
return -ENXIO;
}
@@ -263,9 +263,9 @@ static int matroxfb_dh_open(struct fb_info* info, int user) {
static int matroxfb_dh_release(struct fb_info* info, int user) {
#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
- if (minfo) {
+ if (MINFO) {
}
return 0;
#undef m2info
@@ -320,7 +320,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
int cmap_len;
int mode;
int err;
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
if (con < 0)
p = m2info->fbcon.disp;
@@ -477,7 +477,7 @@ static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, int con,
static int matroxfb_dh_switch(int con, struct fb_info* info);
static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
memset(vblank, 0, sizeof(*vblank));
vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
@@ -496,7 +496,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
int con,
struct fb_info* info) {
#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ MINFO_FROM(m2info->primary_dev);
DBG("matroxfb_crtc2_ioctl")
@@ -516,7 +516,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
case MATROXFB_GET_OUTPUT_MODE:
case MATROXFB_GET_ALL_OUTPUTS:
{
- return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, con, &minfo->fbcon);
+ return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, con, &ACCESS_FBINFO(fbcon));
}
case MATROXFB_SET_OUTPUT_CONNECTION:
{
@@ -660,15 +660,15 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
if (mem < 64*1024)
mem *= 1024;
mem &= ~0x00000FFF; /* PAGE_MASK? */
- if (minfo->video.len_usable + mem <= minfo->video.len)
- m2info->video.offbase = minfo->video.len - mem;
- else if (minfo->video.len < mem) {
+ if (ACCESS_FBINFO(video.len_usable) + mem <= ACCESS_FBINFO(video.len))
+ m2info->video.offbase = ACCESS_FBINFO(video.len) - mem;
+ else if (ACCESS_FBINFO(video.len) < mem) {
kfree(d);
return -ENOMEM;
} else { /* check yres on first head... */
m2info->video.borrowed = mem;
- minfo->video.len_usable -= mem;
- m2info->video.offbase = minfo->video.len_usable;
+ ACCESS_FBINFO(video.len_usable) -= mem;
+ m2info->video.offbase = ACCESS_FBINFO(video.len_usable);
}
m2info->video.base = ACCESS_FBINFO(video.base) + m2info->video.offbase;
m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;
@@ -698,8 +698,8 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
matroxfb_dh_set_var(&matroxfb_dh_defined, -1, &m2info->fbcon);
}
down_write(&ACCESS_FBINFO(crtc2.lock));
- oldcrtc2 = minfo->crtc2.info;
- minfo->crtc2.info = &m2info->fbcon;
+ oldcrtc2 = ACCESS_FBINFO(crtc2.info);
+ ACCESS_FBINFO(crtc2.info) = &m2info->fbcon;
up_write(&ACCESS_FBINFO(crtc2.lock));
if (oldcrtc2) {
printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
@@ -731,9 +731,9 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
struct fb_info* crtc2;
down_write(&ACCESS_FBINFO(crtc2.lock));
- crtc2 = minfo->crtc2.info;
+ crtc2 = ACCESS_FBINFO(crtc2.info);
if (crtc2 == &m2info->fbcon)
- minfo->crtc2.info = NULL;
+ ACCESS_FBINFO(crtc2.info) = NULL;
up_write(&ACCESS_FBINFO(crtc2.lock));
if (crtc2 != &m2info->fbcon) {
printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
@@ -756,7 +756,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
struct matroxfb_dh_fb_info* m2info;
/* hardware is CRTC2 incapable... */
- if (!minfo->devflags.crtc2)
+ if (!ACCESS_FBINFO(devflags.crtc2))
return NULL;
m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
if (!m2info) {
@@ -764,7 +764,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
return NULL;
}
memset(m2info, 0, sizeof(*m2info));
- m2info->primary_dev = minfo;
+ m2info->primary_dev = MINFO;
if (matroxfb_dh_registerfb(m2info)) {
kfree(m2info);
printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index e7d515ec2..57b822293 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -892,9 +892,9 @@ static struct matrox_altout maven_altout = {
static int maven_init_client(struct i2c_client* clnt) {
struct i2c_adapter* a = clnt->adapter;
- struct matroxfb_dh_maven_info* m2info = ((struct i2c_bit_adapter*)a)->minfo;
struct maven_data* md = clnt->data;
- struct matrox_fb_info* minfo = m2info->primary_dev;
+ struct matroxfb_dh_maven_info* m2info __attribute__((unused)) = ((struct i2c_bit_adapter*)a)->minfo;
+ MINFO_FROM(m2info->primary_dev);
md->mode = MODE_MONITOR;
md->primary_head = MINFO;
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 6a4e41e9e..23fc97915 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -4,7 +4,7 @@
* Created 8 August 1998 by Martin Costabel and Kevin Schoedel
*
* Vmode-switching changes and vmode 15/17 modifications created 29 August
- * 1998 by Barry Nathan <barryn@pobox.com>.
+ * 1998 by Barry K. Nathan <barryn@pobox.com>.
*
* Derived directly from:
*
diff --git a/drivers/video/valkyriefb.h b/drivers/video/valkyriefb.h
index ee246a4fc..c8984b38b 100644
--- a/drivers/video/valkyriefb.h
+++ b/drivers/video/valkyriefb.h
@@ -4,7 +4,7 @@
* Created 8 August 1998 by Martin Costabel and Kevin Schoedel
*
* Vmode-switching changes and vmode 15/17 modifications created 29 August
- * 1998 by Barry Nathan <barryn@pobox.com>.
+ * 1998 by Barry K. Nathan <barryn@pobox.com>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License