Commit e4870e45 authored by Pat Gefre's avatar Pat Gefre Committed by Tony Luck

[IA64-SGI] Remove Altix I/O code (ready for re-org).

Signed-off-by: default avatarPatrick Gefre <pfg@sgi.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 825d5976
......@@ -9,4 +9,4 @@
# Makefile for the sn ia64 subplatform
#
obj-y += kernel/ io/
obj-y += kernel/
# arch/ia64/sn/io/Makefile
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn io routines.
#
obj-y += xswitch.o cdl.o snia_if.o \
io.o machvec/ drivers/ platform_init/ sn2/ hwgfs/
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <asm/sn/sgi.h>
#include <asm/io.h>
#include <asm/sn/hcl.h>
#include <asm/sn/pci/pic.h>
#include "asm/sn/ioerror_handling.h"
#include <asm/sn/xtalk/xbow.h>
/* these get called directly in cdl_add_connpt in fops bypass hack */
extern int xbow_attach(vertex_hdl_t);
extern int pic_attach(vertex_hdl_t);
/*
* cdl: Connection and Driver List
*
* We are not porting this to Linux. Devices are registered via
* the normal Linux PCI layer. This is a very simplified version
* of cdl that will allow us to register and call our very own
* IO Infrastructure Drivers e.g. pcibr.
*/
#define MAX_SGI_IO_INFRA_DRVR 5
static struct cdl sgi_infrastructure_drivers[MAX_SGI_IO_INFRA_DRVR] =
{
{ PIC_WIDGET_PART_NUM_BUS0, PIC_WIDGET_MFGR_NUM, pic_attach /* &pcibr_fops */},
{ PIC_WIDGET_PART_NUM_BUS1, PIC_WIDGET_MFGR_NUM, pic_attach /* &pcibr_fops */},
{ XXBOW_WIDGET_PART_NUM, XXBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */},
{ XBOW_WIDGET_PART_NUM, XBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */},
{ PXBOW_WIDGET_PART_NUM, XXBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */},
};
/*
* cdl_add_connpt: We found a device and it's connect point. Call the
* attach routine of that driver.
*
* May need support for pciba registration here ...
*
* This routine use to create /hw/.id/pci/.../.. that links to
* /hw/module/006c06/Pbrick/xtalk/15/pci/<slotnum> .. do we still need
* it? The specified driver attach routine does not reference these
* vertices.
*/
int
cdl_add_connpt(int part_num, int mfg_num,
vertex_hdl_t connpt, int drv_flags)
{
int i;
/*
* Find the driver entry point and call the attach routine.
*/
for (i = 0; i < MAX_SGI_IO_INFRA_DRVR; i++) {
if ( (part_num == sgi_infrastructure_drivers[i].part_num) &&
( mfg_num == sgi_infrastructure_drivers[i].mfg_num) ) {
/*
* Call the device attach routines.
*/
if (sgi_infrastructure_drivers[i].attach) {
return(sgi_infrastructure_drivers[i].attach(connpt));
}
} else {
continue;
}
}
/* printk("WARNING: cdl_add_connpt: Driver not found for part_num 0x%x mfg_num 0x%x\n", part_num, mfg_num); */
return (0);
}
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 io routines.
obj-y += ioconfig_bus.o
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* ioconfig_bus - SGI's Persistent PCI Bus Numbering.
*
* Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/sn/sgi.h>
#include <asm/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/hcl.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/addrs.h>
#include <asm/sn/ioconfig_bus.h>
#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
#define SGI_IOCONFIG_BUS_VERSION "1.0"
/*
* Some Global definitions.
*/
static vertex_hdl_t ioconfig_bus_handle;
static unsigned long ioconfig_bus_debug;
static struct ioconfig_parm parm;
#ifdef IOCONFIG_BUS_DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
static u64 ioconfig_activated;
static char ioconfig_kernopts[128];
/*
* For debugging purpose .. hardcode a table ..
*/
struct ascii_moduleid *ioconfig_bus_table;
static int free_entry;
static int new_entry;
int next_basebus_number;
void
ioconfig_get_busnum(char *io_moduleid, int *bus_num)
{
struct ascii_moduleid *temp;
int index;
DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
*bus_num = -1;
temp = ioconfig_bus_table;
if (!ioconfig_bus_table)
return;
for (index = 0; index < free_entry; temp++, index++) {
if ( (io_moduleid[0] == temp->io_moduleid[0]) &&
(io_moduleid[1] == temp->io_moduleid[1]) &&
(io_moduleid[2] == temp->io_moduleid[2]) &&
(io_moduleid[4] == temp->io_moduleid[4]) &&
(io_moduleid[5] == temp->io_moduleid[5]) ) {
*bus_num = index * 0x10;
return;
}
}
/*
* New IO Brick encountered.
*/
if (((int)io_moduleid[0]) == 0) {
DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
return;
}
io_moduleid[3] = '#';
strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid);
*bus_num = free_entry * 0x10;
free_entry++;
}
static void
dump_ioconfig_table(void)
{
int index = 0;
struct ascii_moduleid *temp;
temp = ioconfig_bus_table;
if (!temp) {
DBG("ioconfig_bus_table tabel empty\n");
return;
}
while (index < free_entry) {
DBG("ASSCI Module ID %s\n", temp->io_moduleid);
temp++;
index++;
}
}
/*
* nextline
* This routine returns the nextline in the buffer.
*/
int nextline(char *buffer, char **next, char *line)
{
char *temp;
if (buffer[0] == 0x0) {
return(0);
}
temp = buffer;
while (*temp != 0) {
*line = *temp;
if (*temp != '\n'){
*line = *temp;
temp++; line++;
} else
break;
}
if (*temp == 0)
*next = temp;
else
*next = ++temp;
return(1);
}
/*
* build_pcibus_name
* This routine parses the ioconfig contents read into
* memory by ioconfig command in EFI and builds the
* persistent pci bus naming table.
*/
int
build_moduleid_table(char *file_contents, struct ascii_moduleid *table)
{
/*
* Read the whole file into memory.
*/
int rc;
char *name;
char *temp;
char *next;
char *curr;
char *line;
struct ascii_moduleid *moduleid;
line = kmalloc(256, GFP_KERNEL);
name = kmalloc(125, GFP_KERNEL);
if (!line || !name) {
if (line)
kfree(line);
if (name)
kfree(name);
printk("build_moduleid_table(): Unabled to allocate memmory");
return -ENOMEM;
}
memset(line, 0,256);
memset(name, 0, 125);
moduleid = table;
curr = file_contents;
while (nextline(curr, &next, line)){
DBG("curr 0x%lx next 0x%lx\n", curr, next);
temp = line;
/*
* Skip all leading Blank lines ..
*/
while (isspace(*temp))
if (*temp != '\n')
temp++;
else
break;
if (*temp == '\n') {
curr = next;
memset(line, 0, 256);
continue;
}
/*
* Skip comment lines
*/
if (*temp == '#') {
curr = next;
memset(line, 0, 256);
continue;
}
/*
* Get the next free entry in the table.
*/
rc = sscanf(temp, "%s", name);
strcpy(&moduleid->io_moduleid[0], name);
DBG("Found %s\n", name);
moduleid++;
free_entry++;
curr = next;
memset(line, 0, 256);
}
new_entry = free_entry;
kfree(line);
kfree(name);
return 0;
}
int
ioconfig_bus_init(void)
{
DBG("ioconfig_bus_init called.\n");
ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
if (!ioconfig_bus_table) {
printk("ioconfig_bus_init : cannot allocate memory\n");
return -1;
}
memset(ioconfig_bus_table, 0, 512);
/*
* If ioconfig options are given on the bootline .. take it.
*/
if (*ioconfig_kernopts != '\0') {
/*
* ioconfig="..." kernel options given.
*/
DBG("ioconfig_bus_init: Kernel Options given.\n");
if ( build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table) < 0 )
return -1;
(void) dump_ioconfig_table();
}
return 0;
}
void
ioconfig_bus_new_entries(void)
{
int index;
struct ascii_moduleid *temp;
if ((ioconfig_activated) && (free_entry > new_entry)) {
printk("### Please add the following new IO Bricks Module ID \n");
printk("### to your Persistent Bus Numbering Config File\n");
} else
return;
index = new_entry;
if (!ioconfig_bus_table) {
printk("ioconfig_bus_table table is empty\n");
return;
}
temp = &ioconfig_bus_table[index];
while (index < free_entry) {
printk("%s\n", (char *)temp);
temp++;
index++;
}
printk("### End\n");
}
static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
/*
* Copy in the parameters.
*/
if (copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm)))
return -EFAULT;
parm.number = free_entry - new_entry;
parm.ioconfig_activated = ioconfig_activated;
if (copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm)))
return -EFAULT;
if (!ioconfig_bus_table)
return -EFAULT;
if (copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry)))
return -EFAULT;
return 0;
}
/*
* ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
*/
static int ioconfig_bus_open(struct inode * inode, struct file * filp)
{
if (ioconfig_bus_debug) {
DBG("ioconfig_bus_open called.\n");
}
return(0);
}
/*
* ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
*/
static int ioconfig_bus_close(struct inode * inode, struct file * filp)
{
if (ioconfig_bus_debug) {
DBG("ioconfig_bus_close called.\n");
}
return(0);
}
struct file_operations ioconfig_bus_fops = {
.ioctl = ioconfig_bus_ioctl,
.open = ioconfig_bus_open, /* open */
.release=ioconfig_bus_close /* release */
};
/*
* init_ifconfig_bus() - Boot time initialization. Ensure that it is called
* after hwgfs has been initialized.
*
*/
int init_ioconfig_bus(void)
{
ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus",
0, 0,
0, 0,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
&ioconfig_bus_fops, NULL);
if (ioconfig_bus_handle == NULL) {
panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
}
return 0;
}
static int __init ioconfig_bus_setup (char *str)
{
char *temp;
DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
temp = (char *)ioconfig_kernopts;
memset(temp, 0, 128);
while ( (*str != '\0') && !isspace (*str) ) {
if (*str == ',') {
*temp = '\n';
temp++;
str++;
continue;
}
*temp = *str;
temp++;
str++;
}
return(0);
}
__setup("ioconfig=", ioconfig_bus_setup);
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 io routines.
obj-y += hcl.o labelcl.o hcl_util.o ramfs.o interface.o
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/sn/sgi.h>
#include <asm/io.h>
#include <asm/sn/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/hwgfs.h>
#include <asm/sn/hcl.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/hcl_util.h>
#include <asm/sn/nodepda.h>
static vertex_hdl_t hwgraph_all_cnodes = GRAPH_VERTEX_NONE;
extern vertex_hdl_t hwgraph_root;
static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE;
extern int maxcpus;
void
mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid)
{
char cpuid_buffer[10];
if (cpuid == CPU_NONE)
return;
if (hwgraph_all_cpuids == GRAPH_VERTEX_NONE) {
(void)hwgraph_path_add( hwgraph_root,
EDGE_LBL_CPUNUM,
&hwgraph_all_cpuids);
}
sprintf(cpuid_buffer, "%ld", cpuid);
(void)hwgraph_edge_add( hwgraph_all_cpuids, vhdl, cpuid_buffer);
}
/*
** Return the "master" for a given vertex. A master vertex is a
** controller or adapter or other piece of hardware that the given
** vertex passes through on the way to the rest of the system.
*/
vertex_hdl_t
device_master_get(vertex_hdl_t vhdl)
{
graph_error_t rc;
vertex_hdl_t master;
rc = hwgraph_edge_get(vhdl, EDGE_LBL_MASTER, &master);
if (rc == GRAPH_SUCCESS)
return(master);
else
return(GRAPH_VERTEX_NONE);
}
/*
** Set the master for a given vertex.
** Returns 0 on success, non-0 indicates failure
*/
int
device_master_set(vertex_hdl_t vhdl, vertex_hdl_t master)
{
graph_error_t rc;
rc = hwgraph_edge_add(vhdl, master, EDGE_LBL_MASTER);
return(rc != GRAPH_SUCCESS);
}
/*
** Return the compact node id of the node that ultimately "owns" the specified
** vertex. In order to do this, we walk back through masters and connect points
** until we reach a vertex that represents a node.
*/
cnodeid_t
master_node_get(vertex_hdl_t vhdl)
{
cnodeid_t cnodeid;
vertex_hdl_t master;
for (;;) {
cnodeid = nodevertex_to_cnodeid(vhdl);
if (cnodeid != CNODEID_NONE)
return(cnodeid);
master = device_master_get(vhdl);
/* Check for exceptional cases */
if (master == vhdl) {
/* Since we got a reference to the "master" thru
* device_master_get() we should decrement
* its reference count by 1
*/
return(CNODEID_NONE);
}
if (master == GRAPH_VERTEX_NONE) {
master = hwgraph_connectpt_get(vhdl);
if ((master == GRAPH_VERTEX_NONE) ||
(master == vhdl)) {
return(CNODEID_NONE);
}
}
vhdl = master;
}
}
/*
** If the specified device represents a node, return its
** compact node ID; otherwise, return CNODEID_NONE.
*/
cnodeid_t
nodevertex_to_cnodeid(vertex_hdl_t vhdl)
{
int rv = 0;
arbitrary_info_t cnodeid = CNODEID_NONE;
rv = labelcl_info_get_LBL(vhdl, INFO_LBL_CNODEID, NULL, &cnodeid);
return((cnodeid_t)cnodeid);
}
void
mark_nodevertex_as_node(vertex_hdl_t vhdl, cnodeid_t cnodeid)
{
if (cnodeid == CNODEID_NONE)
return;
cnodeid_to_vertex(cnodeid) = vhdl;
labelcl_info_add_LBL(vhdl, INFO_LBL_CNODEID, INFO_DESC_EXPORT,
(arbitrary_info_t)cnodeid);
{
char cnodeid_buffer[10];
if (hwgraph_all_cnodes == GRAPH_VERTEX_NONE) {
(void)hwgraph_path_add( hwgraph_root,
EDGE_LBL_NODENUM,
&hwgraph_all_cnodes);
}
sprintf(cnodeid_buffer, "%d", cnodeid);
(void)hwgraph_edge_add( hwgraph_all_cnodes,
vhdl,
cnodeid_buffer);
HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, hwgraph_all_cnodes, NULL, "Creating path vhdl1\n");
}
}
/*
** dev_to_name converts a vertex_hdl_t into a canonical name. If the vertex_hdl_t
** represents a vertex in the hardware graph, it is converted in the
** normal way for vertices. If the vertex_hdl_t is an old vertex_hdl_t (one which
** does not represent a hwgraph vertex), we synthesize a name based
** on major/minor number.
**
** Usually returns a pointer to the original buffer, filled in as
** appropriate. If the buffer is too small to hold the entire name,
** or if anything goes wrong while determining the name, dev_to_name
** returns "UnknownDevice".
*/
char *
dev_to_name(vertex_hdl_t dev, char *buf, uint buflen)
{
return(vertex_to_name(dev, buf, buflen));
}
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
*
* Portions based on Adam Richter's smalldevfs and thus
* Copyright 2002-2003 Yggdrasil Computing, Inc.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/sn/hwgfs.h>
extern struct vfsmount *hwgfs_vfsmount;
static int
walk_parents_mkdir(
const char **path,
struct nameidata *nd,
int is_dir)
{
char *slash;
char buf[strlen(*path)+1];
int error;
while ((slash = strchr(*path, '/')) != NULL) {
int len = slash - *path;
memcpy(buf, *path, len);
buf[len] = '\0';
error = path_walk(buf, nd);
if (unlikely(error))
return error;
nd->dentry = lookup_create(nd, is_dir);
nd->flags |= LOOKUP_PARENT;
if (IS_ERR(nd->dentry))
return PTR_ERR(nd->dentry);
if (!nd->dentry->d_inode)
error = vfs_mkdir(nd->dentry->d_parent->d_inode,
nd->dentry, 0755);
up(&nd->dentry->d_parent->d_inode->i_sem);
if (unlikely(error))
return error;
*path += len + 1;
}
return 0;
}
/* On success, returns with parent_inode->i_sem taken. */
static int
hwgfs_decode(
hwgfs_handle_t dir,
const char *name,
int is_dir,
struct inode **parent_inode,
struct dentry **dentry)
{
struct nameidata nd;
int error;
if (!dir)
dir = hwgfs_vfsmount->mnt_sb->s_root;
memset(&nd, 0, sizeof(nd));
nd.flags = LOOKUP_PARENT;
nd.mnt = mntget(hwgfs_vfsmount);
nd.dentry = dget(dir);
error = walk_parents_mkdir(&name, &nd, is_dir);
if (unlikely(error))
return error;
error = path_walk(name, &nd);
if (unlikely(error))
return error;
*dentry = lookup_create(&nd, is_dir);
if (IS_ERR(*dentry))
return PTR_ERR(*dentry);
*parent_inode = (*dentry)->d_parent->d_inode;
return 0;
}
static int
path_len(
struct dentry *de,
struct dentry *root)
{
int len = 0;
while (de != root) {
len += de->d_name.len + 1; /* count the '/' */
de = de->d_parent;
}
return len; /* -1 because we omit the leading '/',
+1 because we include trailing '\0' */
}
int
hwgfs_generate_path(
hwgfs_handle_t de,
char *path,
int buflen)
{
struct dentry *hwgfs_root;
int len;
char *path_orig = path;
if (unlikely(de == NULL))
return -EINVAL;
hwgfs_root = hwgfs_vfsmount->mnt_sb->s_root;
if (unlikely(de == hwgfs_root))
return -EINVAL;
spin_lock(&dcache_lock);
len = path_len(de, hwgfs_root);
if (len > buflen) {
spin_unlock(&dcache_lock);
return -ENAMETOOLONG;
}
path += len - 1;
*path = '\0';
for (;;) {
path -= de->d_name.len;
memcpy(path, de->d_name.name, de->d_name.len);
de = de->d_parent;
if (de == hwgfs_root)
break;
*(--path) = '/';
}
spin_unlock(&dcache_lock);
BUG_ON(path != path_orig);
return 0;
}
hwgfs_handle_t
hwgfs_register(
hwgfs_handle_t dir,
const char *name,
unsigned int flags,
unsigned int major,
unsigned int minor,
umode_t mode,
void *ops,
void *info)
{
dev_t devnum = MKDEV(major, minor);
struct inode *parent_inode;
struct dentry *dentry;
int error;
error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
if (likely(!error)) {
error = vfs_mknod(parent_inode, dentry, mode, devnum);
if (likely(!error)) {
/*
* Do this inside parents i_sem to avoid racing
* with lookups.
*/
if (S_ISCHR(mode))
dentry->d_inode->i_fop = ops;
dentry->d_fsdata = info;
up(&parent_inode->i_sem);
} else {
up(&parent_inode->i_sem);
dput(dentry);
dentry = NULL;
}
}
return dentry;
}
int
hwgfs_mk_symlink(
hwgfs_handle_t dir,
const char *name,
unsigned int flags,
const char *link,
hwgfs_handle_t *handle,
void *info)
{
struct inode *parent_inode;
struct dentry *dentry;
int error;
error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
if (likely(!error)) {
error = vfs_symlink(parent_inode, dentry, link, S_IALLUGO);
dentry->d_fsdata = info;
if (handle)
*handle = dentry;
up(&parent_inode->i_sem);
/* dput(dentry); */
}
return error;
}
hwgfs_handle_t
hwgfs_mk_dir(
hwgfs_handle_t dir,
const char *name,
void *info)
{
struct inode *parent_inode;
struct dentry *dentry;
int error;
error = hwgfs_decode(dir, name, 1, &parent_inode, &dentry);
if (likely(!error)) {
error = vfs_mkdir(parent_inode, dentry, 0755);
up(&parent_inode->i_sem);
if (unlikely(error)) {
dput(dentry);
dentry = NULL;
} else {
dentry->d_fsdata = info;
}
}
return dentry;
}
void
hwgfs_unregister(
hwgfs_handle_t de)
{
struct inode *parent_inode = de->d_parent->d_inode;
if (S_ISDIR(de->d_inode->i_mode))
vfs_rmdir(parent_inode, de);
else
vfs_unlink(parent_inode, de);
}
/* XXX: this function is utterly bogus. Every use of it is racy and the
prototype is stupid. You have been warned. --hch. */
hwgfs_handle_t
hwgfs_find_handle(
hwgfs_handle_t base,
const char *name,
unsigned int major, /* IGNORED */
unsigned int minor, /* IGNORED */
char type, /* IGNORED */
int traverse_symlinks)
{
struct dentry *dentry = NULL;
struct nameidata nd;
int error;
BUG_ON(*name=='/');
memset(&nd, 0, sizeof(nd));
nd.mnt = mntget(hwgfs_vfsmount);
nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root);
nd.flags = (traverse_symlinks ? LOOKUP_FOLLOW : 0);
error = path_walk(name, &nd);
if (likely(!error)) {
dentry = nd.dentry;
path_release(&nd); /* stale data from here! */
}
return dentry;
}
hwgfs_handle_t
hwgfs_get_parent(
hwgfs_handle_t de)
{
struct dentry *parent;
spin_lock(&de->d_lock);
parent = de->d_parent;
spin_unlock(&de->d_lock);
return parent;
}
int
hwgfs_set_info(
hwgfs_handle_t de,
void *info)
{
if (unlikely(de == NULL))
return -EINVAL;
de->d_fsdata = info;
return 0;
}
void *
hwgfs_get_info(
hwgfs_handle_t de)
{
return de->d_fsdata;
}
EXPORT_SYMBOL(hwgfs_generate_path);
EXPORT_SYMBOL(hwgfs_register);
EXPORT_SYMBOL(hwgfs_unregister);
EXPORT_SYMBOL(hwgfs_mk_symlink);
EXPORT_SYMBOL(hwgfs_mk_dir);
EXPORT_SYMBOL(hwgfs_find_handle);
EXPORT_SYMBOL(hwgfs_get_parent);
EXPORT_SYMBOL(hwgfs_set_info);
EXPORT_SYMBOL(hwgfs_get_info);
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
*
* Mostly shameless copied from Linus Torvalds' ramfs and thus
* Copyright (C) 2000 Linus Torvalds.
* 2000 Transmeta Corp.
*/
#include <linux/module.h>
#include <linux/backing-dev.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/string.h>
#include <asm/uaccess.h>
/* some random number */
#define HWGFS_MAGIC 0x12061983
static struct super_operations hwgfs_ops;
static struct address_space_operations hwgfs_aops;
static struct file_operations hwgfs_file_operations;
static struct inode_operations hwgfs_file_inode_operations;
static struct inode_operations hwgfs_dir_inode_operations;
static struct backing_dev_info hwgfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
.memory_backed = 1, /* Does not contribute to dirty memory */
};
static struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
struct inode * inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_mapping->a_ops = &hwgfs_aops;
inode->i_mapping->backing_dev_info = &hwgfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch (mode & S_IFMT) {
default:
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
inode->i_op = &hwgfs_file_inode_operations;
inode->i_fop = &hwgfs_file_operations;
break;
case S_IFDIR:
inode->i_op = &hwgfs_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
inode->i_nlink++;
break;
case S_IFLNK:
inode->i_op = &page_symlink_inode_operations;
break;
}
}
return inode;
}
static int hwgfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
struct inode * inode = hwgfs_get_inode(dir->i_sb, mode, dev);
int error = -ENOSPC;
if (inode) {
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
}
return error;
}
static int hwgfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
return hwgfs_mknod(dir, dentry, mode | S_IFDIR, 0);
}
static int hwgfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *unused)
{
return hwgfs_mknod(dir, dentry, mode | S_IFREG, 0);
}
static int hwgfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
struct inode *inode;
int error = -ENOSPC;
inode = hwgfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
if (inode) {
int l = strlen(symname)+1;
error = page_symlink(inode, symname, l);
if (!error) {
d_instantiate(dentry, inode);
dget(dentry);
} else
iput(inode);
}
return error;
}
static struct address_space_operations hwgfs_aops = {
.readpage = simple_readpage,
.prepare_write = simple_prepare_write,
.commit_write = simple_commit_write
};
static struct file_operations hwgfs_file_operations = {
.read = generic_file_read,
.write = generic_file_write,
.mmap = generic_file_mmap,
.fsync = simple_sync_file,
.sendfile = generic_file_sendfile,
};
static struct inode_operations hwgfs_file_inode_operations = {
.getattr = simple_getattr,
};
static struct inode_operations hwgfs_dir_inode_operations = {
.create = hwgfs_create,
.lookup = simple_lookup,
.link = simple_link,
.unlink = simple_unlink,
.symlink = hwgfs_symlink,
.mkdir = hwgfs_mkdir,
.rmdir = simple_rmdir,
.mknod = hwgfs_mknod,
.rename = simple_rename,
};
static struct super_operations hwgfs_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
};
static int hwgfs_fill_super(struct super_block * sb, void * data, int silent)
{
struct inode * inode;
struct dentry * root;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = HWGFS_MAGIC;
sb->s_op = &hwgfs_ops;
inode = hwgfs_get_inode(sb, S_IFDIR | 0755, 0);
if (!inode)
return -ENOMEM;
root = d_alloc_root(inode);
if (!root) {
iput(inode);
return -ENOMEM;
}
sb->s_root = root;
return 0;
}
static struct super_block *hwgfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return get_sb_single(fs_type, flags, data, hwgfs_fill_super);
}
static struct file_system_type hwgfs_fs_type = {
.owner = THIS_MODULE,
.name = "hwgfs",
.get_sb = hwgfs_get_sb,
.kill_sb = kill_litter_super,
};
struct vfsmount *hwgfs_vfsmount;
int __init init_hwgfs_fs(void)
{
int error;
error = register_filesystem(&hwgfs_fs_type);
if (error)
return error;
hwgfs_vfsmount = kern_mount(&hwgfs_fs_type);
if (IS_ERR(hwgfs_vfsmount))
goto fail;
return 0;
fail:
unregister_filesystem(&hwgfs_fs_type);
return PTR_ERR(hwgfs_vfsmount);
}
static void __exit exit_hwgfs_fs(void)
{
unregister_filesystem(&hwgfs_fs_type);
}
MODULE_LICENSE("GPL");
module_init(init_hwgfs_fs)
module_exit(exit_hwgfs_fs)
This diff is collapsed.
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 io routines.
obj-y += pci.o pci_dma.o pci_bus_cvlink.o iomv.o
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/sn/simulator.h>
#include <asm/sn/pda.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/sn2/shub_mmr.h>
/**
* sn_io_addr - convert an in/out port to an i/o address
* @port: port to convert
*
* Legacy in/out instructions are converted to ld/st instructions
* on IA64. This routine will convert a port number into a valid
* SN i/o address. Used by sn_in*() and sn_out*().
*/
void *
sn_io_addr(unsigned long port)
{
if (!IS_RUNNING_ON_SIMULATOR()) {
/* On sn2, legacy I/O ports don't point at anything */
if (port < 64*1024)
return 0;
return( (void *) (port | __IA64_UNCACHED_OFFSET));
} else {
/* but the simulator uses them... */
unsigned long io_base;
unsigned long addr;
/*
* word align port, but need more than 10 bits
* for accessing registers in bedrock local block
* (so we don't do port&0xfff)
*/
if ((port >= 0x1f0 && port <= 0x1f7) ||
port == 0x3f6 || port == 0x3f7) {
io_base = (0xc000000fcc000000 | ((unsigned long)get_nasid() << 38));
addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
} else {
addr = __ia64_get_io_port_base() | ((port >> 2) << 2);
}
return(void *) addr;
}
}
EXPORT_SYMBOL(sn_io_addr);
/**
* sn_mmiob - I/O space memory barrier
*
* Acts as a memory mapped I/O barrier for platforms that queue writes to
* I/O space. This ensures that subsequent writes to I/O space arrive after
* all previous writes. For most ia64 platforms, this is a simple
* 'mf.a' instruction. For other platforms, mmiob() may have to read
* a chipset register to ensure ordering.
*
* On SN2, we wait for the PIO_WRITE_STATUS SHub register to clear.
* See PV 871084 for details about the WAR about zero value.
*
*/
void
sn_mmiob (void)
{
while ((((volatile unsigned long) (*pda->pio_write_status_addr)) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) !=
SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK)
cpu_relax();
}
EXPORT_SYMBOL(sn_mmiob);
/*
* SNI64 specific PCI support for SNI IO.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 1997, 1998, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <asm/sn/hcl.h>
#include <asm/sn/pci/pcibr_private.h>
/*
* These routines are only used during sn_pci_init for probing each bus, and
* can probably be removed with a little more cleanup now that the SAL routines
* work on sn2.
*/
extern vertex_hdl_t devfn_to_vertex(unsigned char bus, unsigned char devfn);
int sn_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
{
unsigned long res = 0;
vertex_hdl_t device_vertex;
device_vertex = devfn_to_vertex(bus->number, devfn);
if (!device_vertex)
return PCIBIOS_DEVICE_NOT_FOUND;
res = pciio_config_get(device_vertex, (unsigned)where, size);
*val = (u32)res;
return PCIBIOS_SUCCESSFUL;
}
int sn_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
{
vertex_hdl_t device_vertex;
device_vertex = devfn_to_vertex(bus->number, devfn);
if (!device_vertex)
return PCIBIOS_DEVICE_NOT_FOUND;
pciio_config_set(device_vertex, (unsigned)where, size, (uint64_t)val);
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops sn_pci_ops = {
.read = sn_read_config,
.write = sn_write_config,
};
This diff is collapsed.
This diff is collapsed.
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 io routines.
obj-y += sgi_io_init.o
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/pda.h>
extern void init_all_devices(void);
extern void klhwg_add_all_modules(vertex_hdl_t);
extern void klhwg_add_all_nodes(vertex_hdl_t);
extern int init_hcl(void);
extern vertex_hdl_t hwgraph_root;
extern void io_module_init(void);
extern int pci_bus_to_hcl_cvlink(void);
nasid_t console_nasid = (nasid_t) - 1;
char master_baseio_wid;
nasid_t master_baseio_nasid;
nasid_t master_nasid = INVALID_NASID; /* This is the partition master nasid */
/*
* per_hub_init
*
* This code is executed once for each Hub chip.
*/
static void __init
per_hub_init(cnodeid_t cnode)
{
nasid_t nasid;
nodepda_t *npdap;
ii_icmr_u_t ii_icmr;
ii_ibcr_u_t ii_ibcr;
ii_ilcsr_u_t ii_ilcsr;
nasid = cnodeid_to_nasid(cnode);
ASSERT(nasid != INVALID_NASID);
ASSERT(nasid_to_cnodeid(nasid) == cnode);
npdap = NODEPDA(cnode);
/* Disable the request and reply errors. */
REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000);
/*
* Set the total number of CRBs that can be used.
*/
ii_icmr.ii_icmr_regval = 0x0;
ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
if (enable_shub_wars_1_1()) {
// Set bit one of ICMR to prevent II from sending interrupt for II bug.
ii_icmr.ii_icmr_regval |= 0x1;
}
REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
/*
* Set the number of CRBs that both of the BTEs combined
* can use minus 1.
*/
ii_ibcr.ii_ibcr_regval = 0x0;
ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) {
ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
} else {
/*
* if the LLP is down, there is no attached I/O, so
* give BTE all the CRBs.
*/
ii_ibcr.ii_ibcr_fld_s.i_count = 0x14;
}
REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
/*
* Set CRB timeout to be 10ms.
*/
REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff);
REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
/* Initialize error interrupts for this hub. */
hub_error_init(cnode);
}
/*
* This routine is responsible for the setup of all the IRIX hwgraph style
* stuff that's been pulled into linux. It's called by sn_pci_find_bios which
* is called just before the generic Linux PCI layer does its probing (by
* platform_pci_fixup aka sn_pci_fixup).
*
* It is very IMPORTANT that this call is only made by the Master CPU!
*
*/
void __init
sgi_master_io_infr_init(void)
{
cnodeid_t cnode;
if (init_hcl() < 0) { /* Sets up the hwgraph compatibility layer */
printk("sgi_master_io_infr_init: Cannot init hcl\n");
return;
}
/*
* Initialize platform-dependent vertices in the hwgraph:
* module
* node
* cpu
* memory
* slot
* hub
* router
* xbow
*/
io_module_init(); /* Use to be called module_init() .. */
klhwg_add_all_modules(hwgraph_root);
klhwg_add_all_nodes(hwgraph_root);
for (cnode = 0; cnode < numionodes; cnode++)
per_hub_init(cnode);
/*
*
* Our IO Infrastructure drivers are in place ..
* Initialize the whole IO Infrastructure .. xwidget/device probes.
*
*/
init_all_devices();
pci_bus_to_hcl_cvlink();
}
inline int
check_nasid_equiv(nasid_t nasida, nasid_t nasidb)
{
if ((nasida == nasidb)
|| (nasida == NODEPDA(nasid_to_cnodeid(nasidb))->xbow_peer))
return 1;
else
return 0;
}
int
is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid)
{
/*
* If the widget numbers are different, we're not the master.
*/
if (test_wid != (xwidgetnum_t) master_baseio_wid) {
return 0;
}
/*
* If the NASIDs are the same or equivalent, we're the master.
*/
if (check_nasid_equiv(test_nasid, master_baseio_nasid)) {
return 1;
} else {
return 0;
}
}
# arch/ia64/sn/io/sn2/Makefile
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 specific io routines.
#
obj-y += pcibr/ ml_SN_intr.o shub_intr.o shuberror.o shub.o bte_error.o \
pic.o geo_op.o l1_command.o klconflib.o klgraph.o ml_SN_init.o \
ml_iograph.o module.o pciio.o xbow.o xtalk.o shubio.o
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <asm/smp.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/hcl.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/pci/pciio.h>
#include <asm/sn/pci/pcibr.h>
#include <asm/sn/xtalk/xtalk.h>
#include <asm/sn/pci/pcibr_private.h>
#include <asm/sn/intr.h>
#include <asm/sn/ioerror.h>
#include <asm/sn/sn2/shubio.h>
#include <asm/sn/bte.h>
/*
* Bte error handling is done in two parts. The first captures
* any crb related errors. Since there can be multiple crbs per
* interface and multiple interfaces active, we need to wait until
* all active crbs are completed. This is the first job of the
* second part error handler. When all bte related CRBs are cleanly
* completed, it resets the interfaces and gets them ready for new
* transfers to be queued.
*/
void bte_error_handler(unsigned long);
/*
* First part error handler. This is called whenever any error CRB interrupt
* is generated by the II.
*/
void
bte_crb_error_handler(vertex_hdl_t hub_v, int btenum,
int crbnum, ioerror_t * ioe, int bteop)
{
hubinfo_t hinfo;
struct bteinfo_s *bte;
hubinfo_get(hub_v, &hinfo);
bte = &hinfo->h_nodepda->bte_if[btenum];
/*
* The caller has already figured out the error type, we save that
* in the bte handle structure for the thread excercising the
* interface to consume.
*/
bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET;
bte->bte_error_count++;
BTE_PRINTK(("Got an error on cnode %d bte %d: HW error type 0x%x\n",
bte->bte_cnode, bte->bte_num, ioe->ie_errortype));
bte_error_handler((unsigned long) hinfo->h_nodepda);
}
/*
* Second part error handler. Wait until all BTE related CRBs are completed
* and then reset the interfaces.
*/
void
bte_error_handler(unsigned long _nodepda)
{
struct nodepda_s *err_nodepda = (struct nodepda_s *) _nodepda;
spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
nasid_t nasid;
int i;
int valid_crbs;
unsigned long irq_flags;
volatile u64 *notify;
bte_result_t bh_error;
ii_imem_u_t imem; /* II IMEM Register */
ii_icrb0_d_u_t icrbd; /* II CRB Register D */
ii_ibcr_u_t ibcr;
ii_icmr_u_t icmr;
ii_ieclr_u_t ieclr;
BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
smp_processor_id()));
spin_lock_irqsave(recovery_lock, irq_flags);
if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
(err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
smp_processor_id()));
spin_unlock_irqrestore(recovery_lock, irq_flags);
return;
}
/*
* Lock all interfaces on this node to prevent new transfers
* from being queued.
*/
for (i = 0; i < BTES_PER_NODE; i++) {
if (err_nodepda->bte_if[i].cleanup_active) {
continue;
}
spin_lock(&err_nodepda->bte_if[i].spinlock);
BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
smp_processor_id(), i));
err_nodepda->bte_if[i].cleanup_active = 1;
}
/* Determine information about our hub */
nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
/*
* A BTE transfer can use multiple CRBs. We need to make sure
* that all the BTE CRBs are complete (or timed out) before
* attempting to clean up the error. Resetting the BTE while
* there are still BTE CRBs active will hang the BTE.
* We should look at all the CRBs to see if they are allocated
* to the BTE and see if they are still active. When none
* are active, we can continue with the cleanup.
*
* We also want to make sure that the local NI port is up.
* When a router resets the NI port can go down, while it
* goes through the LLP handshake, but then comes back up.
*/
icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
/*
* There are errors which still need to be cleaned up by
* hubiio_crb_error_handler
*/
mod_timer(recovery_timer, HZ * 5);
BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
smp_processor_id()));
spin_unlock_irqrestore(recovery_lock, irq_flags);
return;
}
if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;
for (i = 0; i < IIO_NUM_CRBS; i++) {
if (!((1 << i) & valid_crbs)) {
/* This crb was not marked as valid, ignore */
continue;
}
icrbd.ii_icrb0_d_regval =
REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
if (icrbd.d_bteop) {
mod_timer(recovery_timer, HZ * 5);
BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
err_nodepda, smp_processor_id(), i));
spin_unlock_irqrestore(recovery_lock,
irq_flags);
return;
}
}
}
BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda,
smp_processor_id()));
/* Reenable both bte interfaces */
imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);
/* Clear IBLS0/1 error bits */
ieclr.ii_ieclr_regval = 0;
if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);
/* Reinitialize both BTE state machines. */
ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
for (i = 0; i < BTES_PER_NODE; i++) {
bh_error = err_nodepda->bte_if[i].bh_error;
if (bh_error != BTE_SUCCESS) {
/* There is an error which needs to be notified */
notify = err_nodepda->bte_if[i].most_rcnt_na;
BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
err_nodepda->bte_if[i].bte_cnode,
err_nodepda->bte_if[i].bte_num,
IBLS_ERROR | (u64) bh_error));
*notify = IBLS_ERROR | bh_error;
err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
}
err_nodepda->bte_if[i].cleanup_active = 0;
BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
smp_processor_id(), i));
spin_unlock(&err_nodepda->bte_if[i].spinlock);
}
del_timer(recovery_timer);
spin_unlock_irqrestore(recovery_lock, irq_flags);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/hcl.h>
#include <asm/sn/hcl_util.h>
#include <asm/sn/labelcl.h>
#include <asm/sn/router.h>
#include <asm/sn/module.h>
#include <asm/sn/ksys/l1.h>
#include <asm/sn/nodepda.h>
#include <asm/sn/clksupport.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/sn_sal.h>
#include <linux/ctype.h>
/* elsc_display_line writes up to 12 characters to either the top or bottom
* line of the L1 display. line points to a buffer containing the message
* to be displayed. The zero-based line number is specified by lnum (so
* lnum == 0 specifies the top line and lnum == 1 specifies the bottom).
* Lines longer than 12 characters, or line numbers not less than
* L1_DISPLAY_LINES, cause elsc_display_line to return an error.
*/
int elsc_display_line(nasid_t nasid, char *line, int lnum)
{
return 0;
}
/*
* iobrick routines
*/
/* iobrick_rack_bay_type_get fills in the three int * arguments with the
* rack number, bay number and brick type of the L1 being addressed. Note
* that if the L1 operation fails and this function returns an error value,
* garbage may be written to brick_type.
*/
int iobrick_rack_bay_type_get( nasid_t nasid, uint *rack,
uint *bay, uint *brick_type )
{
int result = 0;
if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
return( ELSC_ERROR_CMD_SEND );
*rack = (result & MODULE_RACK_MASK) >> MODULE_RACK_SHFT;
*bay = (result & MODULE_BPOS_MASK) >> MODULE_BPOS_SHFT;
*brick_type = (result & MODULE_BTYPE_MASK) >> MODULE_BTYPE_SHFT;
return 0;
}
int iomoduleid_get(nasid_t nasid)
{
int result = 0;
if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
return( ELSC_ERROR_CMD_SEND );
return result;
}
int
iobrick_type_get_nasid(nasid_t nasid)
{
uint rack, bay, type;
int t, ret;
extern char brick_types[];
if ((ret = iobrick_rack_bay_type_get(nasid, &rack, &bay, &type)) < 0) {
return ret;
}
/* convert brick_type to lower case */
if ((type >= 'A') && (type <= 'Z'))
type = type - 'A' + 'a';
/* convert to a module.h brick type */
for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
if( brick_types[t] == type ) {
return t;
}
}
return -1; /* unknown brick */
}
/*
* given a L1 bricktype, return a bricktype string. This string is the
* string that will be used in the hwpath for I/O bricks
*/
char *
iobrick_L1bricktype_to_name(int type)
{
switch (type)
{
default:
return("Unknown");
case L1_BRICKTYPE_PX:
return(EDGE_LBL_PXBRICK);
case L1_BRICKTYPE_OPUS:
return(EDGE_LBL_OPUSBRICK);
case L1_BRICKTYPE_IX:
return(EDGE_LBL_IXBRICK);
case L1_BRICKTYPE_C:
return("Cbrick");
case L1_BRICKTYPE_R:
return("Rbrick");
case L1_BRICKTYPE_CHI_CG:
return(EDGE_LBL_CGBRICK);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# arch/ia64/sn/io/sn2/pcibr/Makefile
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
#
# Makefile for the sn2 specific pci bridge routines.
#
obj-y += pcibr_ate.o pcibr_config.o \
pcibr_dvr.o pcibr_hints.o \
pcibr_intr.o pcibr_rrb.o \
pcibr_slot.o pcibr_error.o \
pcibr_reg.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Platform dependent support for IO probing.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <asm/sn/sgi.h>
#include <asm/sn/sn_sal.h>
/**
* ia64_sn_probe_io_slot - test a memory location for readability
* @paddr: physical address to probe
* @size: number bytes to read (1,2,4,8)
* @data_ptr: address to store value read by probe (-1 returned if probe fails)
*
* This function will probe a physical address to determine if
* the address can be read. If reading the address causes a BUS
* error, an error is returned. If the probe succeeds, the contents
* of the memory location is returned.
*
* Return values:
* 0 - probe successful
* 1 - probe failed (generated MCA)
* 2 - Bad arg
* <0 - PAL error
*/
u64
ia64_sn_probe_io_slot(long paddr, long size, void *data_ptr)
{
struct ia64_sal_retval isrv;
SAL_CALL(isrv, SN_SAL_PROBE, paddr, size, 0, 0, 0, 0, 0);
if (data_ptr) {
switch (size) {
case 1:
*((u8*)data_ptr) = (u8)isrv.v0;
break;
case 2:
*((u16*)data_ptr) = (u16)isrv.v0;
break;
case 4:
*((u32*)data_ptr) = (u32)isrv.v0;
break;
case 8:
*((u64*)data_ptr) = (u64)isrv.v0;
break;
default:
isrv.status = 2;
}
}
return isrv.status;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_SLOTNUM_H
#define _ASM_IA64_SN_SLOTNUM_H
typedef unsigned char slotid_t;
#include <asm/sn/sn2/slotnum.h>
#endif /* _ASM_IA64_SN_SLOTNUM_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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