Commit d925eab6 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by David S. Miller

[PATCH] PA-RISC driver update for 2.6.2

PA-RISC specific driver updates:

 - Stop pasting __FILE__
 - Improve card-mode Dino support (James Bottomley)
 - Fix dev->bridge rename (James Bottomley)
 - iosapic/SBA/LBA cleanups (Grant Grundler)
 - Improve LED support (Helge Deller)
 - Fix mux driver (Ryan Bradetich)
 - Make STI framebuffer work on RDI PrecisionBook (Helge Deller)
parent 537c1ab3
...@@ -106,6 +106,9 @@ config IOMMU_SBA ...@@ -106,6 +106,9 @@ config IOMMU_SBA
#config PCI_EPIC #config PCI_EPIC
# bool "EPIC/SAGA PCI support" # bool "EPIC/SAGA PCI support"
# depends on PCI # depends on PCI
# default y
# help
# Say Y here for V-class PCI, DMA/IOMMU, IRQ subsystem support.
config SUPERIO config SUPERIO
bool "SuperIO (SuckyIO) support" bool "SuperIO (SuckyIO) support"
......
...@@ -364,11 +364,11 @@ ccio_alloc_range(struct ioc *ioc, unsigned long pages_needed) ...@@ -364,11 +364,11 @@ ccio_alloc_range(struct ioc *ioc, unsigned long pages_needed)
CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 64); CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 64);
#endif #endif
} else { } else {
panic(__FILE__ ": %s() Too many pages to map. pages_needed: %ld\n", panic("%s: %s() Too many pages to map. pages_needed: %ld\n",
__FUNCTION__, pages_needed); __FILE__, __FUNCTION__, pages_needed);
} }
panic(__FILE__ ": %s() I/O MMU is out of mapping resources.\n", panic("%s: %s() I/O MMU is out of mapping resources.\n", __FILE__,
__FUNCTION__); __FUNCTION__);
resource_found: resource_found:
...@@ -441,7 +441,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) ...@@ -441,7 +441,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped)
CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 64); CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 64);
#endif #endif
} else { } else {
panic(__FILE__ ":%s() Too many pages to unmap.\n", panic("%s:%s() Too many pages to unmap.\n", __FILE__,
__FUNCTION__); __FUNCTION__);
} }
} }
...@@ -1447,7 +1447,8 @@ ccio_ioc_init(struct ioc *ioc) ...@@ -1447,7 +1447,8 @@ ccio_ioc_init(struct ioc *ioc)
ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL,
get_order(ioc->pdir_size)); get_order(ioc->pdir_size));
if(NULL == ioc->pdir_base) { if(NULL == ioc->pdir_base) {
panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__); panic("%s:%s() could not allocate I/O Page Table\n", __FILE__,
__FUNCTION__);
} }
memset(ioc->pdir_base, 0, ioc->pdir_size); memset(ioc->pdir_base, 0, ioc->pdir_size);
...@@ -1461,7 +1462,8 @@ ccio_ioc_init(struct ioc *ioc) ...@@ -1461,7 +1462,8 @@ ccio_ioc_init(struct ioc *ioc)
ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL,
get_order(ioc->res_size)); get_order(ioc->res_size));
if(NULL == ioc->res_map) { if(NULL == ioc->res_map) {
panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__); panic("%s:%s() could not allocate resource map\n", __FILE__,
__FUNCTION__);
} }
memset(ioc->res_map, 0, ioc->res_size); memset(ioc->res_map, 0, ioc->res_size);
...@@ -1627,11 +1629,11 @@ int ccio_request_resource(const struct parisc_device *dev, ...@@ -1627,11 +1629,11 @@ int ccio_request_resource(const struct parisc_device *dev,
if (!ioc) { if (!ioc) {
parent = &iomem_resource; parent = &iomem_resource;
} else if ((ioc->mmio_region->start <= dev->hpa) && } else if ((ioc->mmio_region->start <= res->start) &&
(dev->hpa < ioc->mmio_region->end)) { (res->end <= ioc->mmio_region->end)) {
parent = ioc->mmio_region; parent = ioc->mmio_region;
} else if (((ioc->mmio_region + 1)->start <= dev->hpa) && } else if (((ioc->mmio_region + 1)->start <= res->start) &&
(dev->hpa < (ioc->mmio_region + 1)->end)) { (res->end <= (ioc->mmio_region + 1)->end)) {
parent = ioc->mmio_region + 1; parent = ioc->mmio_region + 1;
} else { } else {
return -EBUSY; return -EBUSY;
......
...@@ -175,7 +175,7 @@ static int dino_current_bus = 0; ...@@ -175,7 +175,7 @@ static int dino_current_bus = 0;
static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val) int size, u32 *val)
{ {
struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->dev)); struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
unsigned long base_addr = d->hba.base_addr; unsigned long base_addr = d->hba.base_addr;
...@@ -209,7 +209,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -209,7 +209,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where, static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val) int size, u32 val)
{ {
struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->dev)); struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
unsigned long base_addr = d->hba.base_addr; unsigned long base_addr = d->hba.base_addr;
...@@ -468,14 +468,14 @@ static void __init ...@@ -468,14 +468,14 @@ static void __init
dino_card_setup(struct pci_bus *bus, unsigned long base_addr) dino_card_setup(struct pci_bus *bus, unsigned long base_addr)
{ {
int i; int i;
struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev)); struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
struct resource *res; struct resource *res;
char name[128]; char name[128];
int size; int size;
res = &dino_dev->hba.lmmio_space; res = &dino_dev->hba.lmmio_space;
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->dev->bus_id); size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->bridge->bus_id);
res->name = kmalloc(size+1, GFP_KERNEL); res->name = kmalloc(size+1, GFP_KERNEL);
if(res->name) if(res->name)
strcpy((char *)res->name, name); strcpy((char *)res->name, name);
...@@ -489,7 +489,7 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr) ...@@ -489,7 +489,7 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr)
struct list_head *ln, *tmp_ln; struct list_head *ln, *tmp_ln;
printk(KERN_ERR "Dino: cannot attach bus %s\n", printk(KERN_ERR "Dino: cannot attach bus %s\n",
bus->dev->bus_id); bus->bridge->bus_id);
/* kill the bus, we can't do anything with it */ /* kill the bus, we can't do anything with it */
list_for_each_safe(ln, tmp_ln, &bus->devices) { list_for_each_safe(ln, tmp_ln, &bus->devices) {
struct pci_dev *dev = pci_dev_b(ln); struct pci_dev *dev = pci_dev_b(ln);
...@@ -560,11 +560,11 @@ dino_fixup_bus(struct pci_bus *bus) ...@@ -560,11 +560,11 @@ dino_fixup_bus(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
struct pci_dev *dev; struct pci_dev *dev;
struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev)); struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
int port_base = HBA_PORT_BASE(dino_dev->hba.hba_num); int port_base = HBA_PORT_BASE(dino_dev->hba.hba_num);
DBG(KERN_WARNING "%s(0x%p) bus %d sysdata 0x%p\n", DBG(KERN_WARNING "%s(0x%p) bus %d sysdata 0x%p\n",
__FUNCTION__, bus, bus->secondary, bus->dev->platform_data); __FUNCTION__, bus, bus->secondary, bus->bridge->platform_data);
/* Firmware doesn't set up card-mode dino, so we have to */ /* Firmware doesn't set up card-mode dino, so we have to */
if (is_card_dino(&dino_dev->hba.dev->id)) { if (is_card_dino(&dino_dev->hba.dev->id)) {
...@@ -572,15 +572,23 @@ dino_fixup_bus(struct pci_bus *bus) ...@@ -572,15 +572,23 @@ dino_fixup_bus(struct pci_bus *bus)
} else if(bus->parent == NULL) { } else if(bus->parent == NULL) {
/* must have a dino above it, reparent the resources /* must have a dino above it, reparent the resources
* into the dino window */ * into the dino window */
int i;
struct resource *res = &dino_dev->hba.lmmio_space;
bus->resource[0] = &(dino_dev->hba.io_space); bus->resource[0] = &(dino_dev->hba.io_space);
bus->resource[1] = &(dino_dev->hba.lmmio_space); for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) {
if(res[i].flags == 0)
break;
bus->resource[i+1] = &res[i];
}
} else if(bus->self) { } else if(bus->self) {
int i; int i;
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
for(i = 0; i < PCI_NUM_RESOURCES; i++) { for(i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
if((bus->self->resource[i].flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) if((bus->self->resource[i].flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
continue; continue;
...@@ -642,11 +650,10 @@ dino_fixup_bus(struct pci_bus *bus) ...@@ -642,11 +650,10 @@ dino_fixup_bus(struct pci_bus *bus)
* care about an expansion rom on parisc, since it * care about an expansion rom on parisc, since it
* usually contains (x86) bios code) */ * usually contains (x86) bios code) */
dev->resource[PCI_ROM_RESOURCE].flags = 0; dev->resource[PCI_ROM_RESOURCE].flags = 0;
dev->resource[PCI_ROM_RESOURCE].start = 0;
dev->resource[PCI_ROM_RESOURCE].end = 0;
if(dev->irq == 255) { if(dev->irq == 255) {
#define DINO_FIX_UNASSIGNED_INTERRUPTS
#ifdef DINO_FIX_UNASSIGNED_INTERRUPTS #ifdef DINO_FIX_UNASSIGNED_INTERRUPTS
/* This code tries to assign an unassigned /* This code tries to assign an unassigned
...@@ -660,7 +667,7 @@ dino_fixup_bus(struct pci_bus *bus) ...@@ -660,7 +667,7 @@ dino_fixup_bus(struct pci_bus *bus)
dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin);
dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq); dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq);
dev->irq += dino_dev->dino_region->data.irqbase dev->irq += dino_dev->dino_region->data.irqbase;
printk(KERN_WARNING "Device %s has undefined IRQ, setting to %d\n", dev->slot_name, irq_pin); printk(KERN_WARNING "Device %s has undefined IRQ, setting to %d\n", dev->slot_name, irq_pin);
#else #else
dev->irq = 65535; dev->irq = 65535;
...@@ -741,9 +748,9 @@ dino_card_init(struct dino_device *dino_dev) ...@@ -741,9 +748,9 @@ dino_card_init(struct dino_device *dino_dev)
static int __init static int __init
dino_bridge_init(struct dino_device *dino_dev, const char *name) dino_bridge_init(struct dino_device *dino_dev, const char *name)
{ {
unsigned long io_addr, bpos; unsigned long io_addr;
int result; int result, i, count=0;
struct resource *res; struct resource *res, *prevres = NULL;
/* /*
* Decoding IO_ADDR_EN only works for Built-in Dino * Decoding IO_ADDR_EN only works for Built-in Dino
* since PDC has already initialized this. * since PDC has already initialized this.
...@@ -755,21 +762,51 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name) ...@@ -755,21 +762,51 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name)
return -ENODEV; return -ENODEV;
} }
for (bpos = 0; (io_addr & (1 << bpos)) == 0; bpos++)
;
res = &dino_dev->hba.lmmio_space; res = &dino_dev->hba.lmmio_space;
for (i = 0; i < 32; i++) {
unsigned long start, end;
if((io_addr & (1 << i)) == 0)
continue;
start = (unsigned long)(signed int)(0xf0000000 | (i << 23));
end = start + 8 * 1024 * 1024 - 1;
DBG("DINO RANGE %d is at 0x%lx-0x%lx\n", count,
start, end);
if(prevres && prevres->end + 1 == start) {
prevres->end = end;
} else {
if(count >= DINO_MAX_LMMIO_RESOURCES) {
printk(KERN_ERR "%s is out of resource windows for range %d (0x%lx-0x%lx)\n", name, count, start, end);
break;
}
prevres = res;
res->start = start;
res->end = end;
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
res->name = kmalloc(64, GFP_KERNEL);
if(res->name)
snprintf((char *)res->name, 64, "%s LMMIO %d",
name, count);
res++;
count++;
}
}
res = &dino_dev->hba.lmmio_space;
res->start = (unsigned long)(signed int)(0xf0000000 | (bpos << 23)); for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) {
res->end = res->start + 8 * 1024 * 1024 - 1; if(res[i].flags == 0)
break;
result = ccio_request_resource(dino_dev->hba.dev, res); result = ccio_request_resource(dino_dev->hba.dev, &res[i]);
if (result < 0) { if (result < 0) {
printk(KERN_ERR "%s: failed to claim PCI Bus address space!\n", name); printk(KERN_ERR "%s: failed to claim PCI Bus address space %d (0x%lx-0x%lx)!\n", name, i, res[i].start, res[i].end);
return result; return result;
} }
}
return 0; return 0;
} }
...@@ -850,10 +887,8 @@ static int __init dino_common_init(struct parisc_device *dev, ...@@ -850,10 +887,8 @@ static int __init dino_common_init(struct parisc_device *dev,
res = &dino_dev->hba.io_space; res = &dino_dev->hba.io_space;
if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) { if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) {
res->name = "Dino I/O Port"; res->name = "Dino I/O Port";
dino_dev->hba.lmmio_space.name = "Dino LMMIO";
} else { } else {
res->name = "Cujo I/O Port"; res->name = "Cujo I/O Port";
dino_dev->hba.lmmio_space.name = "Cujo LMMIO";
} }
res->start = HBA_PORT_BASE(dino_dev->hba.hba_num); res->start = HBA_PORT_BASE(dino_dev->hba.hba_num);
res->end = res->start + (HBA_PORT_SPACE_SIZE - 1); res->end = res->start + (HBA_PORT_SPACE_SIZE - 1);
......
/*
* EISA "eeprom" support routines
*
* Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
*
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
......
This diff is collapsed.
/*
* Private structs/constants for PARISC IOSAPIC support
*
* Copyright (C) 2000 Hewlett Packard (Grant Grundler)
* Copyright (C) 2000,2003 Grant Grundler (grundler at parisc-linux.org)
* Copyright (C) 2002 Matthew Wilcox (willy at parisc-linux.org)
*
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* /*
** This file is private to iosapic driver. ** This file is private to iosapic driver.
** If stuff needs to be used by another driver, move it to a common file. ** If stuff needs to be used by another driver, move it to a common file.
...@@ -107,16 +130,16 @@ struct iosapic_irt { ...@@ -107,16 +130,16 @@ struct iosapic_irt {
#endif #endif
struct vector_info { struct vector_info {
struct iosapic_info *vi_ios; /* I/O SAPIC this vector is on */ struct iosapic_info *iosapic; /* I/O SAPIC this vector is on */
struct irt_entry *vi_irte; /* IRT entry */ struct irt_entry *irte; /* IRT entry */
u32 *vi_eoi_addr; /* precalculate EOI reg address */ u32 *eoi_addr; /* precalculate EOI reg address */
u32 vi_eoi_data; /* IA64: ? PA: swapped txn_data */ u32 eoi_data; /* IA64: ? PA: swapped txn_data */
int vi_txn_irq; /* virtual IRQ number for processor */ int txn_irq; /* virtual IRQ number for processor */
ulong vi_txn_addr; /* IA64: id_eid PA: partial HPA */ ulong txn_addr; /* IA64: id_eid PA: partial HPA */
ulong vi_txn_data; /* IA64: vector PA: EIR bit */ ulong txn_data; /* IA64: vector PA: EIR bit */
u8 vi_status; /* status/flags */ u8 status; /* status/flags */
u8 vi_irqline; /* INTINn(IRQ) */ u8 irqline; /* INTINn(IRQ) */
char vi_name[32]; /* user visible identity */ char name[32]; /* user visible identity */
}; };
......
...@@ -185,8 +185,6 @@ struct lba_device { ...@@ -185,8 +185,6 @@ struct lba_device {
void *iosapic_obj; void *iosapic_obj;
#ifdef __LP64__ #ifdef __LP64__
unsigned long lmmio_base; /* PA_VIEW - fixup MEM addresses */
unsigned long gmmio_base; /* PA_VIEW - Not used (yet) */
unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */ unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */
#endif #endif
...@@ -508,7 +506,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) ...@@ -508,7 +506,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
{ {
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->dev)); struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
u32 tok = LBA_CFG_TOK(local_bus, devfn); u32 tok = LBA_CFG_TOK(local_bus, devfn);
...@@ -518,7 +516,7 @@ static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int si ...@@ -518,7 +516,7 @@ static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int si
with risk we will miss PCI bus errors. */ with risk we will miss PCI bus errors. */
*data = lba_rd_cfg(d, tok, pos, size); *data = lba_rd_cfg(d, tok, pos, size);
DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data); DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data);
return(*data == ~0UL); return(*data == ~0U);
} }
if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d)))
...@@ -592,7 +590,7 @@ lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) ...@@ -592,7 +590,7 @@ lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
static int lba_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) static int lba_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
{ {
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->dev)); struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
u32 tok = LBA_CFG_TOK(local_bus,devfn); u32 tok = LBA_CFG_TOK(local_bus,devfn);
...@@ -695,20 +693,23 @@ lba_fixup_bus(struct pci_bus *bus) ...@@ -695,20 +693,23 @@ lba_fixup_bus(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
#ifdef FBB_SUPPORT #ifdef FBB_SUPPORT
u16 fbb_enable = PCI_STATUS_FAST_BACK;
u16 status; u16 status;
#endif #endif
struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->dev)); struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num); int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num);
DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n", DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n",
bus, bus->secondary, bus->dev->platform_data); bus, bus->secondary, bus->bridge->platform_data);
/* /*
** Properly Setup MMIO resources for this bus. ** Properly Setup MMIO resources for this bus.
** pci_alloc_primary_bus() mangles this. ** pci_alloc_primary_bus() mangles this.
*/ */
if (NULL == bus->self) { if (bus->self) {
/* PCI-PCI Bridge */
pci_read_bridge_bases(bus);
} else {
/* Host-PCI Bridge */
int err; int err;
DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n", DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
...@@ -725,59 +726,29 @@ lba_fixup_bus(struct pci_bus *bus) ...@@ -725,59 +726,29 @@ lba_fixup_bus(struct pci_bus *bus)
BUG(); BUG();
lba_dump_res(&ioport_resource, 2); lba_dump_res(&ioport_resource, 2);
} }
err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
if (err < 0) { if (err < 0) {
BUG(); BUG();
lba_dump_res(&iomem_resource, 2); lba_dump_res(&iomem_resource, 2);
} }
bus->resource[0] = &(ldev->hba.io_space); #ifdef __LP64__
bus->resource[1] = &(ldev->hba.lmmio_space); if (ldev->hba.gmmio_space.flags) {
} else { err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space));
/* KLUGE ALERT! if (err < 0) {
** PCI-PCI Bridge resource munging. BUG();
** This hack should go away in the near future. lba_dump_res(&iomem_resource, 2);
** It's based on the Alpha port.
*/
int i;
u16 cmd;
for (i = 0; i < 4; i++) {
bus->resource[i] =
&bus->self->resource[PCI_BRIDGE_RESOURCES+i];
bus->resource[i]->name = bus->name;
} }
#if 0 bus->resource[2] = &(ldev->hba.gmmio_space);
bus->resource[0]->flags |= pci_bridge_check_io(bus->self);
#else
bus->resource[0]->flags |= IORESOURCE_IO;
#endif
bus->resource[1]->flags |= IORESOURCE_MEM;
bus->resource[2]->flags = 0; /* Don't support prefetchable */
bus->resource[3]->flags = 0; /* not used */
/*
** If the PPB is enabled (ie already configured) then
** just read those values.
*/
(void) pci_read_config_word(bus->self, PCI_COMMAND, &cmd);
if (cmd & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)) {
pci_read_bridge_bases(bus);
} else {
/* Not configured.
** For now, propagate HBA limits to the bus;
** PCI will adjust them later.
*/
bus->resource[0]->end = ldev->hba.io_space.end;
bus->resource[1]->end = ldev->hba.lmmio_space.end;
} }
#endif
/* Turn off downstream PF memory address range by default */ /* advertize Host bridge resources to PCI bus */
bus->resource[2]->start = 1024*1024; bus->resource[0] = &(ldev->hba.io_space);
bus->resource[2]->end = bus->resource[2]->start - 1; bus->resource[1] = &(ldev->hba.lmmio_space);
} }
list_for_each(ln, &bus->devices) { list_for_each(ln, &bus->devices) {
int i; int i;
struct pci_dev *dev = pci_dev_b(ln); struct pci_dev *dev = pci_dev_b(ln);
...@@ -785,7 +756,7 @@ lba_fixup_bus(struct pci_bus *bus) ...@@ -785,7 +756,7 @@ lba_fixup_bus(struct pci_bus *bus)
DBG("lba_fixup_bus() %s\n", pci_name(dev)); DBG("lba_fixup_bus() %s\n", pci_name(dev));
/* Virtualize Device/Bridge Resources. */ /* Virtualize Device/Bridge Resources. */
for (i = 0; i < PCI_NUM_RESOURCES; i++) { for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
struct resource *res = &dev->resource[i]; struct resource *res = &dev->resource[i];
/* If resource not allocated - skip it */ /* If resource not allocated - skip it */
...@@ -817,7 +788,7 @@ lba_fixup_bus(struct pci_bus *bus) ...@@ -817,7 +788,7 @@ lba_fixup_bus(struct pci_bus *bus)
** No one on the bus can be allowed to use them. ** No one on the bus can be allowed to use them.
*/ */
(void) pci_read_config_word(dev, PCI_STATUS, &status); (void) pci_read_config_word(dev, PCI_STATUS, &status);
fbb_enable &= status; bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK);
#endif #endif
#ifdef __LP64__ #ifdef __LP64__
...@@ -1069,6 +1040,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ...@@ -1069,6 +1040,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
lba_dev->hba.bus_num.start = p->start; lba_dev->hba.bus_num.start = p->start;
lba_dev->hba.bus_num.end = p->end; lba_dev->hba.bus_num.end = p->end;
break; break;
case PAT_LMMIO: case PAT_LMMIO:
/* used to fix up pre-initialized MEM BARs */ /* used to fix up pre-initialized MEM BARs */
lba_dev->hba.lmmio_space_offset = p->start - io->start; lba_dev->hba.lmmio_space_offset = p->start - io->start;
...@@ -1080,23 +1052,28 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ...@@ -1080,23 +1052,28 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
r->flags = IORESOURCE_MEM; r->flags = IORESOURCE_MEM;
r->parent = r->sibling = r->child = NULL; r->parent = r->sibling = r->child = NULL;
break; break;
case PAT_GMMIO: case PAT_GMMIO:
printk(KERN_WARNING MODULE_NAME /* MMIO space > 4GB phys addr; for 64-bit BAR */
" range[%d] : ignoring GMMIO (0x%lx)\n", r = &(lba_dev->hba.gmmio_space);
i, p->start); r->name = "LBA GMMIO";
lba_dev->gmmio_base = p->start; r->start = p->start;
r->end = p->end;
r->flags = IORESOURCE_MEM;
r->parent = r->sibling = r->child = NULL;
break; break;
case PAT_NPIOP: case PAT_NPIOP:
printk(KERN_WARNING MODULE_NAME printk(KERN_WARNING MODULE_NAME
" range[%d] : ignoring NPIOP (0x%lx)\n", " range[%d] : ignoring NPIOP (0x%lx)\n",
i, p->start); i, p->start);
break; break;
case PAT_PIOP: case PAT_PIOP:
/* /*
** Postable I/O port space is per PCI host adapter. ** Postable I/O port space is per PCI host adapter.
** base of 64MB PIOP region
*/ */
/* save base of 64MB PIOP region */
lba_dev->iop_base = p->start; lba_dev->iop_base = p->start;
r = &(lba_dev->hba.io_space); r = &(lba_dev->hba.io_space);
...@@ -1106,6 +1083,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ...@@ -1106,6 +1083,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
r->flags = IORESOURCE_IO; r->flags = IORESOURCE_IO;
r->parent = r->sibling = r->child = NULL; r->parent = r->sibling = r->child = NULL;
break; break;
default: default:
printk(KERN_WARNING MODULE_NAME printk(KERN_WARNING MODULE_NAME
" range[%d] : unknown pat range type (0x%lx)\n", " range[%d] : unknown pat range type (0x%lx)\n",
...@@ -1259,7 +1237,11 @@ lba_hw_init(struct lba_device *d) ...@@ -1259,7 +1237,11 @@ lba_hw_init(struct lba_device *d)
#endif /* DEBUG_LBA_PAT */ #endif /* DEBUG_LBA_PAT */
#ifdef __LP64__ #ifdef __LP64__
#warning FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support /*
* FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support
* Only N-Class and up can really make use of Get slot status.
* maybe L-class too but I've never played with it there.
*/
#endif #endif
/* PDC_PAT_BUG: exhibited in rev 40.48 on L2000 */ /* PDC_PAT_BUG: exhibited in rev 40.48 on L2000 */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* (c) Copyright 2000 Red Hat Software * (c) Copyright 2000 Red Hat Software
* (c) Copyright 2000 Helge Deller <hdeller@redhat.com> * (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
* (c) Copyright 2001-2003 Helge Deller <deller@gmx.de> * (c) Copyright 2001-2004 Helge Deller <deller@gmx.de>
* (c) Copyright 2001 Randolph Chung <tausq@debian.org> * (c) Copyright 2001 Randolph Chung <tausq@debian.org>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -56,6 +56,7 @@ static int led_heartbeat = 1; ...@@ -56,6 +56,7 @@ static int led_heartbeat = 1;
static int led_diskio = 1; static int led_diskio = 1;
static int led_lanrxtx = 1; static int led_lanrxtx = 1;
static char lcd_text[32]; static char lcd_text[32];
static char lcd_text_default[] = "Linux " UTS_RELEASE;
#if 0 #if 0
#define DPRINTK(x) printk x #define DPRINTK(x) printk x
...@@ -196,19 +197,11 @@ static int led_proc_write(struct file *file, const char *buf, ...@@ -196,19 +197,11 @@ static int led_proc_write(struct file *file, const char *buf,
break; break;
case LED_HASLCD: case LED_HASLCD:
if (*cur == 0) while (*cur && cur[strlen(cur)-1] == '\n')
{
/* reset to default */
lcd_print("Linux " UTS_RELEASE);
}
else
{
/* chop off trailing \n.. if the user gives multiple
* \n then it's all their fault.. */
if (*cur && cur[strlen(cur)-1] == '\n')
cur[strlen(cur)-1] = 0; cur[strlen(cur)-1] = 0;
if (*cur == 0)
cur = lcd_text_default;
lcd_print(cur); lcd_print(cur);
}
break; break;
default: default:
return 0; return 0;
...@@ -438,11 +431,7 @@ static __inline__ int led_get_diskio_activity(void) ...@@ -438,11 +431,7 @@ static __inline__ int led_get_diskio_activity(void)
#define HEARTBEAT_2ND_RANGE_START (HZ*22/100) #define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
#define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN) #define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
#if HZ==100 #define NORMALIZED_COUNT(count) (count/(HZ/100))
#define NORMALIZED_COUNT(count) (count)
#else
#define NORMALIZED_COUNT(count) (count/(HZ/100))
#endif
static void led_tasklet_func(unsigned long unused) static void led_tasklet_func(unsigned long unused)
{ {
...@@ -567,7 +556,7 @@ int __init register_led_driver(int model, char *cmd_reg, char *data_reg) ...@@ -567,7 +556,7 @@ int __init register_led_driver(int model, char *cmd_reg, char *data_reg)
printk(KERN_INFO "LCD display at %p,%p registered\n", printk(KERN_INFO "LCD display at %p,%p registered\n",
LCD_CMD_REG , LCD_DATA_REG); LCD_CMD_REG , LCD_DATA_REG);
led_func_ptr = led_LCD_driver; led_func_ptr = led_LCD_driver;
lcd_print( "Linux " UTS_RELEASE ); lcd_print( lcd_text_default );
led_type = LED_HASLCD; led_type = LED_HASLCD;
break; break;
......
...@@ -44,6 +44,11 @@ ...@@ -44,6 +44,11 @@
#define MODULE_NAME "SBA" #define MODULE_NAME "SBA"
#ifdef CONFIG_PROC_FS
/* depends on proc fs support. But costs CPU performance */
#undef SBA_COLLECT_STATS
#endif
/* /*
** The number of debug flags is a clue - this code is fragile. ** The number of debug flags is a clue - this code is fragile.
** Don't even think about messing with it unless you have ** Don't even think about messing with it unless you have
...@@ -217,7 +222,7 @@ struct ioc { ...@@ -217,7 +222,7 @@ struct ioc {
} saved[DELAYED_RESOURCE_CNT]; } saved[DELAYED_RESOURCE_CNT];
#endif #endif
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
#define SBA_SEARCH_SAMPLE 0x100 #define SBA_SEARCH_SAMPLE 0x100
unsigned long avg_search[SBA_SEARCH_SAMPLE]; unsigned long avg_search[SBA_SEARCH_SAMPLE];
unsigned long avg_idx; /* current index into avg_search */ unsigned long avg_idx; /* current index into avg_search */
...@@ -560,7 +565,7 @@ static int ...@@ -560,7 +565,7 @@ static int
sba_alloc_range(struct ioc *ioc, size_t size) sba_alloc_range(struct ioc *ioc, size_t size)
{ {
unsigned int pages_needed = size >> IOVP_SHIFT; unsigned int pages_needed = size >> IOVP_SHIFT;
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
unsigned long cr_start = mfctl(16); unsigned long cr_start = mfctl(16);
#endif #endif
unsigned long pide; unsigned long pide;
...@@ -579,7 +584,8 @@ sba_alloc_range(struct ioc *ioc, size_t size) ...@@ -579,7 +584,8 @@ sba_alloc_range(struct ioc *ioc, size_t size)
if (pide >= (ioc->res_size << 3)) { if (pide >= (ioc->res_size << 3)) {
pide = sba_search_bitmap(ioc, pages_needed); pide = sba_search_bitmap(ioc, pages_needed);
if (pide >= (ioc->res_size << 3)) if (pide >= (ioc->res_size << 3))
panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa); panic("%s: I/O MMU @ %lx is out of mapping resources\n",
__FILE__, ioc->ioc_hpa);
} }
#ifdef ASSERT_PDIR_SANITY #ifdef ASSERT_PDIR_SANITY
...@@ -594,7 +600,7 @@ sba_alloc_range(struct ioc *ioc, size_t size) ...@@ -594,7 +600,7 @@ sba_alloc_range(struct ioc *ioc, size_t size)
(uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map),
ioc->res_bitshift ); ioc->res_bitshift );
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
{ {
unsigned long cr_end = mfctl(16); unsigned long cr_end = mfctl(16);
unsigned long tmp = cr_end - cr_start; unsigned long tmp = cr_end - cr_start;
...@@ -636,7 +642,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) ...@@ -636,7 +642,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
__FUNCTION__, (uint) iova, size, __FUNCTION__, (uint) iova, size,
bits_not_wanted, m, pide, res_ptr, *res_ptr); bits_not_wanted, m, pide, res_ptr, *res_ptr);
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
ioc->used_pages -= bits_not_wanted; ioc->used_pages -= bits_not_wanted;
#endif #endif
...@@ -854,7 +860,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, ...@@ -854,7 +860,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
sba_check_pdir(ioc,"Check before sba_map_single()"); sba_check_pdir(ioc,"Check before sba_map_single()");
#endif #endif
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
ioc->msingle_calls++; ioc->msingle_calls++;
ioc->msingle_pages += size >> IOVP_SHIFT; ioc->msingle_pages += size >> IOVP_SHIFT;
#endif #endif
...@@ -929,7 +935,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, ...@@ -929,7 +935,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
spin_lock_irqsave(&ioc->res_lock, flags); spin_lock_irqsave(&ioc->res_lock, flags);
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
ioc->usingle_calls++; ioc->usingle_calls++;
ioc->usingle_pages += size >> IOVP_SHIFT; ioc->usingle_pages += size >> IOVP_SHIFT;
#endif #endif
...@@ -1057,7 +1063,7 @@ sba_fill_pdir( ...@@ -1057,7 +1063,7 @@ sba_fill_pdir(
printk(KERN_DEBUG " %2d : %08lx/%05x %p/%05x\n", printk(KERN_DEBUG " %2d : %08lx/%05x %p/%05x\n",
nents, nents,
(unsigned long) sg_dma_address(startsg), cnt, (unsigned long) sg_dma_address(startsg), cnt,
sg_virt_address(startsg), startsg->length sg_virt_addr(startsg), startsg->length
); );
#else #else
DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n",
...@@ -1093,7 +1099,7 @@ sba_fill_pdir( ...@@ -1093,7 +1099,7 @@ sba_fill_pdir(
cnt += dma_offset; cnt += dma_offset;
dma_offset=0; /* only want offset on first chunk */ dma_offset=0; /* only want offset on first chunk */
cnt = ROUNDUP(cnt, IOVP_SIZE); cnt = ROUNDUP(cnt, IOVP_SIZE);
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
ioc->msg_pages += cnt >> IOVP_SHIFT; ioc->msg_pages += cnt >> IOVP_SHIFT;
#endif #endif
do { do {
...@@ -1300,7 +1306,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, ...@@ -1300,7 +1306,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
} }
#endif #endif
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
ioc->msg_calls++; ioc->msg_calls++;
#endif #endif
...@@ -1365,7 +1371,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ...@@ -1365,7 +1371,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
ioc = GET_IOC(dev); ioc = GET_IOC(dev);
ASSERT(ioc); ASSERT(ioc);
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
ioc->usg_calls++; ioc->usg_calls++;
#endif #endif
...@@ -1378,7 +1384,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ...@@ -1378,7 +1384,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
while (sg_dma_len(sglist) && nents--) { while (sg_dma_len(sglist) && nents--) {
sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
#ifdef CONFIG_PROC_FS #ifdef SBA_COLLECT_STATS
ioc->usg_pages += ((sg_dma_address(sglist) & ~IOVP_MASK) + sg_dma_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT; ioc->usg_pages += ((sg_dma_address(sglist) & ~IOVP_MASK) + sg_dma_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT;
ioc->usingle_calls--; /* kluge since call is unmap_sg() */ ioc->usingle_calls--; /* kluge since call is unmap_sg() */
#endif #endif
...@@ -1680,6 +1686,21 @@ sba_hw_init(struct sba_device *sba_dev) ...@@ -1680,6 +1686,21 @@ sba_hw_init(struct sba_device *sba_dev)
int num_ioc; int num_ioc;
u64 ioc_ctl; u64 ioc_ctl;
if (!is_pdc_pat()) {
/* Shutdown the USB controller on Astro-based workstations.
** Once we reprogram the IOMMU, the next DMA performed by
** USB will HPMC the box.
*/
pdc_io_reset_devices();
/*
** XXX May need something more sophisticated to deal
** with DMA from LAN. Maybe use page zero boot device
** as a handle to talk to PDC about which device to
** shutdown. This also needs to work for is_pdc_pat().
*/
}
ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL); ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->", DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
__FUNCTION__, sba_dev->sba_hpa, ioc_ctl); __FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
...@@ -1766,7 +1787,8 @@ sba_common_init(struct sba_device *sba_dev) ...@@ -1766,7 +1787,8 @@ sba_common_init(struct sba_device *sba_dev)
if (NULL == sba_dev->ioc[i].res_map) if (NULL == sba_dev->ioc[i].res_map)
{ {
panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ ); panic("%s:%s() could not allocate resource map\n",
__FILE__, __FUNCTION__ );
} }
memset(sba_dev->ioc[i].res_map, 0, res_size); memset(sba_dev->ioc[i].res_map, 0, res_size);
...@@ -1829,7 +1851,9 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) ...@@ -1829,7 +1851,9 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len)
struct sba_device *sba_dev = sba_list; struct sba_device *sba_dev = sba_list;
struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */
int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
#ifdef SBA_COLLECT_STATS
unsigned long i = 0, avg = 0, min, max; unsigned long i = 0, avg = 0, min, max;
#endif
sprintf(buf, "%s rev %d.%d\n", sprintf(buf, "%s rev %d.%d\n",
sba_dev->name, sba_dev->name,
...@@ -1841,13 +1865,14 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) ...@@ -1841,13 +1865,14 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len)
(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */
total_pages); total_pages);
sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
#ifdef SBA_COLLECT_STATS
sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf,
total_pages - ioc->used_pages, ioc->used_pages, total_pages - ioc->used_pages, ioc->used_pages,
(int) (ioc->used_pages * 100 / total_pages)); (int) (ioc->used_pages * 100 / total_pages));
sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
min = max = ioc->avg_search[0]; min = max = ioc->avg_search[0];
for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
avg += ioc->avg_search[i]; avg += ioc->avg_search[i];
...@@ -1876,6 +1901,7 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) ...@@ -1876,6 +1901,7 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len)
sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n",
buf, ioc->usg_calls, ioc->usg_pages, buf, ioc->usg_calls, ioc->usg_pages,
(int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); (int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
#endif
return strlen(buf); return strlen(buf);
} }
......
This diff is collapsed.
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> /* for udelay */
#include <asm/io.h> #include <asm/io.h>
#include <asm/parisc-device.h> #include <asm/parisc-device.h>
...@@ -47,15 +48,17 @@ ...@@ -47,15 +48,17 @@
#define MUX_STATUS(status) ((status & 0xF000) == 0x8000) #define MUX_STATUS(status) ((status & 0xF000) == 0x8000)
#define MUX_BREAK(status) ((status & 0xF000) == 0x2000) #define MUX_BREAK(status) ((status & 0xF000) == 0x2000)
#define UART_NR 8 #define MUX_NR 256
struct mux_card { static unsigned int port_cnt = 0;
struct uart_port ports[UART_NR]; static struct uart_port mux_ports[MUX_NR];
struct uart_driver drv;
struct mux_card *next; static struct uart_driver mux_driver = {
}; .owner = THIS_MODULE,
.driver_name = "ttyB",
static struct mux_card mux_card_head = { .dev_name = "ttyB",
.next = NULL, .major = MUX_MAJOR,
.minor = 0,
.nr = MUX_NR,
}; };
static struct timer_list mux_timer; static struct timer_list mux_timer;
...@@ -181,7 +184,7 @@ static void mux_write(struct uart_port *port) ...@@ -181,7 +184,7 @@ static void mux_write(struct uart_port *port)
return; return;
} }
count = (port->fifosize >> 1) - UART_GET_FIFO_CNT(port); count = (port->fifosize) - UART_GET_FIFO_CNT(port);
do { do {
UART_PUT_CHAR(port, xmit->buf[xmit->tail]); UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
...@@ -191,6 +194,9 @@ static void mux_write(struct uart_port *port) ...@@ -191,6 +194,9 @@ static void mux_write(struct uart_port *port)
} while(--count > 0); } while(--count > 0);
while(UART_GET_FIFO_CNT(port))
udelay(1);
if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
...@@ -361,28 +367,46 @@ static int mux_verify_port(struct uart_port *port, struct serial_struct *ser) ...@@ -361,28 +367,46 @@ static int mux_verify_port(struct uart_port *port, struct serial_struct *ser)
static void mux_poll(unsigned long unused) static void mux_poll(unsigned long unused)
{ {
int i; int i;
struct mux_card *card = &mux_card_head;
while(card) { for(i = 0; i < port_cnt; ++i) {
for(i = 0; i < UART_NR; ++i) { if(!mux_ports[i].info)
if(!card->ports[i].info)
continue; continue;
mux_read(&card->ports[i]); mux_read(&mux_ports[i]);
mux_write(&card->ports[i]); mux_write(&mux_ports[i]);
}
card = card->next;
} }
mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
} }
#ifdef CONFIG_SERIAL_MUX_CONSOLE #ifdef CONFIG_SERIAL_MUX_CONSOLE
static void mux_console_write(struct console *co, const char *s, unsigned count)
{
while(count--)
pdc_iodc_putc(*s++);
}
static int mux_console_setup(struct console *co, char *options)
{
return 0;
}
struct tty_driver *mux_console_device(struct console *co, int *index)
{
*index = co->index;
return mux_driver.tty_driver;
}
static struct console mux_console = { static struct console mux_console = {
.name = "ttyB", .name = "ttyB",
.flags = CON_PRINTBUFFER, .write = mux_console_write,
.device = mux_console_device,
.setup = mux_console_setup,
.flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
.index = 0, .index = 0,
}; };
#define MUX_CONSOLE &mux_console #define MUX_CONSOLE &mux_console
#else #else
#define MUX_CONSOLE NULL #define MUX_CONSOLE NULL
...@@ -416,63 +440,37 @@ static struct uart_ops mux_pops = { ...@@ -416,63 +440,37 @@ static struct uart_ops mux_pops = {
*/ */
static int __init mux_probe(struct parisc_device *dev) static int __init mux_probe(struct parisc_device *dev)
{ {
int i, j, ret, ports, port_cnt = 0; int i, status, ports;
u8 iodc_data[8]; u8 iodc_data[32];
unsigned long bytecnt; unsigned long bytecnt;
struct uart_port *port; struct uart_port *port;
struct mux_card *card = &mux_card_head;
ret = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 8); status = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 32);
if(ret != PDC_OK) { if(status != PDC_OK) {
printk(KERN_ERR "Serial mux: Unable to read IODC.\n"); printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
return 1; return 1;
} }
ports = GET_MUX_PORTS(iodc_data); ports = GET_MUX_PORTS(iodc_data);
printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.2\n", printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports);
ports);
if(!card->drv.nr) { if(!port_cnt) {
init_timer(&mux_timer); mux_driver.cons = MUX_CONSOLE;
mux_timer.function = mux_poll;
} else {
port_cnt += UART_NR;
while(card->next) {
card = card->next;
port_cnt += UART_NR;
}
}
for(i = 0; i < ports / UART_NR; ++i) {
if(card->drv.nr) {
card->next = kmalloc(sizeof(struct mux_card), GFP_KERNEL);
if(!card->next) {
printk(KERN_ERR "Serial mux: Unable to allocate memory.\n");
return 1;
}
memset(card->next, '\0', sizeof(struct mux_card));
card = card->next;
}
card->drv.owner = THIS_MODULE; status = uart_register_driver(&mux_driver);
card->drv.driver_name = "ttyB"; if(status) {
card->drv.dev_name = "ttyB";
card->drv.major = MUX_MAJOR;
card->drv.minor = port_cnt;
card->drv.nr = UART_NR;
card->drv.cons = MUX_CONSOLE;
ret = uart_register_driver(&card->drv);
if(ret) {
printk(KERN_ERR "Serial mux: Unable to register driver.\n"); printk(KERN_ERR "Serial mux: Unable to register driver.\n");
return 1; return 1;
} }
for(j = 0; j < UART_NR; ++j) { init_timer(&mux_timer);
port = &card->ports[j]; mux_timer.function = mux_poll;
}
for(i = 0; i < ports; ++i, ++port_cnt) {
port = &mux_ports[port_cnt];
port->iobase = 0; port->iobase = 0;
port->mapbase = dev->hpa + MUX_OFFSET + (j * MUX_LINE_OFFSET); port->mapbase = dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET);
port->iotype = SERIAL_IO_MEM; port->iotype = SERIAL_IO_MEM;
port->type = PORT_MUX; port->type = PORT_MUX;
...@@ -481,12 +479,14 @@ static int __init mux_probe(struct parisc_device *dev) ...@@ -481,12 +479,14 @@ static int __init mux_probe(struct parisc_device *dev)
port->fifosize = MUX_FIFO_SIZE; port->fifosize = MUX_FIFO_SIZE;
port->ops = &mux_pops; port->ops = &mux_pops;
port->flags = UPF_BOOT_AUTOCONF; port->flags = UPF_BOOT_AUTOCONF;
port->line = j; port->line = port_cnt;
ret = uart_add_one_port(&card->drv, port); status = uart_add_one_port(&mux_driver, port);
BUG_ON(ret); BUG_ON(status);
}
port_cnt += UART_NR;
} }
#ifdef CONFIG_SERIAL_MUX_CONSOLE
register_console(&mux_console);
#endif
return 0; return 0;
} }
...@@ -497,7 +497,7 @@ static struct parisc_device_id mux_tbl[] = { ...@@ -497,7 +497,7 @@ static struct parisc_device_id mux_tbl[] = {
MODULE_DEVICE_TABLE(parisc, mux_tbl); MODULE_DEVICE_TABLE(parisc, mux_tbl);
static struct parisc_driver mux_driver = { static struct parisc_driver serial_mux_driver = {
.name = "Serial MUX", .name = "Serial MUX",
.id_table = mux_tbl, .id_table = mux_tbl,
.probe = mux_probe, .probe = mux_probe,
...@@ -510,7 +510,7 @@ static struct parisc_driver mux_driver = { ...@@ -510,7 +510,7 @@ static struct parisc_driver mux_driver = {
*/ */
static int __init mux_init(void) static int __init mux_init(void)
{ {
return register_parisc_driver(&mux_driver); return register_parisc_driver(&serial_mux_driver);
} }
/** /**
...@@ -521,13 +521,12 @@ static int __init mux_init(void) ...@@ -521,13 +521,12 @@ static int __init mux_init(void)
static void __exit mux_exit(void) static void __exit mux_exit(void)
{ {
int i; int i;
struct mux_card *card = &mux_card_head;
for (i = 0; i < UART_NR; i++) { for (i = 0; i < port_cnt; i++) {
uart_remove_one_port(&card->drv, &card->ports[i]); uart_remove_one_port(&mux_driver, &mux_ports[i]);
} }
uart_unregister_driver(&card->drv); uart_unregister_driver(&mux_driver);
} }
module_init(mux_init); module_init(mux_init);
......
...@@ -588,7 +588,7 @@ sti_select_font(struct sti_cooked_rom *rom, ...@@ -588,7 +588,7 @@ sti_select_font(struct sti_cooked_rom *rom,
static void __init static void __init
sti_dump_rom(struct sti_rom *rom) sti_dump_rom(struct sti_rom *rom)
{ {
printk(KERN_INFO "STI id %04x-%04x, conforms to spec rev. %d.%02x\n", printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n",
rom->graphics_id[0], rom->graphics_id[0],
rom->graphics_id[1], rom->graphics_id[1],
rom->revno[0] >> 4, rom->revno[0] >> 4,
...@@ -869,14 +869,14 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd ...@@ -869,14 +869,14 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd
ok = 0; ok = 0;
if ((sig & 0xff) == 0x01) { if ((sig & 0xff) == 0x01) {
printk(KERN_INFO "STI byte mode ROM at %08lx, hpa at %08lx\n", DPRINTK((" byte mode ROM at %08lx, hpa at %08lx\n",
address, hpa); address, hpa));
ok = sti_read_rom(0, sti, address); ok = sti_read_rom(0, sti, address);
} }
if ((sig & 0xffff) == 0x0303) { if ((sig & 0xffff) == 0x0303) {
printk(KERN_INFO "STI word mode ROM at %08lx, hpa at %08lx\n", DPRINTK((" word mode ROM at %08lx, hpa at %08lx\n",
address, hpa); address, hpa));
ok = sti_read_rom(1, sti, address); ok = sti_read_rom(1, sti, address);
} }
...@@ -903,7 +903,7 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd ...@@ -903,7 +903,7 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd
sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request);
sti_dump_outptr(sti); sti_dump_outptr(sti);
printk(KERN_INFO "STI device: %s\n", sti->outptr.dev_name ); printk(KERN_INFO " graphics card name: %s\n", sti->outptr.dev_name );
sti_roms[num_sti_roms] = sti; sti_roms[num_sti_roms] = sti;
num_sti_roms++; num_sti_roms++;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Low level Frame buffer driver for HP workstations with * Low level Frame buffer driver for HP workstations with
* STI (standard text interface) video firmware. * STI (standard text interface) video firmware.
* *
* Copyright (C) 2001-2002 Helge Deller <deller@gmx.de> * Copyright (C) 2001-2004 Helge Deller <deller@gmx.de>
* Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de> * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
* *
* Based on: * Based on:
...@@ -39,10 +39,10 @@ ...@@ -39,10 +39,10 @@
*/ */
/* TODO: /* TODO:
* - remove the static fb_info to support multiple cards
* - 1bpp mode is completely untested * - 1bpp mode is completely untested
* - add support for h/w acceleration * - add support for h/w acceleration
* - add hardware cursor * - add hardware cursor
* - automatically disable double buffering (e.g. on RDI precisionbook laptop)
*/ */
...@@ -51,6 +51,8 @@ ...@@ -51,6 +51,8 @@
* #undef FALLBACK_TO_1BPP to reject support for unsupported cards */ * #undef FALLBACK_TO_1BPP to reject support for unsupported cards */
#undef FALLBACK_TO_1BPP #undef FALLBACK_TO_1BPP
#undef DEBUG_STIFB_REGS /* debug sti register accesses */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -154,8 +156,27 @@ static int __initdata stifb_force_bpp[MAX_STI_ROMS]; ...@@ -154,8 +156,27 @@ static int __initdata stifb_force_bpp[MAX_STI_ROMS];
#define READ_BYTE(fb,reg) __raw_readb((fb)->info.fix.mmio_start + (reg)) #define READ_BYTE(fb,reg) __raw_readb((fb)->info.fix.mmio_start + (reg))
#define READ_WORD(fb,reg) __raw_readl((fb)->info.fix.mmio_start + (reg)) #define READ_WORD(fb,reg) __raw_readl((fb)->info.fix.mmio_start + (reg))
#define WRITE_BYTE(value,fb,reg) __raw_writeb((value),(fb)->info.fix.mmio_start + (reg))
#define WRITE_WORD(value,fb,reg) __raw_writel((value),(fb)->info.fix.mmio_start + (reg))
#ifndef DEBUG_STIFB_REGS
# define DEBUG_OFF()
# define DEBUG_ON()
# define WRITE_BYTE(value,fb,reg) __raw_writeb((value),(fb)->info.fix.mmio_start + (reg))
# define WRITE_WORD(value,fb,reg) __raw_writel((value),(fb)->info.fix.mmio_start + (reg))
#else
static int debug_on = 1;
# define DEBUG_OFF() debug_on=0
# define DEBUG_ON() debug_on=1
# define WRITE_BYTE(value,fb,reg) do { if (debug_on) \
printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \
__FUNCTION__, reg, value, READ_BYTE(fb,reg)); \
__raw_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
# define WRITE_WORD(value,fb,reg) do { if (debug_on) \
printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \
__FUNCTION__, reg, value, READ_WORD(fb,reg)); \
__raw_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
#endif /* DEBUG_STIFB_REGS */
#define ENABLE 1 /* for enabling/disabling screen */ #define ENABLE 1 /* for enabling/disabling screen */
#define DISABLE 0 #define DISABLE 0
...@@ -449,6 +470,13 @@ SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber) ...@@ -449,6 +470,13 @@ SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber)
static void static void
SET_ATTR_SIZE(struct stifb_info *fb, int width, int height) SET_ATTR_SIZE(struct stifb_info *fb, int width, int height)
{ {
/* REG_6 seems to have special values when run on a
RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or
INTERNAL_EG_X1024). The values are:
0x2f0: internal (LCD) & external display enabled
0x2a0: external display only
0x000: zero on standard artist graphic cards
*/
WRITE_WORD(0x00000000, fb, REG_6); WRITE_WORD(0x00000000, fb, REG_6);
WRITE_WORD((width<<16) | height, fb, REG_9); WRITE_WORD((width<<16) | height, fb, REG_9);
WRITE_WORD(0x05000000, fb, REG_6); WRITE_WORD(0x05000000, fb, REG_6);
...@@ -730,7 +758,7 @@ hyperResetPlanes(struct stifb_info *fb, int enable) ...@@ -730,7 +758,7 @@ hyperResetPlanes(struct stifb_info *fb, int enable)
controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */ controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */
switch (enable) { switch (enable) {
case 1: /* ENABLE */ case ENABLE:
/* clear screen */ /* clear screen */
if (IS_24_DEVICE(fb)) if (IS_24_DEVICE(fb))
ngleDepth24_ClearImagePlanes(fb); ngleDepth24_ClearImagePlanes(fb);
...@@ -750,7 +778,7 @@ hyperResetPlanes(struct stifb_info *fb, int enable) ...@@ -750,7 +778,7 @@ hyperResetPlanes(struct stifb_info *fb, int enable)
hyperUndoITE(fb); hyperUndoITE(fb);
break; break;
case 0: /* DISABLE */ case DISABLE:
/* clear screen */ /* clear screen */
if (IS_24_DEVICE(fb)) if (IS_24_DEVICE(fb))
ngleDepth24_ClearImagePlanes(fb); ngleDepth24_ClearImagePlanes(fb);
...@@ -974,6 +1002,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green, ...@@ -974,6 +1002,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
green >>= 8; green >>= 8;
blue >>= 8; blue >>= 8;
DEBUG_OFF();
START_IMAGE_COLORMAP_ACCESS(fb); START_IMAGE_COLORMAP_ACCESS(fb);
if (fb->info.var.grayscale) { if (fb->info.var.grayscale) {
...@@ -1005,6 +1035,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green, ...@@ -1005,6 +1035,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
FINISH_IMAGE_COLORMAP_ACCESS(fb); FINISH_IMAGE_COLORMAP_ACCESS(fb);
} }
DEBUG_ON();
return 0; return 0;
} }
...@@ -1144,17 +1176,28 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp) ...@@ -1144,17 +1176,28 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
/* only supported cards are allowed */ /* only supported cards are allowed */
switch (fb->id) { switch (fb->id) {
case CRT_ID_VISUALIZE_EG:
/* look for a double buffering device like e.g. the
"INTERNAL_EG_DX1024" in the RDI precisionbook laptop
which won't work. The same device in non-double
buffering mode returns "INTERNAL_EG_X1024". */
if (strstr(sti->outptr.dev_name, "EG_DX")) {
printk(KERN_WARNING
"stifb: ignoring '%s'. Disable double buffering in IPL menu.\n",
sti->outptr.dev_name);
goto out_err0;
}
/* fall though */
case S9000_ID_ARTIST: case S9000_ID_ARTIST:
case S9000_ID_HCRX: case S9000_ID_HCRX:
case S9000_ID_TIMBER: case S9000_ID_TIMBER:
case S9000_ID_A1659A: case S9000_ID_A1659A:
case S9000_ID_A1439A: case S9000_ID_A1439A:
case CRT_ID_VISUALIZE_EG:
break; break;
default: default:
printk(KERN_WARNING "stifb: Unsupported gfx card id 0x%08x\n", printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",
fb->id); sti->outptr.dev_name, fb->id);
goto out_err1; goto out_err0;
} }
/* default to 8 bpp on most graphic chips */ /* default to 8 bpp on most graphic chips */
...@@ -1232,7 +1275,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp) ...@@ -1232,7 +1275,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
"stifb: Unsupported graphics card (id=0x%08x) " "stifb: Unsupported graphics card (id=0x%08x) "
"- skipping.\n", "- skipping.\n",
fb->id); fb->id);
goto out_err1; goto out_err0;
#endif #endif
} }
...@@ -1306,12 +1349,13 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp) ...@@ -1306,12 +1349,13 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
sti->info = info; /* save for unregister_framebuffer() */ sti->info = info; /* save for unregister_framebuffer() */
printk(KERN_INFO printk(KERN_INFO
"fb%d: %s %dx%d-%d frame buffer device, id: %04x, mmio: 0x%04lx\n", "fb%d: %s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",
fb->info.node, fb->info.node,
fix->id, fix->id,
var->xres, var->xres,
var->yres, var->yres,
var->bits_per_pixel, var->bits_per_pixel,
sti->outptr.dev_name,
fb->id, fb->id,
fix->mmio_start); fix->mmio_start);
...@@ -1324,16 +1368,24 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp) ...@@ -1324,16 +1368,24 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
release_mem_region(fix->smem_start, fix->smem_len); release_mem_region(fix->smem_start, fix->smem_len);
out_err1: out_err1:
fb_dealloc_cmap(&info->cmap); fb_dealloc_cmap(&info->cmap);
out_err0:
kfree(fb); kfree(fb);
return -ENXIO; return -ENXIO;
} }
static int stifb_disabled __initdata;
int __init int __init
stifb_init(void) stifb_init(void)
{ {
struct sti_struct *sti; struct sti_struct *sti;
int i; int i;
if (stifb_disabled) {
printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
return -ENXIO;
}
for (i = 1; i < MAX_STI_ROMS; i++) { for (i = 1; i < MAX_STI_ROMS; i++) {
sti = sti_get_rom(i); sti = sti_get_rom(i);
if (!sti) if (!sti)
...@@ -1379,6 +1431,11 @@ stifb_setup(char *options) ...@@ -1379,6 +1431,11 @@ stifb_setup(char *options)
if (!options || !*options) if (!options || !*options)
return 0; return 0;
if (strncmp(options, "off", 3) == 0) {
stifb_disabled = 1;
options += 3;
}
if (strncmp(options, "bpp", 3) == 0) { if (strncmp(options, "bpp", 3) == 0) {
options += 3; options += 3;
for (i = 0; i < MAX_STI_ROMS; i++) { for (i = 0; i < MAX_STI_ROMS; i++) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment