]> git.hungrycats.org Git - linux/commitdiff
v2.4.6.5 -> v2.4.6.6
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 03:11:21 +0000 (19:11 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 03:11:21 +0000 (19:11 -0800)
  - me: fix more buffer head SMP races (non-x86 only - weak memory ordering)
  - Andrea Arkangeli: some bh cleanups from the buffer race condition fix
  - Tim Waugh: parport drievr documentation, init sanity
  - Ion Badulescu: starfire net driver update
  - David Miller: sparc and networking updates
  - Ivan Kokshaysky: alpha version of the inlined rw-semaphores
  - NIIBE Yutaka: SuperH update

53 files changed:
Documentation/Configure.help
Documentation/fb/00-INDEX
Documentation/fb/pvr2fb.txt [new file with mode: 0644]
Makefile
arch/alpha/config.in
arch/alpha/kernel/alpha_ksyms.c
drivers/block/ll_rw_blk.c
drivers/block/ps2esdi.c
drivers/char/lp.c
drivers/char/mem.c
drivers/net/pppoe.c
drivers/net/starfire.c
drivers/net/stnic.c
drivers/parport/ChangeLog
drivers/parport/Config.in
drivers/parport/Makefile
drivers/parport/init.c
drivers/parport/parport_pc.c
drivers/parport/parport_serial.c [new file with mode: 0644]
drivers/pcmcia/hd64465_ss.c
drivers/scsi/aic7xxx_old.c
drivers/video/Config.in
drivers/video/Makefile
drivers/video/dcfb.c [deleted file]
drivers/video/fbmem.c
drivers/video/pvr2fb.c [new file with mode: 0644]
fs/buffer.c
include/asm-alpha/atomic.h
include/asm-alpha/rwsem.h [new file with mode: 0644]
include/asm-i386/atomic.h
include/asm-ia64/atomic.h
include/asm-m68k/atomic.h
include/asm-mips/atomic.h
include/asm-mips64/atomic.h
include/asm-ppc/atomic.h
include/asm-s390/atomic.h
include/asm-s390x/atomic.h
include/asm-sparc/atomic.h
include/asm-sparc/bitops.h
include/asm-sparc64/atomic.h
include/linux/fs.h
include/linux/if_arp.h
include/linux/netlink.h
include/linux/parport.h
include/linux/skbuff.h
lib/rwsem.c
net/core/dv.c
net/core/skbuff.c
net/ipv4/ip_output.c
net/ipv4/raw.c
net/ipv4/tcp_output.c
net/netsyms.c
net/unix/af_unix.c

index 932e50efc2f2ec3a14b6fde26196721d6c935714..ee0eb7073267f5051364e98c32ee23970c016b48 100644 (file)
@@ -3372,6 +3372,30 @@ CONFIG_FB_HGA
   As this card technology is 15 years old, most people will answer N
   here.
 
+NEC PowerVR 2 display support
+CONFIG_FB_PVR2
+  Say Y here if you have a PowerVR 2 card in your box. If you plan to
+  run linux on your Dreamcast, you will have to say Y here. This driver
+  may or may not work on other PowerVR 2 cards, but is totally untested.
+  Use at your own risk. If unsure, say N.
+
+  This driver is also available as a module ( = code which can be
+  inserted and removed from the running kernel whenever you want).
+  The module will be called pvr2fb.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt.
+
+  You can pass several parameters to the driver at boot time or at
+  module load time. The parameters look like "video=pvr2:XXX", where
+  the meaning of XXX can be found at the end of the main source file
+  (drivers/video/pvr2fb.c). Please see the file
+  Documentation/fb/pvr2fb.txt.
+
+Debug pvr2fb
+CONFIG_FB_PVR2_DEBUG
+  Say Y here if you wish for the pvr2fb driver to print out debugging
+  messages. Most people will want to say N here. If unsure, you will
+  also want to say N.
+
 Matrox unified accelerated driver (EXPERIMENTAL)
 CONFIG_FB_MATROX
   Say Y here if you have a Matrox Millennium, Matrox Millennium II,
@@ -3712,6 +3736,12 @@ CONFIG_PARPORT_PC
   
   If unsure, say Y.
 
+Parallel+serial PCI card support
+CONFIG_PARPORT_SERIAL
+  This adds support for multi-IO PCI cards that have parallel and serial
+  ports.  You should say Y or M here.  If you say M, the module will be
+  called parport_serial.o.
+
 Use FIFO/DMA if available
 CONFIG_PARPORT_PC_FIFO
   Many parallel port chipsets provide hardware that can speed up
@@ -13492,10 +13522,12 @@ CONFIG_LP_CONSOLE
   doing that; to actually get it to happen you need to pass the
   option "console=lp0" to the kernel at boot time.
 
-  Note that kernel messages can get lost if the printer is out of
-  paper (or off, or unplugged, or too busy..), but this behaviour
-  can be changed. See drivers/char/lp.c (do this at your own risk).
-
+  If the printer is out of paper (or off, or unplugged, or too
+  busy..) the kernel will stall until the printer is ready again.
+  By defining CONSOLE_LP_STRICT to 0 (at your own risk) you
+  can make the kernel continue when this happens,
+  but it'll lose the kernel messages.
+  
   If unsure, say N.
 
 Support for user-space parallel port device drivers
index 54bb5161cbfec236c38732c29d607887982331ea..92e89aeef52e6c31122f01d671622dba18424733 100644 (file)
@@ -17,6 +17,8 @@ clgenfb.txt
        - info on the Cirrus Logic frame buffer driver
 matroxfb.txt
        - info on the Matrox frame buffer driver
+pvr2fb.txt
+       - info on the PowerVR 2 frame buffer driver
 tgafb.txt
        - info on the TGA (DECChip 21030) frame buffer driver
 vesafb.txt
diff --git a/Documentation/fb/pvr2fb.txt b/Documentation/fb/pvr2fb.txt
new file mode 100644 (file)
index 0000000..6e45c6e
--- /dev/null
@@ -0,0 +1,61 @@
+$Id: pvr2fb.txt,v 1.1 2001/05/24 05:09:16 mrbrown Exp $
+
+What is pvr2fb?
+===============
+
+This is a driver for PowerVR 2 based graphics frame buffers, such as the
+one found in the Dreamcast.
+
+Advantages:
+
+ * It provides a nice large console (128 cols + 48 lines with 1024x768)
+   without using tiny, unreadable fonts.
+ * You can run XF86_FBDev on top of /dev/fb0
+ * Most important: boot logo :-)
+
+Disadvantages:
+
+ * Driver is currently limited to the Dreamcast PowerVR 2 implementation
+   at the time of this writing.
+
+Configuration
+=============
+
+You can pass kernel command line options to pvr2fb with
+`video=pvr2:option1,option2:value2,option3' (multiple options should be
+separated by comma, values are separated from options by `:').
+Accepted options:
+
+font:X    - default font to use. All fonts are supported, including the
+            SUN12x22 font which is very nice at high resolutions.
+
+mode:X    - default video mode. The following video modes are supported:
+            640x240-60, 640x480-60.
+           
+            Note: the 640x240 mode is currently broken, and should not be
+            used for any reason. It is only mentioned as a reference.
+
+inverse   - invert colors on screen (for LCD displays)
+
+nomtrr    - disables write combining on frame buffer. This slows down driver
+            but there is reported minor incompatibility between GUS DMA and
+            XFree under high loads if write combining is enabled (sound
+            dropouts). MTRR is enabled by default on systems that have it
+            configured and that support it.
+
+cable:X   - cable type. This can be any of the following: vga, rgb, and
+            composite. If none is specified, we guess.
+
+output:X  - output type. This can be any of the following: pal, ntsc, and
+            vga. If none is specified, we guess.
+
+X11
+===
+
+XF86_FBDev should work, in theory. At the time of this writing it is
+totally untested and may or may not even portray the beginnings of
+working. If you end up testing this, please let me know!
+
+--
+Paul Mundt <lethal@linuxdc.org>
+
index 41dfa84748d4628bbfecbf459d4e32e059d47f09..697c18111236e73d371acae7fb62db2c5babab15 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 7
-EXTRAVERSION =-pre5
+EXTRAVERSION =-pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index 03d8e66bde10304eb69812bf21e1c8b84d0d0054..bc3cf419924cfdb5d56b1fd0674b323136300af8 100644 (file)
@@ -5,8 +5,8 @@
 
 define_bool CONFIG_ALPHA y
 define_bool CONFIG_UID16 n
-define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
-define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 
 mainmenu_name "Kernel configuration of Linux for Alpha machines"
 
index a23501e202b7968a42ecf81844c2439a2e950b32..55a493a27c650deb1c27cdab5f51c05e1284bae0 100644 (file)
@@ -178,10 +178,6 @@ EXPORT_SYMBOL(down);
 EXPORT_SYMBOL(down_interruptible);
 EXPORT_SYMBOL(down_trylock);
 EXPORT_SYMBOL(up);
-EXPORT_SYMBOL(down_read);
-EXPORT_SYMBOL(down_write);
-EXPORT_SYMBOL(up_read);
-EXPORT_SYMBOL(up_write);
 
 /* 
  * SMP-specific symbols.
index a57c0b96f06c3dc0e881173670a901a450a73cfa..1f6db063f2b76745b8ebe11796898c0e94948436 100644 (file)
@@ -960,16 +960,6 @@ void submit_bh(int rw, struct buffer_head * bh)
        }
 }
 
-/*
- * Default IO end handler, used by "ll_rw_block()".
- */
-static void end_buffer_io_sync(struct buffer_head *bh, int uptodate)
-{
-       mark_buffer_uptodate(bh, uptodate);
-       unlock_buffer(bh);
-       atomic_dec(&bh->b_count);
-}
-
 /**
  * ll_rw_block: low-level access to block devices
  * @rw: whether to %READ or %WRITE or maybe %READA (readahead)
index a0ca8e94dc9de64952be48a4ef4b2678a7f9694d..0fdeccda15263a103cd005a39a5be54067b94f79 100644 (file)
@@ -415,8 +415,11 @@ static void __init ps2esdi_geninit(void)
 
        ps2esdi_gendisk.nr_real = ps2esdi_drives;
 
-       for (i = 0; i < (MAX_HD << 6); i++)
+       /* 128 was old default, maybe maxsect=255 is ok too? - Paul G. */
+       for (i = 0; i < (MAX_HD << 6); i++) {
+               ps2esdi_maxsect[i] = 128;
                ps2esdi_blocksizes[i] = 1024;
+       }
 
        request_dma(dma_arb_level, "ed");
        request_region(io_base, 4, "ed");
index 7092d60086317f4bbdd93b601643cbed97d2c3b5..30f216be3d83c7b79bc4f71817f6f0756a27c981 100644 (file)
@@ -609,8 +609,6 @@ static struct console lpcons = {
 
 /* --- initialisation code ------------------------------------- */
 
-#ifdef MODULE
-
 static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
 static char *parport[LP_NO] = { NULL,  };
 static int reset = 0;
@@ -618,21 +616,18 @@ static int reset = 0;
 MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "s");
 MODULE_PARM(reset, "i");
 
-#else
-
-static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
-static int reset = 0;
-
-static int parport_ptr = 0;
-
-void __init lp_setup(char *str, int *ints)
+static int __init lp_setup (char *str)
 {
-       if (!str) {
-               if (ints[0] == 0 || ints[1] == 0) {
+       static int parport_ptr; // initially zero
+       int x;
+
+       if (get_option (&str, &x)) {
+               if (x == 0) {
                        /* disable driver on "lp=" or "lp=0" */
                        parport_nr[0] = LP_PARPORT_OFF;
                } else {
-                       printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
+                       printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", x);
+                       return 0;
                }
        } else if (!strncmp(str, "parport", 7)) {
                int n = simple_strtoul(str+7, NULL, 10);
@@ -648,10 +643,9 @@ void __init lp_setup(char *str, int *ints)
        } else if (!strcmp(str, "reset")) {
                reset = 1;
        }
+       return 1;
 }
 
-#endif
-
 static int lp_register(int nr, struct parport *port)
 {
        char name[8];
@@ -782,8 +776,7 @@ int __init lp_init (void)
        return 0;
 }
 
-#ifdef MODULE
-int init_module(void)
+static int __init lp_init_module (void)
 {
        if (parport[0]) {
                /* The user gave some parameters.  Let's see what they were.  */
@@ -811,7 +804,7 @@ int init_module(void)
        return lp_init();
 }
 
-void cleanup_module(void)
+static void lp_cleanup_module (void)
 {
        unsigned int offset;
 
@@ -829,4 +822,7 @@ void cleanup_module(void)
                parport_unregister_device(lp_table[offset].dev);
        }
 }
-#endif
+
+__setup("lp=", lp_setup);
+module_init(lp_init_module);
+module_exit(lp_cleanup_module);
index b623f228247338822ab409826e5ccd6d9ebbadf6..dc8977570f5b65e84a391362c9d29e804deac96e 100644 (file)
@@ -626,9 +626,6 @@ int __init chr_dev_init(void)
        mda_console_init();
 #endif
        tty_init();
-#ifdef CONFIG_PRINTER
-       lp_init();
-#endif
 #ifdef CONFIG_M68K_PRINTER
        lp_m68k_init();
 #endif
index d0881887030bad3b44514042e748601876d15359..7a1d338692584e21bcc16ead459efc5af293edec 100644 (file)
@@ -567,17 +567,17 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                if (!dev)
                        goto end;
 
+               po->pppoe_dev = dev;
+
                if( ! (dev->flags & IFF_UP) )
-                       goto end;
+                       goto err_put;
                memcpy(&po->pppoe_pa,
                       &sp->sa_addr.pppoe,
                       sizeof(struct pppoe_addr));
 
                error = set_item(po);
                if (error < 0)
-                       goto end;
-
-               po->pppoe_dev = dev;
+                       goto err_put;
 
                po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
                                   dev->hard_header_len);
@@ -586,6 +586,8 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                po->chan.ops = &pppoe_chan_ops;
 
                error = ppp_register_channel(&po->chan);
+               if (error)
+                       goto err_put;
 
                sk->state = PPPOX_CONNECTED;
        }
@@ -595,6 +597,10 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
  end:
        release_sock(sk);
        return error;
+err_put:
+       dev_put(po->pppoe_dev);
+       po->pppoe_dev = NULL;
+       goto end;
 }
 
 
index 5e52cc461856ac7de064d36499a031a7ab9b980f..fc1d5837c85b1d66d0091c4042432448ea84325a 100644 (file)
        - Fixed 2.2.x compatibility issues introduced in 1.3.1
        - Fixed ethtool ioctl returning uninitialized memory
 
+       LK1.3.3 (Ion Badulescu)
+       - Initialize the TxMode register properly
+       - Set the MII registers _after_ resetting it
+       - Don't dereference dev->priv after unregister_netdev() has freed it
+
 TODO:
        - implement tx_timeout() properly
 */
 
 #define DRV_NAME       "starfire"
-#define DRV_VERSION    "1.03+LK1.3.2"
-#define DRV_RELDATE    "June 04, 2001"
+#define DRV_VERSION    "1.03+LK1.3.3"
+#define DRV_RELDATE    "July 05, 2001"
 
 /*
  * Adaptec's license for their Novell drivers (which is where I got the
@@ -192,12 +197,6 @@ static int full_duplex[MAX_UNITS] = {0, };
 #define skb_first_frag_len(skb)        (skb->len)
 #endif /* not ZEROCOPY */
 
-#if !defined(__OPTIMIZE__)
-#warning  You must compile this file with the correct options!
-#warning  See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -208,7 +207,6 @@ static int full_duplex[MAX_UNITS] = {0, };
 #include <linux/delay.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/uaccess.h>
-#include <asm/io.h>
 
 #ifdef HAS_FIRMWARE
 #include "starfire_firmware.h"
@@ -559,7 +557,7 @@ struct netdev_private {
        unsigned int cur_tx, dirty_tx;
        unsigned int rx_buf_sz;         /* Based on MTU+slack. */
        unsigned int tx_full:1,         /* The Tx queue is full. */
-       /* These values are keep track of the transceiver/media in use. */
+       /* These values keep track of the transceiver/media in use. */
                autoneg:1,              /* Autonegotiation allowed. */
                full_duplex:1,          /* Full-duplex operation. */
                speed100:1;             /* Set if speed == 100MBit. */
@@ -572,6 +570,7 @@ struct netdev_private {
        unsigned char phys[PHY_CNT];    /* MII device addresses. */
 };
 
+
 static int     mdio_read(struct net_device *dev, int phy_id, int location);
 static void    mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int     netdev_open(struct net_device *dev);
@@ -589,7 +588,7 @@ static int  netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int     netdev_close(struct net_device *dev);
 static void    netdev_media_change(struct net_device *dev);
 
-\f
+
 
 static int __devinit starfire_init_one(struct pci_dev *pdev,
                                       const struct pci_device_id *ent)
@@ -615,9 +614,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        if (pci_enable_device (pdev))
                return -EIO;
 
-       ioaddr = pci_resource_start (pdev, 0);
-       io_size = pci_resource_len (pdev, 0);
-       if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_MEM) == 0)) {
+       ioaddr = pci_resource_start(pdev, 0);
+       io_size = pci_resource_len(pdev, 0);
+       if (!ioaddr || ((pci_resource_flags(pdev, 0) & IORESOURCE_MEM) == 0)) {
                printk (KERN_ERR DRV_NAME " %d: no PCI MEM resources, aborting\n", card_idx);
                return -ENODEV;
        }
@@ -777,14 +776,13 @@ err_out_cleardev:
 err_out_free_res:
        pci_release_regions (pdev);
 err_out_free_netdev:
-       unregister_netdev (dev);
-       kfree (dev);
+       unregister_netdev(dev);
+       kfree(dev);
        return -ENODEV;
 }
 
-\f
-/* Read the MII Management Data I/O (MDIO) interfaces. */
 
+/* Read the MII Management Data I/O (MDIO) interfaces. */
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
        long mdio_addr = dev->base_addr + MIICtrl + (phy_id<<7) + (location<<2);
@@ -800,6 +798,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
        return result & 0xffff;
 }
 
+
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
        long mdio_addr = dev->base_addr + MIICtrl + (phy_id<<7) + (location<<2);
@@ -808,7 +807,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
        return;
 }
 
-\f
+
 static int netdev_open(struct net_device *dev)
 {
        struct netdev_private *np = dev->priv;
@@ -931,6 +930,8 @@ static int netdev_open(struct net_device *dev)
        /* Initialize other registers. */
        /* Configure the PCI bus bursts and FIFO thresholds. */
        np->tx_mode = 0x0C04;           /* modified when link is up. */
+       writel(0x8000 | np->tx_mode, ioaddr + TxMode);
+       writel(np->tx_mode, ioaddr + TxMode);
        np->tx_threshold = 4;
        writel(np->tx_threshold, ioaddr + TxThreshold);
 
@@ -986,12 +987,12 @@ static void check_duplex(struct net_device *dev)
        struct netdev_private *np = dev->priv;
        u16 reg0;
 
-       mdio_write(dev, np->phys[0], MII_ADVERTISE, np->advertising);
        mdio_write(dev, np->phys[0], MII_BMCR, BMCR_RESET);
        udelay(500);
        while (mdio_read(dev, np->phys[0], MII_BMCR) & BMCR_RESET);
 
        reg0 = mdio_read(dev, np->phys[0], MII_BMCR);
+       mdio_write(dev, np->phys[0], MII_ADVERTISE, np->advertising);
 
        if (np->autoneg) {
                reg0 |= BMCR_ANENABLE | BMCR_ANRESTART;
@@ -1098,6 +1099,7 @@ static void init_ring(struct net_device *dev)
        return;
 }
 
+
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
        struct netdev_private *np = dev->priv;
@@ -1214,6 +1216,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
@@ -1350,6 +1353,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 #endif
 }
 
+
 /* This routine is logically part of the interrupt handler, but separated
    for clarity and better register allocation. */
 static int netdev_rx(struct net_device *dev)
@@ -1407,11 +1411,9 @@ static int netdev_rx(struct net_device *dev)
                        memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail, pkt_len);
 #endif
                } else {
-                       char *temp;
-
                        pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
                        skb = np->rx_info[entry].skb;
-                       temp = skb_put(skb, pkt_len);
+                       skb_put(skb, pkt_len);
                        np->rx_info[entry].skb = NULL;
                        np->rx_info[entry].mapping = 0;
                }
@@ -1570,6 +1572,7 @@ static void netdev_error(struct net_device *dev, int intr_status)
                np->stats.tx_fifo_errors++;
 }
 
+
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
        long ioaddr = dev->base_addr;
@@ -1596,6 +1599,7 @@ static struct net_device_stats *get_stats(struct net_device *dev)
        return &np->stats;
 }
 
+
 /* The little-endian AUTODIN II ethernet CRC calculations.
    A big-endian version is also available.
    This is slow but compact code.  Do not use this routine for bulk data,
@@ -1622,6 +1626,7 @@ static inline unsigned ether_crc_le(int length, unsigned char *data)
        return crc;
 }
 
+
 static void set_rx_mode(struct net_device *dev)
 {
        long ioaddr = dev->base_addr;
@@ -1658,7 +1663,7 @@ static void set_rx_mode(struct net_device *dev)
 
                memset(mc_filter, 0, sizeof(mc_filter));
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-                        i++, mclist = mclist->next) {
+                    i++, mclist = mclist->next) {
                        int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
                        __u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
 
@@ -1679,7 +1684,6 @@ static void set_rx_mode(struct net_device *dev)
 }
 
 
-
 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
 {
        struct ethtool_cmd ecmd;
@@ -1779,7 +1783,6 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
 }
 
 
-
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct netdev_private *np = dev->priv;
@@ -1808,10 +1811,11 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        u16 value = data->val_in;
                        switch (data->reg_num) {
                        case 0:
-                               if (value & 0x9000)     /* Autonegotiation. */
+                               if (value & (BMCR_RESET | BMCR_ANENABLE))
+                                       /* Autonegotiation. */
                                        np->autoneg = 1;
                                else {
-                                       np->full_duplex = (value & 0x0100) ? 1 : 0;
+                                       np->full_duplex = (value & BMCR_FULLDPLX) ? 1 : 0;
                                        np->autoneg = 0;
                                }
                                break;
@@ -1921,27 +1925,26 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
                BUG();
 
        np = dev->priv;
-
-       unregister_netdev(dev);
-       iounmap((char *)dev->base_addr);
-       pci_release_regions(pdev);
-
        if (np->tx_done_q)
-               pci_free_consistent(np->pci_dev, PAGE_SIZE,
+               pci_free_consistent(pdev, PAGE_SIZE,
                                    np->tx_done_q, np->tx_done_q_dma);
        if (np->rx_done_q)
-               pci_free_consistent(np->pci_dev, PAGE_SIZE,
+               pci_free_consistent(pdev,
+                                   sizeof(struct rx_done_desc) * DONE_Q_SIZE,
                                    np->rx_done_q, np->rx_done_q_dma);
        if (np->tx_ring)
-               pci_free_consistent(np->pci_dev, PAGE_SIZE,
+               pci_free_consistent(pdev, PAGE_SIZE,
                                    np->tx_ring, np->tx_ring_dma);
        if (np->rx_ring)
-               pci_free_consistent(np->pci_dev, PAGE_SIZE,
+               pci_free_consistent(pdev, PAGE_SIZE,
                                    np->rx_ring, np->rx_ring_dma);
 
-       kfree(dev);
+       unregister_netdev(dev);                 /* Will also free np!! */
+       iounmap((char *)dev->base_addr);
+       pci_release_regions(pdev);
 
        pci_set_drvdata(pdev, NULL);
+       kfree(dev);
 }
 
 
index e119ab75733d92bedcdd4af56534a312bdee38d9..d55ed16788993ebefcdbfbc5012b62bb70109942 100644 (file)
@@ -146,6 +146,11 @@ int __init stnic_probe(void)
 
   ei_status.name = dev->name;
   ei_status.word16 = 1;
+#ifdef __LITTLE_ENDIAN__ 
+  ei_status.bigendian = 0;
+#else
+  ei_status.bigendian = 1;
+#endif
   ei_status.tx_start_page = START_PG;
   ei_status.rx_start_page = START_PG + TX_PAGES;
   ei_status.stop_page = STOP_PG;
@@ -154,6 +159,7 @@ int __init stnic_probe(void)
   ei_status.get_8390_hdr = &stnic_get_hdr;
   ei_status.block_input = &stnic_block_input;
   ei_status.block_output = &stnic_block_output;
+
   stnic_init (dev);
 
   printk (KERN_INFO "NS ST-NIC 83902A\n");
index 9e7ce482b5c5c30bd702ceb788c15b12fea2a9d2..03a1ccc9cbac4198270c0fc7aee812d97531baa4 100644 (file)
@@ -1,3 +1,11 @@
+2001-06-20  Tim Waugh  <twaugh@redhat.com>
+
+       * parport_pc.c: Make 'io_hi=0' work.
+
+2001-05-31  Tim Waugh  <twaugh@redhat.com>
+
+       * parport_serial.c: New file.
+
 2001-06-05  Tim Waugh  <twaugh@redhat.com>
 
        * parport_pc.c (parport_pc_unregister_port): New exported function.
index ede473e269dc3e413d1949ae443d02f28cccff9e..75012613407cd487859d3165e07a748bdb3bb3c6 100644 (file)
@@ -11,6 +11,14 @@ comment 'Parallel port support'
 tristate 'Parallel port support' CONFIG_PARPORT
 if [ "$CONFIG_PARPORT" != "n" ]; then
    dep_tristate '  PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+   if [ "$CONFIG_PARPORT_PC" != "n" -a "$CONFIG_SERIAL" != "n" ]; then
+      if [ "$CONFIG_SERIAL" = "m" ]; then
+         define_tristate CONFIG_PARPORT_PC_CML1 m
+      else
+         define_tristate CONFIG_PARPORT_PC_CML1 $CONFIG_PARPORT_PC
+      fi
+      dep_tristate '    Multi-IO cards (parallel and serial)' CONFIG_PARPORT_SERIAL $CONFIG_PARPORT_PC_CML1
+   fi
    if [ "$CONFIG_PARPORT_PC" != "n" ]; then
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
          bool '    Use FIFO/DMA if available (EXPERIMENTAL)' CONFIG_PARPORT_PC_FIFO
index db514ff8c164c2a6f3b5a99bc8cb4d8bce6dc324..cd886a1b1c846a437c74aa295d2fda68458c048c 100644 (file)
@@ -22,6 +22,7 @@ endif
 
 obj-$(CONFIG_PARPORT)          += parport.o
 obj-$(CONFIG_PARPORT_PC)       += parport_pc.o
+obj-$(CONFIG_PARPORT_SERIAL)   += parport_serial.o
 obj-$(CONFIG_PARPORT_AMIGA)    += parport_amiga.o
 obj-$(CONFIG_PARPORT_MFC3)     += parport_mfc3.o
 obj-$(CONFIG_PARPORT_ATARI)    += parport_atari.o
index bbada430e0eff2fd4862be0c0db4d28194268dde..e28ce6b5f61669d70ab7f48fba868aa4fe5774bb 100644 (file)
@@ -21,7 +21,8 @@
 #ifndef MODULE
 static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
 #ifdef CONFIG_PARPORT_PC
-static int io_hi[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
+static int io_hi[PARPORT_MAX+1] __initdata =
+       { [0 ... PARPORT_MAX] = PARPORT_IOHI_AUTO };
 #endif
 static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
 static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
index baf111c6d128f1cd2030dec9e1ca66adb2e37426..eaa824166879c30d5fac8f4cf029b680f9f0553b 100644 (file)
@@ -2824,7 +2824,8 @@ int __init parport_pc_init (int *io, int *io_hi, int *irq, int *dma)
                /* Only probe the ports we were given. */
                user_specified = 1;
                do {
-                       if (!*io_hi) *io_hi = 0x400 + *io;
+                       if ((*io_hi) == PARPORT_IOHI_AUTO)
+                              *io_hi = 0x400 + *io;
                        if (parport_pc_probe_port(*(io++), *(io_hi++),
                                                  *(irq++), *(dma++), NULL))
                                count++;
@@ -2842,7 +2843,8 @@ EXPORT_SYMBOL (parport_pc_unregister_port);
 
 #ifdef MODULE
 static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
-static int io_hi[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
+static int io_hi[PARPORT_PC_MAX_PORTS+1] =
+       { [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
 static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
 static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
 static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
new file mode 100644 (file)
index 0000000..7509a99
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Support for common PCI multi-I/O cards (which is most of them)
+ *
+ * Copyright (C) 2001  Tim Waugh <twaugh@redhat.com>
+ *
+ * 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 the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ *
+ * Multi-function PCI cards are supposed to present separate logical
+ * devices on the bus.  A common thing to do seems to be to just use
+ * one logical device with lots of base address registers for both
+ * parallel ports and serial ports.  This driver is for dealing with
+ * that.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/parport.h>
+#include <linux/parport_pc.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/list.h>
+
+#include <asm/serial.h>
+
+enum parport_pc_pci_cards {
+       titan_110l = 0,
+       titan_210l,
+       netmos_9735,
+       netmos_9835,
+       avlab_1s1p,
+       avlab_1s1p_650,
+       avlab_1s1p_850,
+       avlab_1s2p,
+       avlab_1s2p_650,
+       avlab_1s2p_850,
+       avlab_2s1p,
+       avlab_2s1p_650,
+       avlab_2s1p_850,
+};
+
+
+/* each element directly indexed from enum list, above */
+static struct parport_pc_pci {
+       int numports;
+       struct { /* BAR (base address registers) numbers in the config
+                    space header */
+               int lo;
+               int hi; /* -1 if not there, >6 for offset-method (max
+                           BAR is 6) */
+       } addr[4];
+} cards[] __devinitdata = {
+       /* titan_110l */                { 1, { { 3, -1 }, } },
+       /* titan_210l */                { 1, { { 3, -1 }, } },
+       /* netmos_9735 (not tested) */  { 1, { { 2, 3 }, } },
+       /* netmos_9835 (not tested) */  { 1, { { 2, 3 }, } },
+       /* avlab_1s1p     */            { 1, { { 1, 2}, } },
+       /* avlab_1s1p_650 */            { 1, { { 1, 2}, } },
+       /* avlab_1s1p_850 */            { 1, { { 1, 2}, } },
+       /* avlab_1s2p     */            { 2, { { 1, 2}, { 3, 4 },} },
+       /* avlab_1s2p_650 */            { 2, { { 1, 2}, { 3, 4 },} },
+       /* avlab_1s2p_850 */            { 2, { { 1, 2}, { 3, 4 },} },
+       /* avlab_2s1p     */            { 1, { { 2, 3}, } },
+       /* avlab_2s1p_650 */            { 1, { { 2, 3}, } },
+       /* avlab_2s1p_850 */            { 1, { { 2, 3}, } },
+};
+
+static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = {
+       /* PCI cards */
+       { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
+       { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 },
+       /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
+       { 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
+       { 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
+       { 0x14db, 0x2112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_850},
+       { 0x14db, 0x2140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p},
+       { 0x14db, 0x2141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_650},
+       { 0x14db, 0x2142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_850},
+       { 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p},
+       { 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650},
+       { 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850},
+       { 0, } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
+
+struct pci_board_no_ids {
+       int flags;
+       int num_ports;
+       int base_baud;
+       int uart_offset;
+       int reg_shift;
+       int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
+                       int enable);
+       int first_uart_offset;
+};
+
+static struct pci_board_no_ids pci_boards[] __devinitdata = {
+       /*
+        * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
+        * Offset to get to next UART's registers,
+        * Register shift to use for memory-mapped I/O,
+        * Initialization function, first UART offset
+        */
+
+// Cards not tested are marked n/t
+// If you have one of these cards and it works for you, please tell me..
+
+/* titan_110l */       { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
+/* titan_210l */       { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
+/* netmos_9735 (n/t)*/ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* netmos_9835 (n/t)*/ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_2s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+};
+
+struct parport_serial_private {
+       int num_ser;
+       int line[20];
+       struct pci_board_no_ids ser;
+       int num_par;
+       struct parport *port[PARPORT_MAX];
+};
+
+static int __devinit get_pci_port (struct pci_dev *dev,
+                                  struct pci_board_no_ids *board,
+                                  struct serial_struct *req,
+                                  int idx)
+{
+       unsigned long port;
+       int base_idx;
+       int max_port;
+       int offset;
+
+       base_idx = SPCI_FL_GET_BASE(board->flags);
+       if (board->flags & SPCI_FL_BASE_TABLE)
+               base_idx += idx;
+
+       if (board->flags & SPCI_FL_REGION_SZ_CAP) {
+               max_port = pci_resource_len(dev, base_idx) / 8;
+               if (idx >= max_port)
+                       return 1;
+       }
+                       
+       offset = board->first_uart_offset;
+
+       /* Timedia/SUNIX uses a mixture of BARs and offsets */
+       /* Ugh, this is ugly as all hell --- TYT */
+       if(dev->vendor == PCI_VENDOR_ID_TIMEDIA )  /* 0x1409 */
+               switch(idx) {
+                       case 0: base_idx=0;
+                               break;
+                       case 1: base_idx=0; offset=8;
+                               break;
+                       case 2: base_idx=1; 
+                               break;
+                       case 3: base_idx=1; offset=8;
+                               break;
+                       case 4: /* BAR 2*/
+                       case 5: /* BAR 3 */
+                       case 6: /* BAR 4*/
+                       case 7: base_idx=idx-2; /* BAR 5*/
+               }
+  
+       port =  pci_resource_start(dev, base_idx) + offset;
+
+       if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
+               port += idx * (board->uart_offset ? board->uart_offset : 8);
+
+       if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
+               int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
+               req->port = port;
+               if (high_bits_offset)
+                       req->port_high = port >> high_bits_offset;
+               else
+                       req->port_high = 0;
+               return 0;
+       }
+       req->io_type = SERIAL_IO_MEM;
+       req->iomem_base = ioremap(port, board->uart_offset);
+       req->iomem_reg_shift = board->reg_shift;
+       req->port = 0;
+       return req->iomem_base ? 0 : 1;
+}
+
+/* Register the serial port(s) of a PCI card. */
+static int __devinit serial_register (struct pci_dev *dev,
+                                     const struct pci_device_id *id)
+{
+       struct pci_board_no_ids *board = &pci_boards[id->driver_data];
+       struct parport_serial_private *priv = pci_get_drvdata (dev);
+       struct serial_struct serial_req;
+       int base_baud;
+       int k;
+       int success = 0;
+
+       priv->ser = *board;
+       if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
+               return 1;
+
+       base_baud = board->base_baud;
+       if (!base_baud)
+               base_baud = BASE_BAUD;
+       memset (&serial_req, 0, sizeof (serial_req));
+
+       for (k = 0; k < board->num_ports; k++) {
+               int line;
+               serial_req.irq = dev->irq;
+               if (get_pci_port (dev, board, &serial_req, k))
+                       break;
+               serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
+               line = register_serial (&serial_req);
+               if (line < 0) {
+                       printk (KERN_DEBUG
+                               "parport_serial: register_serial failed\n");
+                       continue;
+               }
+               priv->line[priv->num_ser++] = line;
+               success = 1;
+       }
+
+       return success ? 0 : 1;
+}
+
+/* Register the parallel port(s) of a PCI card. */
+static int __devinit parport_register (struct pci_dev *dev,
+                                      const struct pci_device_id *id)
+{
+       struct parport_serial_private *priv = pci_get_drvdata (dev);
+       int i = id->driver_data, n;
+       int success = 0;
+
+       for (n = 0; n < cards[i].numports; n++) {
+               struct parport *port;
+               int lo = cards[i].addr[n].lo;
+               int hi = cards[i].addr[n].hi;
+               unsigned long io_lo, io_hi;
+               io_lo = pci_resource_start (dev, lo);
+               io_hi = 0;
+               if ((hi >= 0) && (hi <= 6))
+                       io_hi = pci_resource_start (dev, hi);
+               else if (hi > 6)
+                       io_lo += hi; /* Reinterpret the meaning of
+                                        "hi" as an offset (see SYBA
+                                        def.) */
+               /* TODO: test if sharing interrupts works */
+               printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
+                       "I/O at %#lx(%#lx)\n",
+                       parport_serial_pci_tbl[i].vendor,
+                       parport_serial_pci_tbl[i].device, io_lo, io_hi);
+               port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
+                                             PARPORT_DMA_NONE, dev);
+               if (port) {
+                       priv->port[priv->num_par++] = port;
+                       success = 1;
+               }
+       }
+
+       return success ? 0 : 1;
+}
+
+static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
+                                              const struct pci_device_id *id)
+{
+       struct parport_serial_private *priv;
+       int err;
+
+       priv = kmalloc (sizeof *priv, GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+       priv->num_ser = priv->num_par = 0;
+       pci_set_drvdata (dev, priv);
+
+       err = pci_enable_device (dev);
+       if (err) {
+               pci_set_drvdata (dev, NULL);
+               kfree (priv);
+               return err;
+       }
+
+       if (serial_register (dev, id) + parport_register (dev, id)) {
+               pci_set_drvdata (dev, NULL);
+               kfree (priv);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
+{
+       struct parport_serial_private *priv = pci_get_drvdata (dev);
+       int i;
+
+       // Serial ports
+       for (i = 0; i < priv->num_ser; i++) {
+               unregister_serial (priv->line[i]);
+
+               if (priv->ser.init_fn)
+                       (priv->ser.init_fn) (dev, &priv->ser, 0);
+       }
+       pci_set_drvdata (dev, NULL);
+       
+       // Parallel ports
+       for (i = 0; i < priv->num_par; i++)
+               parport_pc_unregister_port (priv->port[i]);
+
+       kfree (priv);
+       return;
+}
+
+static struct pci_driver parport_serial_pci_driver = {
+       name:           "parport_serial",
+       id_table:       parport_serial_pci_tbl,
+       probe:          parport_serial_pci_probe,
+       remove:         parport_serial_pci_remove,
+};
+
+
+static int __init parport_serial_init (void)
+{
+       return pci_module_init (&parport_serial_pci_driver);
+}
+
+static void __exit parport_serial_exit (void)
+{
+       pci_unregister_driver (&parport_serial_pci_driver);
+       return;
+}
+
+MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
+MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
+
+module_init(parport_serial_init);
+module_exit(parport_serial_exit);
index 9148534a87f378410c9a22642e1c71d41f5e69d0..ab876da8d6ca048db69c1c165f1ea2d5b77f60b0 100644 (file)
@@ -681,7 +681,7 @@ static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io)
            hd64465_port_map(
                io->start,
                io->stop - io->start + 1,
-               vaddrbase + io->start);
+               vaddrbase + io->start,0);
        } else {
            hd64465_port_unmap(
                sio->start,
index a6ec97b5c5436a4ff254138fd52a6ac80be56092..d753ff811300d24e5c83254629b964a621eb88e2 100644 (file)
@@ -5336,8 +5336,8 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
       if(!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
       {
         printk(WARN_LEAD "invalid scb during SEQ_SG_FIXUP flags:0x%x "
-               "scb->cmd:0x%x\n", p->host_no, CTL_OF_SCB(scb),
-               scb->flags, (unsigned int)scb->cmd);
+               "scb->cmd:0x%p\n", p->host_no, CTL_OF_SCB(scb),
+               scb->flags, scb->cmd);
         printk(INFO_LEAD "SCSISIGI 0x%x, SEQADDR 0x%x, SSTAT0 0x%x, SSTAT1 "
            "0x%x\n", p->host_no, CTL_OF_SCB(scb),
            aic_inb(p, SCSISIGI),
index e9d5cbf5329566ae62366e85a10bdec2afd122e6..a3742547fdf97e55310d89e3f08fb890eb038664 100644 (file)
@@ -98,14 +98,13 @@ if [ "$CONFIG_FB" = "y" ]; then
          bool '    CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX
       fi
    fi
+   tristate '  NEC PowerVR 2 display support' CONFIG_FB_PVR2
+   dep_bool '    Debug pvr2fb' CONFIG_FB_PVR2_DEBUG $CONFIG_FB_PVR2
    bool '  Epson 1355 framebuffer support' CONFIG_FB_E1355
    if [ "$CONFIG_FB_E1355" = "y" ]; then
       hex '    Register Base Address' CONFIG_E1355_REG_BASE a8000000
       hex '    Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000
    fi
-   if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
-      tristate '  Dreamcast Frame Buffer support' CONFIG_FB_DC
-   fi
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       if [ "$CONFIG_PCI" != "n" ]; then
         tristate '  Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX
@@ -262,7 +261,8 @@ if [ "$CONFIG_FB" = "y" ]; then
           "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
           "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
           "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y"  -o \
-          "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then
+          "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
+          "$CONFIG_FB_PVR2" = "y" ]; then
         define_tristate CONFIG_FBCON_CFB16 y
       else
         if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -276,7 +276,7 @@ if [ "$CONFIG_FB" = "y" ]; then
              "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \
              "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
              "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
-             "$CONFIG_FB_SA1100" = "m" ]; then
+             "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_PVR2" = "m" ]; then
            define_tristate CONFIG_FBCON_CFB16 m
         fi
       fi
@@ -284,14 +284,14 @@ if [ "$CONFIG_FB" = "y" ]; then
           "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
           "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
            "$CONFIG_FB_ATY128" = "y" -o \
-          "$CONFIG_FB_CYBER2000" = "y" ]; then
+          "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PVR2" = "y" ]; then
         define_tristate CONFIG_FBCON_CFB24 y
       else
         if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
              "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
              "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
              "$CONFIG_FB_ATY128" = "m" -o \
-             "$CONFIG_FB_CYBER2000" = "m" ]; then
+             "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_PVR2" = "m" ]; then
            define_tristate CONFIG_FBCON_CFB24 m
         fi
       fi
@@ -302,7 +302,8 @@ if [ "$CONFIG_FB" = "y" ]; then
           "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
           "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
           "$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
-          "$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_SIS" = "y" ]; then
+          "$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_SIS" = "y" -o \
+          "$CONFIG_FB_PVR2" = "y" ]; then
         define_tristate CONFIG_FBCON_CFB32 y
       else
         if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -312,7 +313,8 @@ if [ "$CONFIG_FB" = "y" ]; then
              "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
              "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
              "$CONFIG_FB_3DFX" = "m" -o \
-             "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then
+             "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
+             "$CONFIG_FB_PVR2" = "m" ]; then
            define_tristate CONFIG_FBCON_CFB32 m
         fi
       fi
index 3cae285cbae128d66e5459c81abf81adc8bb5aa9..52f2684f2f9fcc1a1bced2fb13318e7b13c4e7fb 100644 (file)
@@ -101,7 +101,7 @@ obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o  
 obj-$(CONFIG_FB_HIT)              += hitfb.o fbgen.o
 obj-$(CONFIG_FB_E1355)            += epson1355fb.o fbgen.o
-obj-$(CONFIG_FB_DC)               += dcfb.o fbgen.o
+obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 
 # Generic Low Level Drivers
 
diff --git a/drivers/video/dcfb.c b/drivers/video/dcfb.c
deleted file mode 100644 (file)
index 6b72ee1..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- *     $Id: dcfb.c,v 1.1 2001/04/01 15:02:51 yaegashi Exp $
- *     SEGA Dreamcast framebuffer
- */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/nubus.h>
-#include <linux/init.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-
-#include <linux/fb.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
-
-#define BORDERRGB      0xa05f8040
-#define DISPLAYMODE    0xa05f8044
-#define ALPHAMODE      0xa05f8048
-#define DISPLAYALIGN   0xa05f804c
-#define BASEOFFSET1    0xa05f8050
-#define BASEOFFSET2    0xa05f8054
-#define DISPLAYSIZE    0xa05f805c
-#define SYNCMODE       0xa05f80d0
-#define VERTICALRANGE  0xa05f80dc
-#define HORIZPOSITION  0xa05f80ec
-#define VERTPOSITION   0xa05f80f0
-#define PALETTEMODE    0xa05f8108
-#define VIDEOOUTPUT    0xa0702c00
-
-static unsigned long dc_parm_vga_16bpp[] = {
-    DISPLAYMODE,       0x00800005,
-    BASEOFFSET1,       0,
-    BASEOFFSET2,       640*2,
-    DISPLAYSIZE,       (1<<20)+((480-1)<<10)+(640*2/4-1),
-    SYNCMODE,          0x100,
-    VERTPOSITION,      0x00230023,
-    VERTICALRANGE,     0x00280208,
-    HORIZPOSITION,     0x00000090,
-    VIDEOOUTPUT,       0,
-    0, 0,
-};
-    
-static unsigned long dc_parm_vga_32bpp[] = {
-    DISPLAYMODE,       0x0080000d,
-    BASEOFFSET1,       0,
-    BASEOFFSET2,       640*4,
-    DISPLAYSIZE,       (1<<20)+((480-1)<<10)+(640*4/4-1),
-    SYNCMODE,          0x100,
-    VERTPOSITION,      0x00230023,
-    VERTICALRANGE,     0x00280208,
-    HORIZPOSITION,     0x00000090,
-    VIDEOOUTPUT,       0,
-    0, 0,
-};
-
-static unsigned long *dc_parm_vga[] = {
-    dc_parm_vga_16bpp,
-    dc_parm_vga_32bpp,
-};
-
-static unsigned long dc_parm_composite_16bpp[] = {
-    DISPLAYMODE,       0x00000005,
-    BASEOFFSET1,       0,
-    BASEOFFSET2,       640*2,
-    DISPLAYSIZE,       ((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
-    SYNCMODE,          0x150,
-    VERTPOSITION,      0x00120012,
-    VERTICALRANGE,     0x00240204,
-    HORIZPOSITION,     0x000000a4,
-    VIDEOOUTPUT,       0x300,
-    0, 0,
-};
-    
-static unsigned long dc_parm_composite_32bpp[] = {
-    DISPLAYMODE,       0x0000000d,
-    BASEOFFSET1,       0,
-    BASEOFFSET2,       640*4,
-    DISPLAYSIZE,       ((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
-    SYNCMODE,          0x150,
-    VERTPOSITION,      0x00120012,
-    VERTICALRANGE,     0x00240204,
-    HORIZPOSITION,     0x000000a4,
-    VIDEOOUTPUT,       0x300,
-    0, 0,
-};
-
-static unsigned long *dc_parm_composite[] = {
-    dc_parm_composite_16bpp,
-    dc_parm_composite_32bpp,
-};
-
-static unsigned long dc_parm_interlace_16bpp[] = {
-    DISPLAYMODE,       0x00000005,
-    BASEOFFSET1,       0,
-    BASEOFFSET2,       640*2,
-    DISPLAYSIZE,       ((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
-    SYNCMODE,          0x150,
-    VERTPOSITION,      0x00120012,
-    VERTICALRANGE,     0x00240204,
-    HORIZPOSITION,     0x000000a4,
-    VIDEOOUTPUT,       0,
-    0, 0,
-};
-    
-static unsigned long dc_parm_interlace_32bpp[] = {
-    DISPLAYMODE,       0x0000000d,
-    BASEOFFSET1,       0,
-    BASEOFFSET2,       640*4,
-    DISPLAYSIZE,       ((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
-    SYNCMODE,          0x150,
-    VERTPOSITION,      0x00120012,
-    VERTICALRANGE,     0x00240204,
-    HORIZPOSITION,     0x000000a4,
-    VIDEOOUTPUT,       0,
-    0, 0,
-};
-
-static unsigned long *dc_parm_interlace[] = {
-    dc_parm_interlace_16bpp,
-    dc_parm_interlace_32bpp,
-};
-
-struct dcfb_info {
-    struct fb_info_gen gen;
-};
-
-struct dcfb_par
-{
-    int x, y;
-    int bpp;
-};
-
-static struct dcfb_info fb_info;
-static struct dcfb_par current_par;
-static int current_par_valid = 0;
-static struct display disp;
-
-static union {
-#ifdef FBCON_HAS_CFB16
-    u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-    u32 cfb32[16];
-#endif
-} fbcon_cmap;
-
-static unsigned long **dc_parms;
-static unsigned long dc_videobase, dc_videosize;
-static struct fb_var_screeninfo default_var;
-
-int dcfb_init(void);
-
-static void dcfb_set_par(struct dcfb_par *par, const struct fb_info *info);
-static void dcfb_encode_var(struct fb_var_screeninfo *var, 
-                             struct dcfb_par *par,
-                             const struct fb_info *info);
-
-
-/*
- *     Check cable type.
- *     0: VGA, 2: RGB, 3: Composite
- */
-
-#define        PCTRA   0xff80002c
-#define PDTRA  0xff800030
-
-static int dcfb_cable_check(void)
-{
-    unsigned long temp = ctrl_inl(PCTRA);
-    temp &= 0xfff0ffff;
-    temp |= 0x000a0000;
-    ctrl_outl(temp, PCTRA);
-    return (ctrl_inw(PDTRA)>>8)&3;
-}
-
-static void dcfb_detect(void)
-{
-    struct dcfb_par par;
-    int cable = dcfb_cable_check();
-    unsigned long **parm_list[4] = {
-       dc_parm_vga, dc_parm_vga, dc_parm_interlace, dc_parm_composite,
-    };
-    char *cable_name[] = { "VGA", "VGA", "Interlace", "Composite", };
-
-    dc_videobase = 0xa5000000;
-    dc_videosize = 0x00200000;
-
-    par.x = 640;
-    par.y = 480;
-    par.bpp = 32;
-    dc_parms = parm_list[cable];
-    printk(KERN_INFO "Dreamcast video cable detected: %s.\n", cable_name[cable]);
-
-    dcfb_set_par(&par, NULL);
-    dcfb_encode_var(&default_var, &par, NULL);
-}
-
-static int dcfb_encode_fix(struct fb_fix_screeninfo *fix,
-                           struct dcfb_par *par,
-                           const struct fb_info *info)
-{
-    memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-
-    strcpy(fix->id, "SEGA Dreamcast");
-    fix->smem_start = dc_videobase;
-    fix->smem_len = dc_videosize;
-    fix->type = FB_TYPE_PACKED_PIXELS;
-    fix->type_aux = 0;
-    fix->visual = FB_VISUAL_TRUECOLOR;
-    fix->xpanstep = 0;
-    fix->ypanstep = 0;
-    fix->ywrapstep = 0;
-
-    switch(par->bpp) {
-    default:
-    case 16:
-       fix->line_length = par->x*2;
-       break;
-    case 32:
-       fix->line_length = par->x*4;
-       break;
-    }
-
-    return 0;
-}
-
-
-static int dcfb_decode_var(struct fb_var_screeninfo *var,
-                           struct dcfb_par *par,
-                           const struct fb_info *info)
-{
-    par->x = var->xres;
-    par->y = var->yres;
-    par->bpp = var->bits_per_pixel;
-    return 0;
-}
-
-
-static void dcfb_encode_var(struct fb_var_screeninfo *var, 
-                            struct dcfb_par *par,
-                            const struct fb_info *info)
-{
-    memset(var, 0, sizeof(*var));
-
-    var->xres = par->x;
-    var->yres = par->y;
-    var->xres_virtual = var->xres;
-    var->yres_virtual = var->yres;
-    var->xoffset = 0;
-    var->yoffset = 0;
-    var->bits_per_pixel = par->bpp;
-    var->grayscale = 0;
-    var->transp.offset = 0;
-    var->transp.length = 0;
-    var->transp.msb_right = 0;
-    var->nonstd = 0;
-    var->activate = 0;
-    var->height = -1;
-    var->width = -1;
-    var->vmode = FB_VMODE_NONINTERLACED;
-    var->pixclock = 0;
-    var->sync = 0;
-    var->left_margin = 0;
-    var->right_margin = 0;
-    var->upper_margin = 0;
-    var->lower_margin = 0;
-    var->hsync_len = 0;
-    var->vsync_len = 0;
-
-    switch (var->bits_per_pixel) {
-
-       case 16:        /* RGB 565 */
-           var->red.offset = 11;
-           var->red.length = 5;
-           var->green.offset = 5;
-           var->green.length = 6;
-           var->blue.offset = 0;
-           var->blue.length = 5;
-           var->transp.offset = 0;
-           var->transp.length = 0;
-           break;
-
-       case 32:
-           var->red.offset = 16;
-           var->red.length = 8;
-           var->green.offset = 8;
-           var->green.length = 8;
-           var->blue.offset = 0;
-           var->blue.length = 8;
-           var->transp.offset = 0;
-           var->transp.length = 0;
-           break;
-
-    }
-
-    var->red.msb_right = 0;
-    var->green.msb_right = 0;
-    var->blue.msb_right = 0;
-    var->transp.msb_right = 0;
-}
-
-
-static void dcfb_get_par(struct dcfb_par *par, const struct fb_info *info)
-{
-    *par = current_par;
-}
-
-
-static void dcfb_set_par(struct dcfb_par *par, const struct fb_info *info)
-{
-    unsigned long a, d, *p;
-
-    current_par = *par;
-    current_par_valid = 1;
-
-    switch(par->bpp) {
-    default:
-    case 16:
-       p = dc_parms[0];
-       break;
-    case 32:
-       p = dc_parms[1];
-       break;
-    }
-
-    ctrl_outl(0, 0xa05f8008);  /* reset? */
-    ctrl_outl(0, BORDERRGB);
-
-    while(1) {
-       a = *p++; d = *p++;
-       if (!a) break;
-       ctrl_outl(d, a);
-    }
-
-}
-
-static struct {
-  u_int red, green, blue;
-} palette[256];
-
-static int dcfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                         u_int *transp, struct fb_info *info)
-{
-    if (regno > 255)
-       return 1;       
-
-    *red = palette[regno].red;
-    *green = palette[regno].green;
-    *blue = palette[regno].blue;
-    *transp = 0;
-    
-    return 0;
-}
-
-
-static int dcfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                         u_int transp, struct fb_info *info)
-{
-    if (regno > 255)
-       return 1;
-
-    palette[regno].red = red;
-    palette[regno].green = green;
-    palette[regno].blue = blue;
-    
-    if(regno<16) {
-       switch(current_par.bpp) {
-#ifdef FBCON_HAS_CFB16
-       case 16:
-           fbcon_cmap.cfb16[regno] =
-               ((red   & 0xf800)      ) |
-               ((green & 0xfc00) >>  5) |
-               ((blue  & 0xf800) >> 11);
-           break;
-#endif
-#ifdef FBCON_HAS_CFB32
-       case 32:
-           fbcon_cmap.cfb32[regno] =
-               ((red   & 0xff00) <<  8) |
-               ((green & 0xff00)      ) |
-               ((blue  & 0xff00) >>  8);
-           break;
-#endif
-       }
-    }
-
-    return 0;
-}
-
-static int dcfb_blank(int blank_mode, const struct fb_info *info)
-{
-    return 0;
-}
-
-
-static void dcfb_set_disp(const void *par, struct display *disp,
-                          struct fb_info_gen *info)
-{
-    disp->screen_base = (void *)dc_videobase;
-    disp->scrollmode = SCROLL_YREDRAW;
-
-    switch(((struct dcfb_par *)par)->bpp) {
-#ifdef FBCON_HAS_CFB16
-    case 16:
-       disp->dispsw = &fbcon_cfb16;
-       disp->dispsw_data = fbcon_cmap.cfb16;
-       break;
-#endif
-#ifdef FBCON_HAS_CFB32
-    case 32:
-       disp->dispsw = &fbcon_cfb32;
-       disp->dispsw_data = fbcon_cmap.cfb32;
-       break;
-#endif
-    default:
-       disp->dispsw = &fbcon_dummy;
-    }
-}
-
-
-struct fbgen_hwswitch dcfb_switch = {
-    dcfb_detect,
-    dcfb_encode_fix,
-    dcfb_decode_var,
-    dcfb_encode_var,
-    dcfb_get_par,
-    dcfb_set_par,
-    dcfb_getcolreg,
-    dcfb_setcolreg,
-    NULL,
-    dcfb_blank,
-    dcfb_set_disp
-};
-
-static struct fb_ops dcfb_ops = {
-       owner:          THIS_MODULE,
-       fb_get_fix:     fbgen_get_fix,
-       fb_get_var:     fbgen_get_var,
-       fb_set_var:     fbgen_set_var,
-       fb_get_cmap:    fbgen_get_cmap,
-       fb_set_cmap:    fbgen_set_cmap,
-};
-
-
-int __init dcfb_init(void)
-{
-    strcpy(fb_info.gen.info.modename, "SEGA Dreamcast");
-    fb_info.gen.info.node = -1;
-    fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
-    fb_info.gen.info.fbops = &dcfb_ops;
-    fb_info.gen.info.disp = &disp;
-    fb_info.gen.info.changevar = NULL;
-    fb_info.gen.info.switch_con = &fbgen_switch;
-    fb_info.gen.info.updatevar = &fbgen_update_var;
-    fb_info.gen.info.blank = &fbgen_blank;
-    fb_info.gen.parsize = sizeof(struct dcfb_par);
-    fb_info.gen.fbhw = &dcfb_switch;
-    fb_info.gen.fbhw->detect();
-    
-    fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
-    disp.var.activate = FB_ACTIVATE_NOW;
-    fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
-    fbgen_set_disp(-1, &fb_info.gen);
-    fbgen_install_cmap(0, &fb_info.gen);
-    
-    if(register_framebuffer(&fb_info.gen.info)<0) return -EINVAL;
-    
-    printk(KERN_INFO "fb%d: %s frame buffer device\n",
-          GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
-    
-    return 0;
-}
-
-
-void dcfb_cleanup(struct fb_info *info)
-{
-    unregister_framebuffer(info);
-}
-
-
-#ifdef MODULE
-int init_module(void)
-{
-    return dcfb_init();
-}
-
-void cleanup_module(void)
-{
-    dcfb_cleanup(void);
-}
-#endif
index 70a975b2149d4b9733fc9caee9fb6a964902072e..ab5696291ded0fa41d642911cfa75fd50e5b808b 100644 (file)
@@ -122,8 +122,9 @@ extern int radeonfb_init(void);
 extern int radeonfb_setup(char*);
 extern int e1355fb_init(void);
 extern int e1355fb_setup(char*);
-extern int dcfb_init(void);
-  
+extern int pvr2fb_init(void);
+extern int pvr2fb_setup(char*);
+
 static struct {
        const char *name;
        int (*init)(void);
@@ -270,8 +271,8 @@ static struct {
 #ifdef CONFIG_FB_E1355
        { "e1355fb", e1355fb_init, e1355fb_setup },
 #endif
-#ifdef CONFIG_FB_DC
-       { "dcfb", dcfb_init, NULL },
+#ifdef CONFIG_FB_PVR2
+       { "pvr2", pvr2fb_init, pvr2fb_setup },
 #endif
 
        /*
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
new file mode 100644 (file)
index 0000000..5555493
--- /dev/null
@@ -0,0 +1,1171 @@
+/* drivers/video/pvr2fb.c
+ *
+ * Frame buffer and fbcon support for the NEC PowerVR2 found within the Sega
+ * Dreamcast.
+ *
+ * Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org>
+ * Copyright (c) 2001 Paul Mundt  <lethal@chaoticdreams.org>
+ *
+ * This file is part of the LinuxDC project (linuxdc.sourceforge.net).
+ *
+ */
+
+/*
+ * This driver is mostly based on the excellent amifb and vfb sources.  It uses
+ * an odd scheme for converting hardware values to/from framebuffer values, here are
+ * some hacked-up formulas:
+ *
+ *  The Dreamcast has screen offsets from each side of it's four borders and the start
+ *  offsets of the display window.  I used these values to calculate 'pseudo' values
+ *  (think of them as placeholders) for the fb video mode, so that when it came time
+ *  to convert these values back into their hardware values, I could just add mode-
+ *  specific offsets to get the correct mode settings:
+ *
+ *      left_margin = diwstart_h - borderstart_h;
+ *      right_margin = borderstop_h - (diwstart_h + xres);
+ *      upper_margin = diwstart_v - borderstart_v;
+ *      lower_margin = borderstop_v - (diwstart_h + yres);
+ *
+ *      hsync_len = borderstart_h + (hsync_total - borderstop_h);
+ *      vsync_len = borderstart_v + (vsync_total - borderstop_v);
+ *
+ *  Then, when it's time to convert back to hardware settings, the only constants
+ *  are the borderstart_* offsets, all other values are derived from the fb video
+ *  mode:
+ *  
+ *      // PAL
+ *      borderstart_h = 116;
+ *      borderstart_v = 44;
+ *      ...
+ *      borderstop_h = borderstart_h + hsync_total - hsync_len;
+ *      ...
+ *      diwstart_v = borderstart_v - upper_margin;
+ *
+ *  However, in the current implementation, the borderstart values haven't had
+ *  the benefit of being fully researched, so some modes may be broken.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#ifdef CONFIG_SH_DREAMCAST
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/dc_sysasic.h>
+#endif
+
+#ifdef CONFIG_MTRR
+  #include <asm/mtrr.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#ifdef CONFIG_FB_PVR2_DEBUG
+#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#  define DPRINTK(fmt, args...)
+#endif
+
+/* 2D video registers */
+#define DISP_BASE 0xa05f8000
+
+#define DISP_BRDRCOLR (DISP_BASE + 0x40)
+#define DISP_DIWMODE (DISP_BASE + 0x44)
+#define DISP_DIWADDRL (DISP_BASE + 0x50)
+#define DISP_DIWADDRS (DISP_BASE + 0x54)
+#define DISP_DIWSIZE (DISP_BASE + 0x5c)
+#define DISP_SYNCCONF (DISP_BASE + 0xd0)
+#define DISP_BRDRHORZ (DISP_BASE + 0xd4)
+#define DISP_SYNCSIZE (DISP_BASE + 0xd8)
+#define DISP_BRDRVERT (DISP_BASE + 0xdc)
+#define DISP_DIWCONF (DISP_BASE + 0xe8)
+#define DISP_DIWHSTRT (DISP_BASE + 0xec)
+#define DISP_DIWVSTRT (DISP_BASE + 0xf0)
+
+/* Pixel clocks, one for TV output, doubled for VGA output */
+#define TV_CLK 74239
+#define VGA_CLK 37119
+
+/* This is for 60Hz - the VTOTAL is doubled for interlaced modes */
+#define PAL_HTOTAL 863
+#define PAL_VTOTAL 312
+#define NTSC_HTOTAL 857
+#define NTSC_VTOTAL 262
+
+enum { CT_VGA, CT_NONE, CT_RGB, CT_COMPOSITE };
+
+enum { VO_PAL, VO_NTSC, VO_VGA };
+
+struct pvr2_params { u_short val; char *name; };
+static struct pvr2_params cables[] __initdata = {
+       { CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
+};
+
+static struct pvr2_params outputs[] __initdata = {
+       { VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
+};
+
+/*
+ * This describes the current video mode
+ */
+
+static struct pvr2fb_par {
+
+       int xres;
+       int yres;
+       int vxres;
+       int vyres;
+       int xoffset;
+       int yoffset;
+       u_short bpp;
+
+       u_long pixclock;
+       u_short hsync_total;    /* Clocks/line */
+       u_short vsync_total;    /* Lines/field */
+       u_short borderstart_h;
+       u_short borderstop_h;
+       u_short borderstart_v;
+       u_short borderstop_v;
+       u_short diwstart_h;     /* Horizontal offset of the display field */
+       u_short diwstart_v;     /* Vertical offset of the display field, for
+                                  interlaced modes, this is the long field */
+       u_long disp_start;      /* Address of image within VRAM */
+
+       u_long next_line;       /* Modulo for next line */
+
+       u_char is_interlaced;   /* Is the display interlaced? */
+       u_char is_doublescan;   /* Are scanlines output twice? (doublescan) */
+       u_char is_lowres;       /* Is horizontal pixel-doubling enabled? */
+
+       u_long bordercolor;     /* RGB888 format border color */
+
+       u_long vmode;
+       
+} currentpar;
+
+static int currcon = 0;
+static int currbpp;
+static struct display disp;
+static struct fb_info fb_info;
+static int pvr2fb_inverse = 0;
+
+static struct { u_short red, green, blue, alpha; } palette[256];
+static union {
+#ifdef FBCON_HAS_CFB16
+       u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+       u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+       u32 cfb32[16];
+#endif
+} fbcon_cmap;
+
+static char pvr2fb_name[16] = "NEC PowerVR2";
+
+#define VIDEOMEMSIZE (8*1024*1024)
+static u_long videomemory = 0xa5000000, videomemorysize = VIDEOMEMSIZE;
+static int cable_type = -1;
+static int video_output = -1;
+
+#ifdef CONFIG_MTRR
+static int enable_mtrr = 1;
+static int mtrr_handle;
+#endif
+
+/*
+ * We do all updating, blanking, etc. during the vertical retrace period
+ */
+
+static u_short do_vmode_full = 0;      /* Change the video mode */
+static u_short do_vmode_pan = 0;       /* Update the video mode */
+static short do_blank = 0;             /* (Un)Blank the screen */
+
+static u_short is_blanked = 0;         /* Is the screen blanked? */
+
+/* Interface used by the world */
+
+int pvr2fb_setup(char*);
+
+static int pvr2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                            struct fb_info *info);
+static int pvr2fb_get_var(struct fb_var_screeninfo *var, int con,
+                            struct fb_info *info);
+static int pvr2fb_set_var(struct fb_var_screeninfo *var, int con,
+                            struct fb_info *info);
+static int pvr2fb_pan_display(struct fb_var_screeninfo *var, int con,
+                                struct fb_info *info);
+static int pvr2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+                             struct fb_info *info);
+static int pvr2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+                             struct fb_info *info);
+
+       /*
+        * Interface to the low level console driver
+        */
+
+static int pvr2fbcon_switch(int con, struct fb_info *info);
+static int pvr2fbcon_updatevar(int con, struct fb_info *info);
+static void pvr2fbcon_blank(int blank, struct fb_info *info);
+
+       /*
+        * Internal/hardware-specific routines
+        */
+
+static void do_install_cmap(int con, struct fb_info *info);
+static u_long get_line_length(int xres_virtual, int bpp);
+static void set_color_bitfields(struct fb_var_screeninfo *var);
+static int pvr2_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                            u_int *transp, struct fb_info *info);
+static int pvr2_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                            u_int transp, struct fb_info *info);
+
+static int pvr2_encode_fix(struct fb_fix_screeninfo *fix,
+                             struct pvr2fb_par *par);
+static int pvr2_decode_var(struct fb_var_screeninfo *var,
+                          struct pvr2fb_par *par);
+static int pvr2_encode_var(struct fb_var_screeninfo *var,
+                          struct pvr2fb_par *par);
+static void pvr2_get_par(struct pvr2fb_par *par);
+static void pvr2_set_var(struct fb_var_screeninfo *var);
+static void pvr2_pan_var(struct fb_var_screeninfo *var);
+static int pvr2_update_par(void);
+static void pvr2_update_display(void);
+static void pvr2_init_display(void);
+static void pvr2_do_blank(void);
+static void pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
+static int pvr2_init_cable(void);
+static int pvr2_get_param(const struct pvr2_params *p, const char *s,
+                            int val, int size);
+
+static struct fb_ops pvr2fb_ops = {
+       owner:          THIS_MODULE,
+       fb_get_fix:     pvr2fb_get_fix,
+       fb_get_var:     pvr2fb_get_var,
+       fb_set_var:     pvr2fb_set_var,
+       fb_get_cmap:    pvr2fb_get_cmap,
+       fb_set_cmap:    pvr2fb_set_cmap,
+       fb_pan_display: pvr2fb_pan_display,
+};
+
+static struct fb_videomode pvr2_modedb[] __initdata = {
+
+    /*
+     * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with
+     * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
+     * NTSC, so it shouldn't be a problem (I hope).
+     */
+
+    {
+       /* 640x480 @ 60Hz interlaced (NTSC) */
+       "ntsc_640x480i", 60, 640, 480, TV_CLK, 38, 33, 0, 18, 146, 26,
+       FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+    },
+
+    {
+       /* 640x240 @ 60Hz (NTSC) */
+       /* XXX: Broken! Don't use... */
+       "ntsc_640x240", 60, 640, 240, TV_CLK, 38, 33, 0, 0, 146, 22,
+       FB_SYNC_BROADCAST, FB_VMODE_YWRAP
+    },
+
+    {
+       /* 640x480 @ 60hz (VGA) */
+       "vga_640x480", 60, 640, 480, 38, 33, 0, 18, 146, 26,
+       0, FB_VMODE_YWRAP
+    },
+
+};
+
+#define NUM_TOTAL_MODES  ARRAY_SIZE(pvr2_modedb)
+
+#define DEFMODE_NTSC   0
+#define DEFMODE_PAL    0
+#define DEFMODE_VGA    2
+
+static int defmode = DEFMODE_NTSC;
+static const char *mode_option __initdata = NULL;
+
+/* Get the fixed part of the display */
+
+static int pvr2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                            struct fb_info *info)
+{
+       struct pvr2fb_par par;
+
+       if (con == -1)
+               pvr2_get_par(&par);
+       else {
+               int err;
+
+               if ((err = pvr2_decode_var(&fb_display[con].var, &par)))
+                       return err;
+       }
+       return pvr2_encode_fix(fix, &par);
+}
+
+/* Get the user-defined part of the display */
+
+static int pvr2fb_get_var(struct fb_var_screeninfo *var, int con,
+                            struct fb_info *info)
+{
+       int err = 0;
+
+       if (con == -1) {
+               struct pvr2fb_par par;
+
+               pvr2_get_par(&par);
+               err = pvr2_encode_var(var, &par);
+       } else
+               *var = fb_display[con].var;
+       
+       return err;
+}
+
+/* Set the user-defined part of the display */
+
+static int pvr2fb_set_var(struct fb_var_screeninfo *var, int con,
+                            struct fb_info *info)
+{
+       int err, activate = var->activate;
+       int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+       struct pvr2fb_par par;
+
+       struct display *display;
+       if (con >= 0)
+               display = &fb_display[con];
+       else
+               display = &disp;        /* used during initialization */
+
+       /*
+        * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+        * as FB_VMODE_SMOOTH_XPAN is only used internally
+        */
+
+       if (var->vmode & FB_VMODE_CONUPDATE) {
+               var->vmode |= FB_VMODE_YWRAP;
+               var->xoffset = display->var.xoffset;
+               var->yoffset = display->var.yoffset;
+       }
+       if ((err = pvr2_decode_var(var, &par)))
+               return err;
+       pvr2_encode_var(var, &par);
+
+       /* Do memory check and bitfield set here?? */
+
+       if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+               oldxres = display->var.xres;
+               oldyres = display->var.yres;
+               oldvxres = display->var.xres_virtual;
+               oldvyres = display->var.yres_virtual;
+               oldbpp = display->var.bits_per_pixel;
+               display->var = *var;
+               if (oldxres != var->xres || oldyres != var->yres ||
+                   oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+                   oldbpp != var->bits_per_pixel) {
+                       struct fb_fix_screeninfo fix;
+
+                       pvr2_encode_fix(&fix, &par);
+                       display->screen_base = (char *)fix.smem_start;
+                       display->visual = fix.visual;
+                       display->type = fix.type;
+                       display->type_aux = fix.type_aux;
+                       display->ypanstep = fix.ypanstep;
+                       display->ywrapstep = fix.ywrapstep;
+                       display->line_length = fix.line_length;
+                       display->can_soft_blank = 1;
+                       display->inverse = pvr2fb_inverse;
+                       switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB16
+                           case 16:
+                               display->dispsw = &fbcon_cfb16;
+                               display->dispsw_data = fbcon_cmap.cfb16;
+                               break;
+#endif
+#ifdef FBCON_HAS_CFB24
+                           case 24:
+                               display->dispsw = &fbcon_cfb24;
+                               display->dispsw_data = fbcon_cmap.cfb24;
+                               break;
+#endif
+#ifdef FBCON_HAS_CFB32
+                           case 32:
+                               display->dispsw = &fbcon_cfb32;
+                               display->dispsw_data = fbcon_cmap.cfb32;
+                               break;
+#endif
+                           default:
+                               display->dispsw = &fbcon_dummy;
+                               break;
+                       }
+                       if (fb_info.changevar)
+                               (*fb_info.changevar)(con);
+               }
+               if (oldbpp != var->bits_per_pixel) {
+                       if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+                               return err;
+                       do_install_cmap(con, info);
+               }
+               if (con == currcon)
+                       pvr2_set_var(&display->var);
+       }
+
+       return 0;
+}
+
+/*
+ * Pan or wrap the display.
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YRAP flag
+ */
+
+static int pvr2fb_pan_display(struct fb_var_screeninfo *var, int con,
+                                struct fb_info *info)
+{
+       if (var->vmode & FB_VMODE_YWRAP) {
+               if (var->yoffset<0 || var->yoffset >=
+                   fb_display[con].var.yres_virtual || var->xoffset)
+                       return -EINVAL;
+        } else {
+               if (var->xoffset+fb_display[con].var.xres >
+                   fb_display[con].var.xres_virtual ||
+                   var->yoffset+fb_display[con].var.yres >
+                   fb_display[con].var.yres_virtual)
+                   return -EINVAL;
+       }
+       if (con == currcon)
+               pvr2_pan_var(var);
+       fb_display[con].var.xoffset = var->xoffset;
+       fb_display[con].var.yoffset = var->yoffset;
+       if (var->vmode & FB_VMODE_YWRAP)
+               fb_display[con].var.vmode |= FB_VMODE_YWRAP;
+       else
+               fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+                       
+       return 0;
+}
+
+/* Get the colormap */
+
+static int pvr2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+                             struct fb_info *info)
+{
+       if (con == currcon) /* current console? */
+               return fb_get_cmap(cmap, kspc, pvr2_getcolreg, info);
+       else if (fb_display[con].cmap.len) /* non default colormap? */
+               fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+       else
+               fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+                            cmap, kspc ? 0 : 2);
+       return 0;
+}
+
+/* Set the colormap */
+
+static int pvr2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+                            struct fb_info *info)
+{
+       int err;
+
+       if (!fb_display[con].cmap.len) {        /* no colormap allocated? */
+               if ((err = fb_alloc_cmap(&fb_display[con].cmap,
+                                        1<<fb_display[con].var.bits_per_pixel,
+                                        0)))
+                        return err;
+       }
+       if (con == currcon)                     /* current console? */
+               return fb_set_cmap(cmap, kspc, pvr2_setcolreg, info);
+       else
+               fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+
+       return 0;
+}
+
+static int pvr2fbcon_switch(int con, struct fb_info *info)
+{
+       /* Do we have to save the colormap? */
+       if (fb_display[currcon].cmap.len)
+               fb_get_cmap(&fb_display[currcon].cmap, 1, pvr2_getcolreg, info);
+
+       currcon = con;
+       pvr2_set_var(&fb_display[con].var);
+       /* Install new colormap */
+       do_install_cmap(con, info);
+       return 0;
+}
+
+static int pvr2fbcon_updatevar(int con, struct fb_info *info)
+{
+       pvr2_pan_var(&fb_display[con].var);
+       return 0;
+}
+
+static void pvr2fbcon_blank(int blank, struct fb_info *info)
+{
+       do_blank = blank ? blank : -1;
+}
+
+/* Setup the colormap */
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+       if (con != currcon)
+               return;
+       if (fb_display[con].cmap.len)
+               fb_set_cmap(&fb_display[con].cmap, 1, pvr2_setcolreg, info);
+       else
+               fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+                            1, pvr2_setcolreg, info);
+}
+
+static inline u_long get_line_length(int xres_virtual, int bpp)
+{
+       return (u_long)((((xres_virtual*bpp)+31)&~31) >> 3);
+}
+
+static void set_color_bitfields(struct fb_var_screeninfo *var)
+{
+       switch (var->bits_per_pixel) {
+           case 16:        /* RGB 565 */
+               var->red.offset = 11;    var->red.length = 5;
+               var->green.offset = 5;   var->green.length = 6;
+               var->blue.offset = 0;    var->blue.length = 5;
+               var->transp.offset = 0;  var->transp.length = 0;
+               break;
+           case 24:        /* RGB 888 */
+               var->red.offset = 16;    var->red.length = 8;
+               var->green.offset = 8;   var->green.length = 8;
+               var->blue.offset = 0;    var->blue.length = 8;
+               var->transp.offset = 0;  var->transp.length = 0;
+               break;
+           case 32:        /* ARGB 8888 */
+               var->red.offset = 16;    var->red.length = 8;
+               var->green.offset = 8;   var->green.length = 8;
+               var->blue.offset = 0;    var->blue.length = 8;
+               var->transp.offset = 24; var->transp.length = 8;
+               break;
+       }
+}
+
+static int pvr2_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                            u_int *transp, struct fb_info *info)
+{
+       if (regno > 255)
+           return 1;
+       
+       *red = palette[regno].red;
+       *green = palette[regno].green;
+       *blue = palette[regno].blue;
+       *transp = 0;
+       return 0;
+}
+       
+static int pvr2_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                            u_int transp, struct fb_info *info)
+{
+       if (regno > 255)
+               return 1;
+
+       palette[regno].red = red;
+       palette[regno].green = green;
+       palette[regno].blue = blue;
+
+       if (regno < 16) {
+               switch (currbpp) {
+#ifdef FBCON_HAS_CFB16
+                   case 16: /* RGB 565 */
+                       fbcon_cmap.cfb16[regno] = (red & 0xf800) |
+                                                 ((green & 0xf800) >> 6) |
+                                                 ((blue & 0xf800) >> 11);
+                       break;
+#endif
+#ifdef FBCON_HAS_CFB24
+                   case 24: /* RGB 888 */
+                       red >>= 8; green >>= 8; blue >>= 8;
+                       fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | blue;
+                       break;
+#endif
+#ifdef FBCON_HAS_CFB32
+                   case 32: /* ARGB 8888 */
+                       red >>= 8; green >>= 8; blue >>= 8;
+                       fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue;
+                       break;
+#endif
+                   default:
+                       DPRINTK("Invalid bit depth %d?!?\n", currbpp);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+
+static int pvr2_encode_fix(struct fb_fix_screeninfo *fix,
+                             struct pvr2fb_par *par)
+{
+       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+       strcpy(fix->id, pvr2fb_name);
+       fix->smem_start = videomemory;
+       fix->smem_len = videomemorysize;
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       fix->type_aux = 0;
+       fix->visual = FB_VISUAL_TRUECOLOR;
+
+       if (par->vmode & FB_VMODE_YWRAP) {
+               fix->ywrapstep = 1;
+               fix->xpanstep = fix->ypanstep = 0;
+       } else {
+               fix->ywrapstep = 0;
+               fix->xpanstep = 1;
+               fix->ypanstep = 1;
+       }
+       fix->line_length = par->next_line;
+
+       return 0;
+}
+
+/*
+ * Create a hardware video mode using the framebuffer values.  If a value needs
+ * to be clipped or constrained it's done here.  This routine needs a bit more
+ * work to make sure we're doing the right tests at the right time.
+ */
+static int pvr2_decode_var(struct fb_var_screeninfo *var,
+                             struct pvr2fb_par *par)
+{
+       u_long line_length;
+       u_short vtotal;
+
+       if (var->pixclock != TV_CLK && var->pixclock != VGA_CLK) {
+               DPRINTK("Invalid pixclock value %d\n", var->pixclock);
+               return -EINVAL;
+       }
+       par->pixclock = var->pixclock;
+       
+       if ((par->xres = var->xres) < 320)
+               par->xres = 320;
+       if ((par->yres = var->yres) < 240)
+               par->yres = 240;
+       if ((par->vxres = var->xres_virtual) < par->xres)
+               par->vxres = par->xres;
+       if ((par->vyres = var->yres_virtual) < par->yres)
+               par->vyres = par->yres;
+
+       if ((par->bpp = var->bits_per_pixel) <= 16)
+               par->bpp = 16;
+       else if ((par->bpp = var->bits_per_pixel) <= 24)
+               par->bpp = 24;
+       else if ((par->bpp = var->bits_per_pixel) <= 32)
+               par->bpp = 32;
+
+       currbpp = par->bpp;
+
+       /*
+        * XXX: It's possible that a user could use a VGA box, change the cable
+        * type in hardware (i.e. switch from VGA<->composite), then change modes
+        * (i.e. switching to another VT).  If that happens we should automagically
+        * change the output format to cope, but currently I don't have a VGA box
+        * to make sure this works properly.
+        */
+       cable_type = pvr2_init_cable();
+       if (cable_type == CT_VGA && video_output != VO_VGA)
+               video_output = VO_VGA;
+
+       par->vmode = var->vmode & FB_VMODE_MASK;
+       if (par->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
+               par->is_interlaced = 1;
+       /* 
+        * XXX: Need to be more creative with this (i.e. allow doublecan for
+        * PAL/NTSC output).
+        */
+       par->is_doublescan = (par->yres < 480 && video_output == VO_VGA);
+       
+       par->hsync_total = var->left_margin + var->xres + var->right_margin +
+                          var->hsync_len;
+       par->vsync_total = var->upper_margin + var->yres + var->lower_margin +
+                          var->vsync_len;
+
+       if (var->sync & FB_SYNC_BROADCAST) {
+               vtotal = par->vsync_total;
+               if (par->is_interlaced)
+                       vtotal /= 2;
+               if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) {
+                       /* PAL video output */
+                       /* XXX: Should be using a range here ... ? */
+                       if (par->hsync_total != PAL_HTOTAL) {
+                               DPRINTK("invalid hsync total for PAL\n");
+                               return -EINVAL;
+                       }
+                       /* XXX: Check for start values here... */
+                       /* XXX: Check hardware for PAL-compatibility */
+                       par->borderstart_h = 116;
+                       par->borderstart_v = 44;
+               } else {
+                       /* NTSC video output */
+                       if (par->hsync_total != NTSC_HTOTAL) {
+                               DPRINTK("invalid hsync total for NTSC\n");
+                               return -EINVAL;
+                       }
+                       par->borderstart_h = 126;
+                       par->borderstart_v = 18;
+               }
+       } else {
+               /* VGA mode */
+               /* XXX: What else needs to be checked? */
+               /* 
+                * XXX: We have a little freedom in VGA modes, what ranges should
+                * be here (i.e. hsync/vsync totals, etc.)?
+                */
+               par->borderstart_h = 126;
+               par->borderstart_v = 40;
+       }
+
+       /* Calculate the remainding offsets */
+       par->borderstop_h = par->borderstart_h + par->hsync_total -
+                           var->hsync_len;
+       par->borderstop_v = par->borderstart_v + par->vsync_total -
+                           var->vsync_len;
+       par->diwstart_h = par->borderstart_h + var->left_margin;
+       par->diwstart_v = par->borderstart_v + var->upper_margin;
+       if (!par->is_interlaced)
+               par->borderstop_v /= 2;
+
+       if (par->xres < 640)
+               par->is_lowres = 1;
+
+       /* XXX: Needs testing. */
+       if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
+               par->xoffset = var->xoffset;
+               par->yoffset = var->yoffset;
+               if (par->vmode & FB_VMODE_YWRAP) {
+                       if (par->xoffset || par->yoffset < 0 || par->yoffset >=
+                           par->vyres)
+                               par->xoffset = par->yoffset = 0;
+               } else {
+                       if (par->xoffset < 0 || par->xoffset > par->vxres-par->xres ||
+                           par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
+                               par->xoffset = par->yoffset = 0;
+               }
+       } else
+               par->xoffset = par->yoffset = 0;
+
+       /* Check memory sizes */
+       line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+       if (line_length * var->yres_virtual > videomemorysize)
+               return -ENOMEM;
+       par->disp_start = videomemory + (get_line_length(par->vxres, par->bpp) *
+                         par->yoffset) * get_line_length(par->xoffset, par->bpp);
+       par->next_line = line_length;
+       
+       return 0;
+}
+
+static int pvr2_encode_var(struct fb_var_screeninfo *var,
+                             struct pvr2fb_par *par)
+{
+       memset(var, 0, sizeof(struct fb_var_screeninfo));
+
+       var->xres = par->xres;
+       var->yres = par->yres;
+       var->xres_virtual = par->vxres;
+       var->yres_virtual = par->vyres;
+       var->xoffset = par->xoffset;
+       var->yoffset = par->yoffset;
+
+       var->bits_per_pixel = par->bpp;
+       set_color_bitfields(var);
+
+       var->activate = FB_ACTIVATE_NOW;
+       var->height = -1;
+       var->width = -1;
+
+       var->pixclock = par->pixclock;
+
+       if (par->is_doublescan)
+               var->vmode = FB_VMODE_DOUBLE;
+
+       if (par->is_interlaced)
+               var->vmode |= FB_VMODE_INTERLACED;
+       else
+               var->vmode |= FB_VMODE_NONINTERLACED;
+
+       var->right_margin = par->borderstop_h - (par->diwstart_h + par->xres);
+       var->left_margin = par->diwstart_h - par->borderstart_h;
+       var->hsync_len = par->borderstart_h + (par->hsync_total - par->borderstop_h);
+       var->upper_margin = par->diwstart_v - par->borderstart_v;
+       var->lower_margin = par->borderstop_v - (par->diwstart_v + par->yres);
+       var->vsync_len = par->borderstart_v + (par->vsync_total - par->borderstop_v);
+       if (video_output != VO_VGA)
+               var->sync = FB_SYNC_BROADCAST;
+
+       if (par->vmode & FB_VMODE_YWRAP)
+               var->vmode |= FB_VMODE_YWRAP;
+       
+       return 0;
+}
+
+static void pvr2_get_par(struct pvr2fb_par *par)
+{
+       *par = currentpar;
+}
+
+/* Setup the new videomode in hardware */
+
+static void pvr2_set_var(struct fb_var_screeninfo *var)
+{
+       do_vmode_pan = 0;
+       do_vmode_full = 0;
+       pvr2_decode_var(var, &currentpar);
+
+       do_vmode_full = 1;
+}
+
+/* 
+ * Pan or wrap the display
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag in `var'.
+ */
+static void pvr2_pan_var(struct fb_var_screeninfo *var)
+{
+       struct pvr2fb_par *par = &currentpar;
+
+       par->xoffset = var->xoffset;
+       par->yoffset = var->yoffset;
+       if (var->vmode & FB_VMODE_YWRAP)
+               par->vmode |= FB_VMODE_YWRAP;
+       else
+               par->vmode &= ~FB_VMODE_YWRAP;
+
+       do_vmode_pan = 0;
+       pvr2_update_par();
+       do_vmode_pan = 1;
+}
+
+static int pvr2_update_par(void)
+{
+       struct pvr2fb_par *par = &currentpar;
+       u_long move;
+
+       move = get_line_length(par->xoffset, par->bpp);
+       if (par->yoffset) {
+               par->disp_start += (par->next_line * par->yoffset) + move;
+       } else
+               par->disp_start += move;
+
+       return 0;
+}
+
+static void pvr2_update_display(void)
+{
+       struct pvr2fb_par *par = &currentpar;
+
+       /* Update the start address of the display image */
+       ctrl_outl(par->disp_start, DISP_DIWADDRL);
+       ctrl_outl(par->disp_start +
+                 get_line_length(par->xoffset + par->xres, par->bpp),
+                 DISP_DIWADDRS);
+}
+
+/* 
+ * Initialize the video mode.  Currently, the 16bpp and 24bpp modes aren't
+ * very stable.  It's probably due to the fact that a lot of the 2D video
+ * registers are still undocumented.
+ */
+
+static void pvr2_init_display(void)
+{
+       struct pvr2fb_par *par = &currentpar;
+       u_short diw_height, diw_width, diw_modulo = 1;
+       u_short bytesperpixel = par->bpp / 8;
+
+       /* hsync and vsync totals */
+       ctrl_outl((par->vsync_total << 16) | par->hsync_total, DISP_SYNCSIZE);
+
+       /* column height, modulo, row width */
+       /* since we're "panning" within vram, we need to offset things based
+        * on the offset from the virtual x start to our real gfx. */
+       if (video_output != VO_VGA && par->is_interlaced)
+               diw_modulo += par->next_line / 4;
+       diw_height = (par->is_interlaced ? par->yres / 2 : par->yres);
+       diw_width = get_line_length(par->xres, par->bpp) / 4;
+       ctrl_outl((diw_modulo << 20) | (--diw_height << 10) | --diw_width,
+                 DISP_DIWSIZE);
+
+       /* display address, long and short fields */
+       ctrl_outl(par->disp_start, DISP_DIWADDRL);
+       ctrl_outl(par->disp_start +
+                 get_line_length(par->xoffset + par->xres, par->bpp),
+                 DISP_DIWADDRS);
+
+       /* border horizontal, border vertical, border color */
+       ctrl_outl((par->borderstart_h << 16) | par->borderstop_h, DISP_BRDRHORZ);
+       ctrl_outl((par->borderstart_v << 16) | par->borderstop_v, DISP_BRDRVERT);
+       ctrl_outl(0, DISP_BRDRCOLR);
+
+       /* display window start position */
+       ctrl_outl(par->diwstart_h, DISP_DIWHSTRT);
+       ctrl_outl((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT);
+       
+       /* misc. settings */
+       ctrl_outl((0x16 << 16) | par->is_lowres, DISP_DIWCONF);
+
+       /* clock doubler (for VGA), scan doubler, display enable */
+       ctrl_outl(((video_output == VO_VGA) << 23) | 
+                 (par->is_doublescan << 1) | 1, DISP_DIWMODE);
+
+       /* bits per pixel */
+       ctrl_outl(ctrl_inl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
+
+       /* video enable, color sync, interlace, 
+        * hsync and vsync polarity (currently unused) */
+       ctrl_outl(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
+
+}
+
+/* Simulate blanking by making the border cover the entire screen */
+
+#define BLANK_BIT (1<<3)
+
+static void pvr2_do_blank(void)
+{
+       u_long diwconf;
+
+       diwconf = ctrl_inl(DISP_DIWCONF);
+       if (do_blank > 0)
+               ctrl_outl(diwconf | BLANK_BIT, DISP_DIWCONF);
+       else
+               ctrl_outl(diwconf & ~BLANK_BIT, DISP_DIWCONF);
+
+       is_blanked = do_blank > 0 ? do_blank : 0;
+}
+
+static void pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+{
+       if (do_vmode_pan || do_vmode_full)
+               pvr2_update_display();
+
+       if (do_vmode_full)
+               pvr2_init_display();
+
+       if (do_vmode_pan)
+               do_vmode_pan = 0;
+
+       if (do_blank) {
+               pvr2_do_blank();
+               do_blank = 0;
+       }
+
+       if (do_vmode_full) {
+               do_vmode_full = 0;
+       }
+}
+
+/*
+ * Determine the cable type and initialize the cable output format.  Don't do
+ * anything if the cable type has been overidden (via "cable:XX").
+ */
+
+#define PCTRA 0xff80002c
+#define PDTRA 0xff800030
+#define VOUTC 0xa0702c00
+
+static int pvr2_init_cable(void)
+{
+       if (cable_type < 0) {
+               ctrl_outl((ctrl_inl(PCTRA) & 0xfff0ffff) | 0x000a0000, 
+                         PCTRA);
+               cable_type = (ctrl_inw(PDTRA) >> 8) & 3;
+       }
+
+       /* Now select the output format (either composite or other) */
+       /* XXX: Save the previous val first, as this reg is also AICA
+         related */
+       if (cable_type == CT_COMPOSITE)
+               ctrl_outl(3 << 8, VOUTC);
+       else
+               ctrl_outl(0, VOUTC);
+
+       return cable_type;
+}
+
+int __init pvr2fb_init(void)
+{
+       struct fb_var_screeninfo var;
+       u_long modememused;
+
+       if (!MACH_DREAMCAST)
+               return -ENXIO;
+
+       /* Make a guess at the monitor based on the attached cable */
+       if (pvr2_init_cable() == CT_VGA) {
+               fb_info.monspecs.hfmin = 30000;
+               fb_info.monspecs.hfmax = 70000;
+               fb_info.monspecs.vfmin = 60;
+               fb_info.monspecs.vfmax = 60;
+       }
+       else { /* Not VGA, using a TV (taken from acornfb) */
+               fb_info.monspecs.hfmin = 15469;
+               fb_info.monspecs.hfmax = 15781;
+               fb_info.monspecs.vfmin = 49;
+               fb_info.monspecs.vfmax = 51;
+       }
+
+       /* XXX: This needs to pull default video output via BIOS or other means */
+       if (video_output < 0) {
+               if (cable_type == CT_VGA)
+                       video_output = VO_VGA;
+               else
+                       video_output = VO_NTSC;
+       }
+       
+       strcpy(fb_info.modename, pvr2fb_name);
+       fb_info.changevar = NULL;
+       fb_info.node = -1;
+       fb_info.fbops = &pvr2fb_ops;
+       fb_info.disp = &disp;
+       fb_info.switch_con = &pvr2fbcon_switch;
+       fb_info.updatevar = &pvr2fbcon_updatevar;
+       fb_info.blank = &pvr2fbcon_blank;
+       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       memset(&var, 0, sizeof(var));
+
+       if (video_output == VO_VGA)
+               defmode = DEFMODE_VGA;
+
+       if (!fb_find_mode(&var, &fb_info, mode_option, pvr2_modedb,
+                         NUM_TOTAL_MODES, &pvr2_modedb[defmode], 16)) {
+               return -EINVAL;
+       }
+
+       if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, 0,
+                       "pvr2 VBL handler", &currentpar)) {
+               DPRINTK("couldn't register VBL int\n");
+               return -EBUSY;
+       }
+
+#ifdef CONFIG_MTRR
+       if (enable_mtrr) {
+               mtrr_handle = mtrr_add(videomemory, videomemorysize, MTRR_TYPE_WRCOMB, 1);
+               printk("pvr2fb: MTRR turned on\n");
+       }
+#endif
+
+       pvr2fb_set_var(&var, -1, &fb_info);
+
+       if (register_framebuffer(&fb_info) < 0)
+               return -EINVAL;
+
+       modememused = get_line_length(var.xres_virtual, var.bits_per_pixel);
+       modememused *= var.yres_virtual;
+       printk("fb%d: %s frame buffer device, using %ldk/%ldk of video memory\n",
+              GET_FB_IDX(fb_info.node), fb_info.modename, modememused>>10,
+              videomemorysize>>10);
+       printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", 
+              GET_FB_IDX(fb_info.node), var.xres, var.yres, var.bits_per_pixel, 
+              get_line_length(var.xres, var.bits_per_pixel),
+              (char *)pvr2_get_param(cables, NULL, cable_type, 6),
+              (char *)pvr2_get_param(outputs, NULL, video_output, 6));
+
+       return 0;
+}
+
+static void __exit pvr2fb_exit(void)
+{
+#ifdef CONFIG_MTRR
+       if (enable_mtrr) {
+               mtrr_del(mtrr_handle, videomemory, videomemorysize);
+               printk("pvr2fb: MTRR turned off\n");
+       }
+#endif
+       unregister_framebuffer(&fb_info);
+}
+
+static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
+                                   int val, int size)
+{
+       int i;
+
+       for (i = 0 ; i < size ; i++ ) {
+               if (s != NULL) {
+                       if (!strnicmp(p[i].name, s, strlen(s)))
+                               return p[i].val;
+               } else {
+                       if (p[i].val == val)
+                               return (int)p[i].name;
+               }
+       }
+       return -1;
+}
+
+/*
+ * Parse command arguments.  Supported arguments are:
+ *    inverse                             Use inverse color maps
+ *    nomtrr                              Disable MTRR usage
+ *    font:<fontname>                     Specify console font
+ *    cable:composite|rgb|vga             Override the video cable type
+ *    output:NTSC|PAL|VGA                 Override the video output format
+ *
+ *    <xres>x<yres>[-<bpp>][@<refresh>]   or,
+ *    <name>[-<bpp>][@<refresh>]          Startup using this video mode
+ */
+
+#ifndef MODULE
+int __init pvr2fb_setup(char *options)
+{
+       char *this_opt;
+       char cable_arg[80];
+       char output_arg[80];
+
+       fb_info.fontname[0] = '\0';
+
+       if (!options || !*options)
+               return 0;
+
+       while ((this_opt = strsep(&options, ","))) {
+               if (!*this_opt)
+                       continue;
+               if (!strcmp(this_opt, "inverse")) {
+                       pvr2fb_inverse = 1;
+                       fb_invert_cmaps();
+               } else if (!strncmp(this_opt, "font:", 5))
+                       strcpy(fb_info.fontname, this_opt + 5);
+               else if (!strncmp(this_opt, "cable:", 6))
+                       strcpy(cable_arg, this_opt + 6);
+               else if (!strncmp(this_opt, "output:", 7))
+                       strcpy(output_arg, this_opt + 7);
+#ifdef CONFIG_MTRR
+               else if (!strncmp(this_opt, "nomtrr", 6))
+                       enable_mtrr = 0;
+#endif
+               else
+                       mode_option = this_opt;
+       }
+
+       if (*cable_arg)
+               cable_type = pvr2_get_param(cables, cable_arg, 0, 6);
+
+       if (*output_arg)
+               video_output = pvr2_get_param(outputs, output_arg, 0, 6);
+
+       return 0;
+}
+#endif
+
+#ifdef MODULE
+module_init(pvr2fb_init);
+#endif
+module_exit(pvr2fb_exit);
+
index 264babd758e089507ed7be947548b7af69882ba3..345ee6e923ee187dcf264085bbe4647377c5a62a 100644 (file)
@@ -71,8 +71,16 @@ static char buffersize_index[65] =
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_inode_buffers)
 
-#define get_bh(bh)     atomic_inc(&(bh)->b_count)
-#define put_bh(bh)     atomic_dec(&(bh)->b_count)
+static inline void get_bh(struct buffer_head * bh)
+{
+       atomic_inc(&(bh)->b_count);
+}
+
+static inline void put_bh(struct buffer_head *bh)
+{
+       smp_mb__before_atomic_dec();
+       atomic_dec(&bh->b_count);
+}
 
 /*
  * Hash table gook..
@@ -136,7 +144,7 @@ union bdflush_param {
 int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   1*HZ,   0, 0, 0};
 int bdflush_max[N_PARAM] = {100,50000, 20000, 20000,600*HZ, 6000*HZ, 100, 0, 0};
 
-static inline void __unlock_buffer(struct buffer_head *bh)
+inline void unlock_buffer(struct buffer_head *bh)
 {
        clear_bit(BH_Lock, &bh->b_state);
        smp_mb__after_clear_bit();
@@ -144,13 +152,6 @@ static inline void __unlock_buffer(struct buffer_head *bh)
                wake_up(&bh->b_wait);
 }
 
-void unlock_buffer(struct buffer_head *bh)
-{
-       get_bh(bh);
-       __unlock_buffer(bh);
-       put_bh(bh);
-}
-
 /*
  * Rewrote the wait-routines to use the "new" wait-queue functionality,
  * and getting rid of the cli-sti pairs. The wait-queue routines still
@@ -179,11 +180,14 @@ void __wait_on_buffer(struct buffer_head * bh)
        put_bh(bh);
 }
 
-/* End-of-write handler.. Just mark it up-to-date and unlock the buffer. */
-static void end_buffer_write(struct buffer_head *bh, int uptodate)
+/*
+ * Default synchronous end-of-IO handler..  Just mark it up-to-date and
+ * unlock the buffer. This is what ll_rw_block uses too.
+ */
+void end_buffer_io_sync(struct buffer_head *bh, int uptodate)
 {
        mark_buffer_uptodate(bh, uptodate);
-       __unlock_buffer(bh);
+       unlock_buffer(bh);
        put_bh(bh);
 }
 
@@ -201,7 +205,7 @@ static void write_locked_buffers(struct buffer_head **array, unsigned int count)
        get_bh(wait);
        do {
                struct buffer_head * bh = *array++;
-               bh->b_end_io = end_buffer_write;
+               bh->b_end_io = end_buffer_io_sync;
                submit_bh(WRITE, bh);
        } while (--count);
        wait_on_buffer(wait);
@@ -240,7 +244,7 @@ repeat:
                        write_locked_buffers(array, count);
                        goto repeat;
                }
-               __unlock_buffer(bh);
+               unlock_buffer(bh);
                put_bh(bh);
        }
        spin_unlock(&lru_list_lock);
@@ -823,7 +827,7 @@ static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
         * that unlock the page..
         */
        spin_lock_irqsave(&page_uptodate_lock, flags);
-       __unlock_buffer(bh);
+       unlock_buffer(bh);
        tmp = bh->b_this_page;
        while (tmp != bh) {
                if (tmp->b_end_io == end_buffer_io_async && buffer_locked(tmp))
@@ -2005,8 +2009,7 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate)
        mark_buffer_uptodate(bh, uptodate);
 
        kiobuf = bh->b_private;
-       __unlock_buffer(bh);
-       put_bh(bh);
+       unlock_buffer(bh);
        end_kio_request(kiobuf, uptodate);
 }
 
@@ -2131,7 +2134,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
                                offset += size;
 
                                atomic_inc(&iobuf->io_count);
-                               get_bh(tmp);
                                submit_bh(rw, tmp);
                                /* 
                                 * Wait for IO if we have got too much 
index a509f6c74bd93421c5453033181b2fec9e7ba0ca..349cd5613f5660378cb8f32cfdfe79a9a4d03ecd 100644 (file)
@@ -106,4 +106,9 @@ static __inline__ long atomic_sub_return(int i, atomic_t * v)
 #define atomic_inc(v) atomic_add(1,(v))
 #define atomic_dec(v) atomic_sub(1,(v))
 
+#define smp_mb__before_atomic_dec()    smp_mb()
+#define smp_mb__after_atomic_dec()     smp_mb()
+#define smp_mb__before_atomic_inc()    smp_mb()
+#define smp_mb__after_atomic_inc()     smp_mb()
+
 #endif /* _ALPHA_ATOMIC_H */
diff --git a/include/asm-alpha/rwsem.h b/include/asm-alpha/rwsem.h
new file mode 100644 (file)
index 0000000..6812299
--- /dev/null
@@ -0,0 +1,208 @@
+#ifndef _ALPHA_RWSEM_H
+#define _ALPHA_RWSEM_H
+
+/*
+ * Written by Ivan Kokshaysky <ink@jurassic.park.msu.ru>, 2001.
+ * Based on asm-alpha/semaphore.h and asm-i386/rwsem.h
+ */
+
+#ifndef _LINUX_RWSEM_H
+#error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
+#endif
+
+#ifdef __KERNEL__
+
+#include <asm/compiler.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+struct rwsem_waiter;
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+       long                    count;
+#define RWSEM_UNLOCKED_VALUE           0x0000000000000000L
+#define RWSEM_ACTIVE_BIAS              0x0000000000000001L
+#define RWSEM_ACTIVE_MASK              0x00000000ffffffffL
+#define RWSEM_WAITING_BIAS             (-0x0000000100000000L)
+#define RWSEM_ACTIVE_READ_BIAS         RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS                (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+       spinlock_t              wait_lock;
+       struct list_head        wait_list;
+#if RWSEM_DEBUG
+       int                     debug;
+#endif
+};
+
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT      , 0
+#else
+#define __RWSEM_DEBUG_INIT     /* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+       { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+       LIST_HEAD_INIT((name).wait_list) __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name) \
+       struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+       sem->count = RWSEM_UNLOCKED_VALUE;
+       spin_lock_init(&sem->wait_lock);
+       INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+       sem->debug = 0;
+#endif
+}
+
+static inline void __down_read(struct rw_semaphore *sem)
+{
+       long oldcount;
+#ifndef        CONFIG_SMP
+       oldcount = sem->count;
+       sem->count += RWSEM_ACTIVE_READ_BIAS;
+#else
+       long temp;
+       __asm__ __volatile__(
+       "1:     ldq_l   %0,%1\n"
+       "       addq    %0,%3,%2\n"
+       "       stq_c   %2,%1\n"
+       "       beq     %2,2f\n"
+       "       mb\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
+       :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
+#endif
+       if (__builtin_expect(oldcount < 0, 0))
+               rwsem_down_read_failed(sem);
+}
+
+static inline void __down_write(struct rw_semaphore *sem)
+{
+       long oldcount;
+#ifndef        CONFIG_SMP
+       oldcount = sem->count;
+       sem->count += RWSEM_ACTIVE_WRITE_BIAS;
+#else
+       long temp;
+       __asm__ __volatile__(
+       "1:     ldq_l   %0,%1\n"
+       "       addq    %0,%3,%2\n"
+       "       stq_c   %2,%1\n"
+       "       beq     %2,2f\n"
+       "       mb\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
+       :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
+#endif
+       if (__builtin_expect(oldcount, 0))
+               rwsem_down_write_failed(sem);
+}
+
+static inline void __up_read(struct rw_semaphore *sem)
+{
+       long oldcount;
+#ifndef        CONFIG_SMP
+       oldcount = sem->count;
+       sem->count -= RWSEM_ACTIVE_READ_BIAS;
+#else
+       long temp;
+       __asm__ __volatile__(
+       "       mb\n"
+       "1:     ldq_l   %0,%1\n"
+       "       subq    %0,%3,%2\n"
+       "       stq_c   %2,%1\n"
+       "       beq     %2,2f\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
+       :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
+#endif
+       if (__builtin_expect(oldcount < 0, 0)) 
+               if ((int)oldcount - RWSEM_ACTIVE_READ_BIAS == 0)
+                       rwsem_wake(sem);
+}
+
+static inline void __up_write(struct rw_semaphore *sem)
+{
+       long count;
+#ifndef        CONFIG_SMP
+       sem->count -= RWSEM_ACTIVE_WRITE_BIAS;
+       count = sem->count;
+#else
+       long temp;
+       __asm__ __volatile__(
+       "       mb\n"
+       "1:     ldq_l   %0,%1\n"
+       "       subq    %0,%3,%2\n"
+       "       stq_c   %2,%1\n"
+       "       beq     %2,2f\n"
+       "       subq    %0,%3,%0\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       :"=&r" (count), "=m" (sem->count), "=&r" (temp)
+       :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
+#endif
+       if (__builtin_expect(count, 0))
+               if ((int)count == 0)
+                       rwsem_wake(sem);
+}
+
+static inline void rwsem_atomic_add(long val, struct rw_semaphore *sem)
+{
+#ifndef        CONFIG_SMP
+       sem->count += val;
+#else
+       long temp;
+       __asm__ __volatile__(
+       "1:     ldq_l   %0,%1\n"
+       "       addq    %0,%2,%0\n"
+       "       stq_c   %0,%1\n"
+       "       beq     %0,2f\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       :"=&r" (temp), "=m" (sem->count)
+       :"Ir" (val), "m" (sem->count));
+#endif
+}
+
+static inline long rwsem_atomic_update(long val, struct rw_semaphore *sem)
+{
+#ifndef        CONFIG_SMP
+       sem->count += val;
+       return sem->count;
+#else
+       long ret, temp;
+       __asm__ __volatile__(
+       "1:     ldq_l   %0,%1\n"
+       "       addq    %0,%3,%2\n"
+       "       addq    %0,%3,%0\n"
+       "       stq_c   %2,%1\n"
+       "       beq     %2,2f\n"
+       ".subsection 2\n"
+       "2:     br      1b\n"
+       ".previous"
+       :"=&r" (ret), "=m" (sem->count), "=&r" (temp)
+       :"Ir" (val), "m" (sem->count));
+
+       return ret;
+#endif
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ALPHA_RWSEM_H */
index 34ccfe914c36cb17b36e81953f356e0f5b0e939f..b356b373944e6a81579f71c51cb29b53fb4510c2 100644 (file)
@@ -195,4 +195,10 @@ __asm__ __volatile__(LOCK "andl %0,%1" \
 __asm__ __volatile__(LOCK "orl %0,%1" \
 : : "r" (mask),"m" (*addr) : "memory")
 
+/* Atomic operations are already serializing on x86 */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif
index 08fc25c5715f4fabfcd38c2b0666e1bca7522a74..d10f1f424b45939f5c76f7622962407d05b7e19b 100644 (file)
@@ -91,4 +91,10 @@ atomic_add_negative (int i, atomic_t *v)
 #define atomic_inc(v)                  atomic_add(1, (v))
 #define atomic_dec(v)                  atomic_sub(1, (v))
 
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif /* _ASM_IA64_ATOMIC_H */
index 4f92a2f5731aafff80b9cd9c3aa190e86be6391d..d7ef37661179e0d682124410da3e82690f4e5de9 100644 (file)
@@ -49,4 +49,10 @@ static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
 #define atomic_set_mask(mask, v) \
        __asm__ __volatile__("orl %1,%0" : "=m" (*v) : "id" (mask),"0"(*v))
 
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif /* __ARCH_M68K_ATOMIC __ */
index 63667f0c81f17f0aeec10d8fdaa92d98d22d4f05..b15c8b2eb297de135298c8413081e341fc896884 100644 (file)
@@ -272,6 +272,12 @@ extern __inline__ int atomic_sub_return(int i, atomic_t * v)
  * Currently not implemented for MIPS.
  */
 
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif /* defined(__KERNEL__) */
 
 #endif /* __ASM_ATOMIC_H */
index a2804018d4af1f3b3447ae13ebd6e0aaac61f915..9ed4c541926d9bf2d4e5203b1416750ba30127da 100644 (file)
@@ -183,6 +183,12 @@ extern __inline__ int atomic_sub_return(int i, atomic_t * v)
  * atomic_add_negative is currently not implemented for mips64.
  */
 
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif /* defined(__KERNEL__) */
 
 #endif /* _ASM_ATOMIC_H */
index 1cefd84efe41ea8d0e852f597562d1fb4ba27853..a0fa988a50290d4291e18b41fe51399e7a0c3be3 100644 (file)
@@ -111,4 +111,9 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
        return t;
 }
 
+#define smp_mb__before_atomic_dec()    smp_mb()
+#define smp_mb__after_atomic_dec()     smp_mb()
+#define smp_mb__before_atomic_inc()    smp_mb()
+#define smp_mb__after_atomic_inc()     smp_mb()
+
 #endif /* _ASM_PPC_ATOMIC_H_ */
index d2bf9f58c8b6a199db3e8fa974e9edfbaec6199d..d99d1aef9d71666d07cb09c129faa5ff116b5a2a 100644 (file)
@@ -170,5 +170,10 @@ if (atomic_compare_and_swap ((from), (to), (where))) {\
         atomic_set(where,(to));\
 }
 
+#define smp_mb__before_atomic_dec()    smp_mb()
+#define smp_mb__after_atomic_dec()     smp_mb()
+#define smp_mb__before_atomic_inc()    smp_mb()
+#define smp_mb__after_atomic_inc()     smp_mb()
+
 #endif                                 /* __ARCH_S390_ATOMIC __            */
 
index 0d2a9348b1fd0e7024b149241df28962776adf9f..e97e7bbe3c0b1a8218b8f1da55df59dfda1a2ec6 100644 (file)
@@ -170,5 +170,9 @@ if (atomic_compare_and_swap ((from), (to), (where))) {\
         atomic_set(where,(to));\
 }
 
-#endif                                 /* __ARCH_S390_ATOMIC __            */
+#define smp_mb__before_atomic_dec()    smp_mb()
+#define smp_mb__after_atomic_dec()     smp_mb()
+#define smp_mb__before_atomic_inc()    smp_mb()
+#define smp_mb__after_atomic_inc()     smp_mb()
 
+#endif                                 /* __ARCH_S390_ATOMIC __            */
index 6c8c16bf44bbc7b0679cc467828a431fea1c924b..e28e478a020bb02d8706c778f0dc8674f972e408 100644 (file)
@@ -100,6 +100,12 @@ static __inline__ int __atomic_sub(int i, atomic_t *v)
 
 #define atomic_add_negative(i, v) (__atomic_add((i), (v)) < 0)
 
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif /* !(__KERNEL__) */
 
 #endif /* !(__ARCH_SPARC_ATOMIC__) */
index b1085349015af775f4f366303bf466316090559d..b3e159e77d8e3ba9e55421a1c3f6ee08068adc02 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.61 2000/09/23 02:11:22 davem Exp $
+/* $Id: bitops.h,v 1.62 2001/07/07 10:58:22 davem Exp $
  * bitops.h: Bit string operations on the Sparc.
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -131,7 +131,9 @@ extern __inline__ void clear_bit(unsigned long nr, volatile void *addr)
        (void) test_and_clear_bit(nr, addr);
 }
 
-extern __inline__ int test_and_change_bit(unsigned long nr, volatile void *addr)
+#define test_and_change_bit(n, a) __test_and_change_bit(n, a)
+
+extern __inline__ int __test_and_change_bit(unsigned long nr, volatile void *addr)
 {
        register unsigned long mask asm("g2");
        register unsigned long *ADDR asm("g1");
@@ -149,7 +151,9 @@ extern __inline__ int test_and_change_bit(unsigned long nr, volatile void *addr)
        return mask != 0;
 }
 
-extern __inline__ void change_bit(unsigned long nr, volatile void *addr)
+#define change_bit(n, a) __change_bit(n, a)
+
+extern __inline__ void __change_bit(unsigned long nr, volatile void *addr)
 {
        (void) test_and_change_bit(nr, addr);
 }
index 1a6cc2bfc1436c5b6c47a7c0922403cbc09c4492..76cdae6115448347607357e3c423acc1847de167 100644 (file)
@@ -29,4 +29,10 @@ extern int __atomic_sub(int, atomic_t *);
 #define atomic_inc(v) ((void)__atomic_add(1, v))
 #define atomic_dec(v) ((void)__atomic_sub(1, v))
 
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif /* !(__ARCH_SPARC64_ATOMIC__) */
index f6866ccf6abb499b0c212fcdd02f6a8d9febe7e2..6f6ef817b059e96ff80ace10c5c7b78e8a048e14 100644 (file)
@@ -1058,6 +1058,7 @@ extern int fs_may_remount_ro(struct super_block *);
 
 extern int try_to_free_buffers(struct page *, unsigned int);
 extern void refile_buffer(struct buffer_head * buf);
+extern void end_buffer_io_sync(struct buffer_head *bh, int uptodate);
 
 /* reiserfs_writepage needs this */
 extern void set_buffer_async_io(struct buffer_head *bh) ;
index 9843b91077d201c3dc18f9107435efaffb365f83..e8dc980b0ea06bd94d78952e3fc90eb48d1b2eea 100644 (file)
 #define        ARPHRD_IEEE802  6               /* IEEE 802.2 Ethernet/TR/TB    */
 #define        ARPHRD_ARCNET   7               /* ARCnet                       */
 #define        ARPHRD_APPLETLK 8               /* APPLEtalk                    */
-#define        ARPHRD_IEEE1394 9               /* IEEE 1394 IPv4 - RFC 2734    */
 #define ARPHRD_DLCI    15              /* Frame Relay DLCI             */
 #define ARPHRD_ATM     19              /* ATM                          */
 #define ARPHRD_METRICOM        23              /* Metricom STRIP (new IANA id) */
+#define        ARPHRD_IEEE1394 24              /* IEEE 1394 IPv4 - RFC 2734    */
 
 /* Dummy types for non ARP hardware */
 #define ARPHRD_SLIP    256
index 2afb52e98531b9ea42f72175069e8d4b7d4d7e83..ce7f93b9e9d043888765af15f6254c9f5d80b029 100644 (file)
@@ -34,7 +34,7 @@ struct nlmsghdr
 
 #define NLM_F_REQUEST          1       /* It is request message.       */
 #define NLM_F_MULTI            2       /* Multipart message, terminated by NLMSG_DONE */
-#define NLM_F_ACK              4       /* If succeed, reply with ack   */
+#define NLM_F_ACK              4       /* Reply with ack, with zero or error code */
 #define NLM_F_ECHO             8       /* Echo this request            */
 
 /* Modifiers to GET request */
index 40732e005e85ab66668df761c3e73aa7210f51f1..8d148b6db6e9e6866d56d1ae7f47788ad900c189 100644 (file)
@@ -22,6 +22,7 @@
 #define PARPORT_DMA_NOFIFO -3
 #define PARPORT_DISABLE   -2
 #define PARPORT_IRQ_PROBEONLY -3
+#define PARPORT_IOHI_AUTO -1
 
 #define PARPORT_CONTROL_STROBE    0x1
 #define PARPORT_CONTROL_AUTOFD    0x2
index 44fc5e05e2678c7f44d0c4da6318286a941721f7..09eee390b5bc33a3fead5e1830ebf95722f91ac1 100644 (file)
@@ -1124,6 +1124,7 @@ extern void                       skb_free_datagram(struct sock * sk, struct sk_buff *skb);
 extern unsigned int            skb_checksum(const struct sk_buff *skb, int offset, int len, unsigned int csum);
 extern int                     skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
 extern unsigned int            skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, int len, unsigned int csum);
+extern void                    skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
 
 extern void skb_init(void);
 extern void skb_add_mtu(int mtu);
index 8d480e7e7f110b94ce92d24f1c3112d12e28d1b8..1acf30ae566bd681dd32ad15cb2dffe7a7de2804 100644 (file)
@@ -112,7 +112,7 @@ static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem)
  */
 static inline struct rw_semaphore *rwsem_down_failed_common(struct rw_semaphore *sem,
                                                                 struct rwsem_waiter *waiter,
-                                                                __s32 adjustment)
+                                                                signed long adjustment)
 {
        struct task_struct *tsk = current;
        signed long count;
index 1a31310ca730efc10ed8317e225ea9a83735edb2..0178979d2e0dd4704ce399a7d48570ab7f74a634 100644 (file)
@@ -66,6 +66,7 @@ int alloc_divert_blk(struct net_device *dev)
                } else {
                        memset(dev->divert, 0, sizeof(struct divert_blk));
                }
+               dev_hold(dev);
        } else {
                printk(KERN_DEBUG "divert: not allocating divert_blk for non-ethernet device %s\n",
                       dev->name);
@@ -84,6 +85,7 @@ void free_divert_blk(struct net_device *dev)
        if (dev->divert) {
                kfree(dev->divert);
                dev->divert=NULL;
+               dev_put(dev);
                printk(KERN_DEBUG "divert: freeing divert_blk for %s\n",
                       dev->name);
        } else {
@@ -151,7 +153,8 @@ int remove_port(u16 ports[], u16 port)
 int check_args(struct divert_cf *div_cf, struct net_device **dev)
 {
        char devname[32];
-               
+       int ret;
+
        if (dev == NULL)
                return -EFAULT;
        
@@ -170,16 +173,21 @@ int check_args(struct divert_cf *div_cf, struct net_device **dev)
        /* dev should NOT be null */
        if (*dev == NULL)
                return -EINVAL;
-       
+
+       ret = 0;
+
        /* user issuing the ioctl must be a super one :) */
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
+       if (!capable(CAP_SYS_ADMIN)) {
+               ret = -EPERM;
+               goto out;
+       }
 
        /* Device must have a divert_blk member NOT null */
        if ((*dev)->divert == NULL)
-               return -EFAULT;
-
-       return 0;
+               ret = -EINVAL;
+out:
+       dev_put(*dev);
+       return ret;
 }
 
 /*
index e776e520b6b94ef20a454056cb3a1fa48c65fe7a..1385479d5099dc86e491158d75058f359e27818f 100644 (file)
@@ -4,7 +4,7 @@
  *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
  *                     Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *     Version:        $Id: skbuff.c,v 1.87 2001/03/06 22:09:50 davem Exp $
+ *     Version:        $Id: skbuff.c,v 1.88 2001/07/09 23:19:14 davem Exp $
  *
  *     Fixes:  
  *             Alan Cox        :       Fixed the worst of the load balancer bugs.
@@ -1149,6 +1149,32 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *t
        return csum;
 }
 
+void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
+{
+       unsigned int csum;
+       long csstart;
+
+       if (skb->ip_summed == CHECKSUM_HW)
+               csstart = skb->h.raw - skb->data;
+       else
+               csstart = skb->len - skb->data_len;
+
+       if (csstart > skb->len - skb->data_len)
+               BUG();
+
+       memcpy(to, skb->data, csstart);
+
+       csum = 0;
+       if (csstart != skb->len)
+               csum = skb_copy_and_csum_bits(skb, csstart, to+csstart,
+                               skb->len-csstart, 0);
+
+       if (skb->ip_summed == CHECKSUM_HW) {
+               long csstuff = csstart + skb->csum;
+
+               *((unsigned short *)(to + csstuff)) = csum_fold(csum);
+       }
+}
 
 #if 0
 /* 
index 9d4873b7d379e587bb79ef0c72ababdb81e316a4..e3b9e1fd91e08231f65bdc29a5efa9105e4812cb 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) output module.
  *
- * Version:    $Id: ip_output.c,v 1.93 2001/06/01 14:59:31 davem Exp $
+ * Version:    $Id: ip_output.c,v 1.94 2001/07/10 00:40:13 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -847,6 +847,9 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
                ptr += len;
                offset += len;
 
+#ifdef CONFIG_NET_SCHED
+               skb2->tc_index = skb->tc_index;
+#endif
 #ifdef CONFIG_NETFILTER
                skb2->nfmark = skb->nfmark;
                /* Connection association is same as pre-frag packet */
index 646f6a63dda7d7255824185f3bde6a1ed844605c..f4b08be85e4320fa32c7aa27dd58ee4072599558 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             RAW - implementation of IP "raw" sockets.
  *
- * Version:    $Id: raw.c,v 1.62 2001/06/05 10:52:15 davem Exp $
+ * Version:    $Id: raw.c,v 1.63 2001/07/10 04:29:01 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -520,6 +520,7 @@ int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        if (sin) {
                sin->sin_family = AF_INET;
                sin->sin_addr.s_addr = skb->nh.iph->saddr;
+               memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
        }
        if (sk->protinfo.af_inet.cmsg_flags)
                ip_cmsg_recv(msg, skb);
index 2f4929242533afa04f56eefdf12b74a3067d7122..91e4a7b848b2718ac17f2823471ae4218c0125e9 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_output.c,v 1.136 2001/03/06 22:42:56 davem Exp $
+ * Version:    $Id: tcp_output.c,v 1.137 2001/06/29 21:11:28 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
index 7f9acd0b6e16c47f17aea6520ddb97f12970f953..fffeac0931bf158b937b740e9fb62bc8c53763c5 100644 (file)
@@ -145,6 +145,7 @@ EXPORT_SYMBOL(skb_copy_datagram_iovec);
 EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
 EXPORT_SYMBOL(skb_copy_bits);
 EXPORT_SYMBOL(skb_copy_and_csum_bits);
+EXPORT_SYMBOL(skb_copy_and_csum_dev);
 EXPORT_SYMBOL(skb_copy_expand);
 EXPORT_SYMBOL(___pskb_trim);
 EXPORT_SYMBOL(__pskb_pull_tail);
index f224e03b1388aeabf1610230c621b04b9e3eb7da..d6a001c5b0034a02a559bdd4562f794ab125aa82 100644 (file)
@@ -8,7 +8,7 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  *
- * Version:    $Id: af_unix.c,v 1.116 2001/03/03 01:20:11 davem Exp $
+ * Version:    $Id: af_unix.c,v 1.117 2001/07/01 06:59:10 davem Exp $
  *
  * Fixes:
  *             Linus Torvalds  :       Assorted bug cures.