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,
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
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
- 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
--- /dev/null
+$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>
+
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 7
-EXTRAVERSION =-pre5
+EXTRAVERSION =-pre6
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
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"
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.
}
}
-/*
- * 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)
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");
/* --- 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;
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);
} else if (!strcmp(str, "reset")) {
reset = 1;
}
+ return 1;
}
-#endif
-
static int lp_register(int nr, struct parport *port)
{
char name[8];
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. */
return lp_init();
}
-void cleanup_module(void)
+static void lp_cleanup_module (void)
{
unsigned int offset;
parport_unregister_device(lp_table[offset].dev);
}
}
-#endif
+
+__setup("lp=", lp_setup);
+module_init(lp_init_module);
+module_exit(lp_cleanup_module);
mda_console_init();
#endif
tty_init();
-#ifdef CONFIG_PRINTER
- lp_init();
-#endif
#ifdef CONFIG_M68K_PRINTER
lp_m68k_init();
#endif
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);
po->chan.ops = &pppoe_chan_ops;
error = ppp_register_channel(&po->chan);
+ if (error)
+ goto err_put;
sk->state = PPPOX_CONNECTED;
}
end:
release_sock(sk);
return error;
+err_put:
+ dev_put(po->pppoe_dev);
+ po->pppoe_dev = NULL;
+ goto end;
}
- 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
#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>
#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"
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. */
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);
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)
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;
}
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);
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);
return;
}
-\f
+
static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = dev->priv;
/* 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);
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;
return;
}
+
static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct netdev_private *np = dev->priv;
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)
#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)
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;
}
np->stats.tx_fifo_errors++;
}
+
static struct net_device_stats *get_stats(struct net_device *dev)
{
long ioaddr = dev->base_addr;
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,
return crc;
}
+
static void set_rx_mode(struct net_device *dev)
{
long ioaddr = dev->base_addr;
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];
}
-
static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
{
struct ethtool_cmd ecmd;
}
-
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct netdev_private *np = dev->priv;
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;
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);
}
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;
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");
+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.
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
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
#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 };
/* 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++;
#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, };
--- /dev/null
+/*
+ * 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);
hd64465_port_map(
io->start,
io->stop - io->start + 1,
- vaddrbase + io->start);
+ vaddrbase + io->start,0);
} else {
hd64465_port_unmap(
sio->start,
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),
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
"$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 \
"$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
"$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
"$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 \
"$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
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
+++ /dev/null
-/*
- * $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
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);
#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
/*
--- /dev/null
+/* 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, ¤tpar);
+
+ 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 = ¤tpar;
+
+ 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 = ¤tpar;
+ 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 = ¤tpar;
+
+ /* 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 = ¤tpar;
+ 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", ¤tpar)) {
+ 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);
+
#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..
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();
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
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);
}
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);
write_locked_buffers(array, count);
goto repeat;
}
- __unlock_buffer(bh);
+ unlock_buffer(bh);
put_bh(bh);
}
spin_unlock(&lru_list_lock);
* 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))
mark_buffer_uptodate(bh, uptodate);
kiobuf = bh->b_private;
- __unlock_buffer(bh);
- put_bh(bh);
+ unlock_buffer(bh);
end_kio_request(kiobuf, uptodate);
}
offset += size;
atomic_inc(&iobuf->io_count);
- get_bh(tmp);
submit_bh(rw, tmp);
/*
* Wait for IO if we have got too much
#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 */
--- /dev/null
+#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 */
__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
#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 */
#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 __ */
* 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 */
* 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 */
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_ */
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 __ */
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 __ */
#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__) */
-/* $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)
(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");
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);
}
#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__) */
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) ;
#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
#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 */
#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
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);
*/
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;
} 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);
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 {
int check_args(struct divert_cf *div_cf, struct net_device **dev)
{
char devname[32];
-
+ int ret;
+
if (dev == NULL)
return -EFAULT;
/* 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;
}
/*
* 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.
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
/*
*
* 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>
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 */
*
* 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>
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);
*
* 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>
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);
* 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.