Commit b46aedbc authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://ppc.bkbits.net/for-linus-ppc

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 20917119 f347cc1b
This diff is collapsed.
...@@ -1108,6 +1108,8 @@ config MCA ...@@ -1108,6 +1108,8 @@ config MCA
<file:Documentation/mca.txt> (and especially the web page given <file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel. there) before attempting to build an MCA bus kernel.
source "drivers/mca/Kconfig"
config HOTPLUG config HOTPLUG
bool "Support for hot-pluggable devices" bool "Support for hot-pluggable devices"
---help--- ---help---
......
This diff is collapsed.
...@@ -44,5 +44,6 @@ obj-$(CONFIG_MD) += md/ ...@@ -44,5 +44,6 @@ obj-$(CONFIG_MD) += md/
obj-$(CONFIG_BT) += bluetooth/ obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_HOTPLUG_PCI) += hotplug/ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
obj-$(CONFIG_ISDN_BOOL) += isdn/ obj-$(CONFIG_ISDN_BOOL) += isdn/
obj-$(CONFIG_MCA) += mca/
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -795,7 +795,6 @@ static inline void drain_rx_pool (amb_dev * dev, unsigned char pool) { ...@@ -795,7 +795,6 @@ static inline void drain_rx_pool (amb_dev * dev, unsigned char pool) {
return; return;
} }
#ifdef MODULE
static void drain_rx_pools (amb_dev * dev) { static void drain_rx_pools (amb_dev * dev) {
unsigned char pool; unsigned char pool;
...@@ -803,10 +802,7 @@ static void drain_rx_pools (amb_dev * dev) { ...@@ -803,10 +802,7 @@ static void drain_rx_pools (amb_dev * dev) {
for (pool = 0; pool < NUM_RX_POOLS; ++pool) for (pool = 0; pool < NUM_RX_POOLS; ++pool)
drain_rx_pool (dev, pool); drain_rx_pool (dev, pool);
return;
} }
#endif
static inline void fill_rx_pool (amb_dev * dev, unsigned char pool, int priority) { static inline void fill_rx_pool (amb_dev * dev, unsigned char pool, int priority) {
rx_in rx; rx_in rx;
......
...@@ -627,7 +627,7 @@ typedef struct { ...@@ -627,7 +627,7 @@ typedef struct {
struct amb_dev { struct amb_dev {
u8 irq; u8 irq;
u8 flags; long flags;
u32 iobase; u32 iobase;
u32 * membase; u32 * membase;
......
...@@ -603,8 +603,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r, ...@@ -603,8 +603,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
// note: rounding the rate down means rounding 'p' up // note: rounding the rate down means rounding 'p' up
const unsigned long br = test_bit (ultra, (hrz_flags *) &dev->flags) ? const unsigned long br = test_bit(ultra, &dev->flags) ? BR_ULT : BR_HRZ;
BR_ULT : BR_HRZ;
u32 div = CR_MIND; u32 div = CR_MIND;
u32 pre; u32 pre;
...@@ -1106,9 +1105,9 @@ static inline void rx_bus_master_complete_handler (hrz_dev * dev) { ...@@ -1106,9 +1105,9 @@ static inline void rx_bus_master_complete_handler (hrz_dev * dev) {
static inline int tx_hold (hrz_dev * dev) { static inline int tx_hold (hrz_dev * dev) {
while (test_and_set_bit (tx_busy, &dev->flags)) { while (test_and_set_bit (tx_busy, &dev->flags)) {
PRINTD (DBG_TX, "sleeping at tx lock %p %u", dev, dev->flags); PRINTD (DBG_TX, "sleeping at tx lock %p %lu", dev, dev->flags);
interruptible_sleep_on (&dev->tx_queue); interruptible_sleep_on (&dev->tx_queue);
PRINTD (DBG_TX, "woken at tx lock %p %u", dev, dev->flags); PRINTD (DBG_TX, "woken at tx lock %p %lu", dev, dev->flags);
if (signal_pending (current)) if (signal_pending (current))
return -1; return -1;
} }
......
...@@ -429,7 +429,7 @@ struct hrz_dev { ...@@ -429,7 +429,7 @@ struct hrz_dev {
#endif #endif
u8 irq; u8 irq;
u8 flags; long flags;
u8 tx_last; u8 tx_last;
u8 tx_idle; u8 tx_idle;
......
...@@ -328,13 +328,7 @@ struct mxser_hwconf mxsercfg[MXSER_BOARDS]; ...@@ -328,13 +328,7 @@ struct mxser_hwconf mxsercfg[MXSER_BOARDS];
* static functions: * static functions:
*/ */
#ifdef MODULE
int init_module(void);
void cleanup_module(void);
#endif
static void mxser_getcfg(int board, struct mxser_hwconf *hwconf); static void mxser_getcfg(int board, struct mxser_hwconf *hwconf);
int mxser_init(void);
static int mxser_get_ISA_conf(int, struct mxser_hwconf *); static int mxser_get_ISA_conf(int, struct mxser_hwconf *);
static int mxser_get_PCI_conf(struct pci_dev *, int, struct mxser_hwconf *); static int mxser_get_PCI_conf(struct pci_dev *, int, struct mxser_hwconf *);
static void mxser_do_softint(void *); static void mxser_do_softint(void *);
...@@ -373,21 +367,7 @@ static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned in ...@@ -373,21 +367,7 @@ static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned in
* The MOXA C168/C104 serial driver boot-time initialization code! * The MOXA C168/C104 serial driver boot-time initialization code!
*/ */
static void __exit mxser_module_exit(void)
#ifdef MODULE
int init_module(void)
{
int ret;
if (verbose)
printk("Loading module mxser ...\n");
ret = mxser_init();
if (verbose)
printk("Done.\n");
return (ret);
}
void cleanup_module(void)
{ {
int i, err = 0; int i, err = 0;
...@@ -411,8 +391,6 @@ void cleanup_module(void) ...@@ -411,8 +391,6 @@ void cleanup_module(void)
printk("Done.\n"); printk("Done.\n");
} }
#endif
int mxser_initbrd(int board, struct mxser_hwconf *hwconf) int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
{ {
...@@ -510,7 +488,7 @@ static int mxser_get_PCI_conf(struct pci_dev *pdev, int board_type, struct mxser ...@@ -510,7 +488,7 @@ static int mxser_get_PCI_conf(struct pci_dev *pdev, int board_type, struct mxser
return (0); return (0);
} }
int mxser_init(void) static int __init mxser_module_init(void)
{ {
int i, m, retval, b; int i, m, retval, b;
int n, index; int n, index;
...@@ -2493,3 +2471,6 @@ static void mxser_normal_mode(int port) ...@@ -2493,3 +2471,6 @@ static void mxser_normal_mode(int port)
} }
outb(0x00, port + 4); outb(0x00, port + 4);
} }
module_init(mxser_module_init);
module_exit(mxser_module_exit);
...@@ -44,7 +44,7 @@ struct sx_board { ...@@ -44,7 +44,7 @@ struct sx_board {
int poll; int poll;
int ta_type; int ta_type;
struct timer_list timer; struct timer_list timer;
int locks; long locks;
}; };
struct vpd_prom { struct vpd_prom {
......
...@@ -3,8 +3,9 @@ ...@@ -3,8 +3,9 @@
* *
* ADB HID driver for Power Macintosh computers. * ADB HID driver for Power Macintosh computers.
* *
* Adapted from drivers/macintosh/mac_keyb.c by Franz Sirl * Adapted from drivers/macintosh/mac_keyb.c by Franz Sirl.
* (see that file for its authors and contributors). * drivers/macintosh/mac_keyb.c was Copyright (C) 1996 Paul Mackerras
* with considerable contributions from Ben Herrenschmidt and others.
* *
* Copyright (C) 2000 Franz Sirl. * Copyright (C) 2000 Franz Sirl.
* *
...@@ -433,22 +434,17 @@ static void leds_done(struct adb_request *req) ...@@ -433,22 +434,17 @@ static void leds_done(struct adb_request *req)
static int static int
adb_message_handler(struct notifier_block *this, unsigned long code, void *x) adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
{ {
unsigned long flags;
switch (code) { switch (code) {
case ADB_MSG_PRE_RESET: case ADB_MSG_PRE_RESET:
case ADB_MSG_POWERDOWN: case ADB_MSG_POWERDOWN:
/* Stop the repeat timer. Autopoll is already off at this point */ /* Stop the repeat timer. Autopoll is already off at this point */
save_flags(flags);
cli();
{ {
int i; int i;
for (i = 1; i < 16; i++) { for (i = 1; i < 16; i++) {
if (adbhid[i]) if (adbhid[i])
del_timer(&adbhid[i]->input.timer); del_timer_sync(&adbhid[i]->input.timer);
} }
} }
restore_flags(flags);
/* Stop pending led requests */ /* Stop pending led requests */
while(!led_request.complete) while(!led_request.complete)
...@@ -479,7 +475,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id, ...@@ -479,7 +475,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
memset(adbhid[id], 0, sizeof(struct adbhid)); memset(adbhid[id], 0, sizeof(struct adbhid));
sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id); sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
init_input_dev(&adbhid[id]); init_input_dev(&adbhid[id]->input);
adbhid[id]->id = default_id; adbhid[id]->id = default_id;
adbhid[id]->original_handler_id = original_handler_id; adbhid[id]->original_handler_id = original_handler_id;
...@@ -508,21 +504,21 @@ adbhid_input_register(int id, int default_id, int original_handler_id, ...@@ -508,21 +504,21 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
switch (original_handler_id) { switch (original_handler_id) {
default: default:
printk("<unknown>.\n"); printk("<unknown>.\n");
adbhid[id]->input.idversion = ADB_KEYBOARD_UNKNOWN; adbhid[id]->input.id.version = ADB_KEYBOARD_UNKNOWN;
break; break;
case 0x01: case 0x02: case 0x03: case 0x06: case 0x08: case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:
case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C: case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:
case 0xC0: case 0xC3: case 0xC6: case 0xC0: case 0xC3: case 0xC6:
printk("ANSI.\n"); printk("ANSI.\n");
adbhid[id]->input.idversion = ADB_KEYBOARD_ANSI; adbhid[id]->input.id.version = ADB_KEYBOARD_ANSI;
break; break;
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D: case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1: case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
case 0xC4: case 0xC7: case 0xC4: case 0xC7:
printk("ISO, swapping keys.\n"); printk("ISO, swapping keys.\n");
adbhid[id]->input.idversion = ADB_KEYBOARD_ISO; adbhid[id]->input.id.version = ADB_KEYBOARD_ISO;
i = adbhid[id]->keycode[10]; i = adbhid[id]->keycode[10];
adbhid[id]->keycode[10] = adbhid[id]->keycode[50]; adbhid[id]->keycode[10] = adbhid[id]->keycode[50];
adbhid[id]->keycode[50] = i; adbhid[id]->keycode[50] = i;
...@@ -531,7 +527,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id, ...@@ -531,7 +527,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A: case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A:
case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9: case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9:
printk("JIS.\n"); printk("JIS.\n");
adbhid[id]->input.idversion = ADB_KEYBOARD_JIS; adbhid[id]->input.id.version = ADB_KEYBOARD_JIS;
break; break;
} }
......
comment "Micro Channel Architecture Bus support"
depends on MCA
config MCA_LEGACY
bool "Legacy MCA API Support"
depends on MCA
help
This compiles in support for the old slot based MCA API. If you
have an unconverted MCA driver, you will need to say Y here. It
is safe to say Y anyway.
config MCA_PROC_FS
bool "Support for the mca entry in /proc"
depends on MCA_LEGACY && PROC_FS
help
If you want the old style /proc/mca directory in addition to the
new style sysfs say Y here.
# Makefile for the Linux MCA bus support
obj-y := mca-bus.o mca-device.o mca-driver.o
obj-$(CONFIG_MCA_PROC_FS) += mca-proc.o
obj-$(CONFIG_MCA_LEGACY) += mca-legacy.o
export-objs := mca-bus.o mca-legacy.o mca-proc.o mca-driver.o
include $(TOPDIR)/Rules.make
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA bus support functions for sysfs.
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/mca.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
/* Very few machines have more than one MCA bus. However, there are
* those that do (Voyager 35xx/5xxx), so we do it this way for future
* expansion. None that I know have more than 2 */
struct mca_bus *mca_root_busses[MAX_MCA_BUSSES];
#define MCA_DEVINFO(i,s) { .pos = i, .name = s }
struct mca_device_info {
short pos_id; /* the 2 byte pos id for this card */
char name[DEVICE_NAME_SIZE];
};
static int mca_bus_match (struct device *dev, struct device_driver *drv)
{
struct mca_device *mca_dev = to_mca_device (dev);
struct mca_driver *mca_drv = to_mca_driver (drv);
const short *mca_ids = mca_drv->id_table;
int i;
if (!mca_ids)
return 0;
for(i = 0; mca_ids[i]; i++) {
if (mca_ids[i] == mca_dev->pos_id) {
mca_dev->index = i;
return 1;
}
}
return 0;
}
struct bus_type mca_bus_type = {
.name = "MCA",
.match = mca_bus_match,
};
EXPORT_SYMBOL (mca_bus_type);
static ssize_t mca_show_pos_id(struct device *dev, char *buf, size_t count,
loff_t off)
{
/* four digits, \n and trailing \0 */
char mybuf[6];
struct mca_device *mca_dev = to_mca_device(dev);
int len;
if(mca_dev->pos_id < MCA_DUMMY_POS_START)
len = sprintf(mybuf, "%04x\n", mca_dev->pos_id);
else
len = sprintf(mybuf, "none\n");
len++;
if(len > off) {
len = min((size_t)(len - off), count);
memcpy(buf + off, mybuf + off, len);
} else {
len = 0;
}
return len;
}
static ssize_t mca_show_pos(struct device *dev, char *buf, size_t count,
loff_t off)
{
/* enough for 8 two byte hex chars plus space and new line */
char mybuf[26];
int j, len=0;
struct mca_device *mca_dev = to_mca_device(dev);
for(j=0; j<8; j++)
len += sprintf(mybuf+len, "%02x ", mca_dev->pos[j]);
/* change last trailing space to new line */
mybuf[len-1] = '\n';
len++;
if(len > off) {
len = min((size_t)(len - off), count);
memcpy(buf + off, mybuf + off, len);
} else {
len = 0;
}
return len;
}
static DEVICE_ATTR(id, S_IRUGO, mca_show_pos_id, NULL);
static DEVICE_ATTR(pos, S_IRUGO, mca_show_pos, NULL);
int __init mca_register_device(int bus, struct mca_device *mca_dev)
{
struct mca_bus *mca_bus = mca_root_busses[bus];
mca_dev->dev.parent = &mca_bus->dev;
mca_dev->dev.bus = &mca_bus_type;
sprintf (mca_dev->dev.bus_id, "%02d:%02X", bus, mca_dev->slot);
mca_dev->dma_mask = mca_bus->default_dma_mask;
mca_dev->dev.dma_mask = &mca_dev->dma_mask;
if (device_register(&mca_dev->dev))
return 0;
device_create_file(&mca_dev->dev, &dev_attr_id);
device_create_file(&mca_dev->dev, &dev_attr_pos);
return 1;
}
/* */
struct mca_bus * __devinit mca_attach_bus(int bus)
{
struct mca_bus *mca_bus;
if (unlikely(mca_root_busses[bus] != NULL)) {
/* This should never happen, but just in case */
printk(KERN_EMERG "MCA tried to add already existing bus %d\n",
bus);
dump_stack();
return NULL;
}
mca_bus = kmalloc(sizeof(struct mca_bus), GFP_KERNEL);
if (!mca_bus)
return NULL;
memset(mca_bus, 0, sizeof(struct mca_bus));
sprintf(mca_bus->dev.bus_id,"mca%d",bus);
sprintf(mca_bus->dev.name,"Host %s MCA Bridge", bus ? "Secondary" : "Primary");
device_register(&mca_bus->dev);
mca_root_busses[bus] = mca_bus;
return mca_bus;
}
int __init mca_system_init (void)
{
return bus_register(&mca_bus_type);
}
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA device support functions
*
* These functions support the ongoing device access API.
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/mca.h>
/**
* mca_device_read_stored_pos - read POS register from stored data
* @mca_dev: device to read from
* @reg: register to read from
*
* Fetch a POS value that was stored at boot time by the kernel
* when it scanned the MCA space. The register value is returned.
* Missing or invalid registers report 0.
*/
unsigned char mca_device_read_stored_pos(struct mca_device *mca_dev, int reg)
{
if(reg < 0 || reg >= 8)
return 0;
return mca_dev->pos[reg];
}
EXPORT_SYMBOL(mca_device_read_stored_pos);
/**
* mca_device_read_pos - read POS register from card
* @mca_dev: device to read from
* @reg: register to read from
*
* Fetch a POS value directly from the hardware to obtain the
* current value. This is much slower than
* mca_device_read_stored_pos and may not be invoked from
* interrupt context. It handles the deep magic required for
* onboard devices transparently.
*/
unsigned char mca_device_read_pos(struct mca_device *mca_dev, int reg)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_read_pos(mca_dev, reg);
return mca_dev->pos[reg];
}
EXPORT_SYMBOL(mca_device_read_pos);
/**
* mca_device_write_pos - read POS register from card
* @mca_dev: device to write pos register to
* @reg: register to write to
* @byte: byte to write to the POS registers
*
* Store a POS value directly to the hardware. You should not
* normally need to use this function and should have a very good
* knowledge of MCA bus before you do so. Doing this wrongly can
* damage the hardware.
*
* This function may not be used from interrupt context.
*
*/
void mca_device_write_pos(struct mca_device *mca_dev, int reg,
unsigned char byte)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
mca_bus->f.mca_write_pos(mca_dev, reg, byte);
}
EXPORT_SYMBOL(mca_device_write_pos);
/**
* mca_device_transform_irq - transform the ADF obtained IRQ
* @mca_device: device whose irq needs transforming
* @irq: input irq from ADF
*
* MCA Adapter Definition Files (ADF) contain irq, ioport, memory
* etc. definitions. In systems with more than one bus, these need
* to be transformed through bus mapping functions to get the real
* system global quantities.
*
* This function transforms the interrupt number and returns the
* transformed system global interrupt
*/
int mca_device_transform_irq(struct mca_device *mca_dev, int irq)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_transform_irq(mca_dev, irq);
}
EXPORT_SYMBOL(mca_device_transform_irq);
/**
* mca_device_transform_ioport - transform the ADF obtained I/O port
* @mca_device: device whose port needs transforming
* @ioport: input I/O port from ADF
*
* MCA Adapter Definition Files (ADF) contain irq, ioport, memory
* etc. definitions. In systems with more than one bus, these need
* to be transformed through bus mapping functions to get the real
* system global quantities.
*
* This function transforms the I/O port number and returns the
* transformed system global port number.
*
* This transformation can be assumed to be linear for port ranges.
*/
int mca_device_transform_ioport(struct mca_device *mca_dev, int port)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_transform_ioport(mca_dev, port);
}
EXPORT_SYMBOL(mca_device_transform_ioport);
/**
* mca_device_transform_memory - transform the ADF obtained memory
* @mca_device: device whose memory region needs transforming
* @mem: memory region start from ADF
*
* MCA Adapter Definition Files (ADF) contain irq, ioport, memory
* etc. definitions. In systems with more than one bus, these need
* to be transformed through bus mapping functions to get the real
* system global quantities.
*
* This function transforms the memory region start and returns the
* transformed system global memory region (physical).
*
* This transformation can be assumed to be linear for region ranges.
*/
void *mca_device_transform_memory(struct mca_device *mca_dev, void *mem)
{
struct mca_bus *mca_bus = to_mca_bus(mca_dev->dev.parent);
return mca_bus->f.mca_transform_memory(mca_dev, mem);
}
EXPORT_SYMBOL(mca_device_transform_memory);
/**
* mca_device_claimed - check if claimed by driver
* @mca_dev: device to check
*
* Returns 1 if the slot has been claimed by a driver
*/
int mca_device_claimed(struct mca_device *mca_dev)
{
return mca_dev->driver_loaded;
}
EXPORT_SYMBOL(mca_device_claimed);
/**
* mca_device_set_claim - set the claim value of the driver
* @mca_dev: device to set value for
* @val: claim value to set (1 claimed, 0 unclaimed)
*/
void mca_device_set_claim(struct mca_device *mca_dev, int val)
{
mca_dev->driver_loaded = val;
}
EXPORT_SYMBOL(mca_device_set_claim);
/**
* mca_device_status - get the status of the device
* @mca_device: device to get
*
* returns an enumeration of the device status:
*
* MCA_ADAPTER_NORMAL adapter is OK.
* MCA_ADAPTER_NONE no adapter at device (should never happen).
* MCA_ADAPTER_DISABLED adapter is disabled.
* MCA_ADAPTER_ERROR adapter cannot be initialised.
*/
enum MCA_AdapterStatus mca_device_status(struct mca_device *mca_dev)
{
return mca_dev->status;
}
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA driver support functions for sysfs.
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/device.h>
#include <linux/mca.h>
#include <linux/module.h>
int mca_register_driver(struct mca_driver *mca_drv)
{
int r;
mca_drv->driver.bus = &mca_bus_type;
if ((r = driver_register(&mca_drv->driver)) < 0)
return r;
return 0;
}
EXPORT_SYMBOL(mca_register_driver);
void mca_unregister_driver(struct mca_driver *mca_drv)
{
driver_unregister(&mca_drv->driver);
}
EXPORT_SYMBOL(mca_unregister_driver);
This diff is collapsed.
/* -*- mode: c; c-basic-offset: 8 -*- */
/*
* MCA bus support functions for the proc fs.
*
* NOTE: this code *requires* the legacy MCA api.
*
* Legacy API means the API that operates in terms of MCA slot number
*
* (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
*
**-----------------------------------------------------------------------------
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/mca.h>
static int get_mca_info_helper(struct mca_device *mca_dev, char *page, int len)
{
int j;
for(j=0; j<8; j++)
len += sprintf(page+len, "%02x ",
mca_dev ? mca_dev->pos[j] : 0xff);
len += sprintf(page+len, " %s\n", mca_dev ? mca_dev->dev.name : "");
return len;
}
int get_mca_info(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int i, len = 0;
if(MCA_bus) {
struct mca_device *mca_dev;
/* Format POS registers of eight MCA slots */
for(i=0; i<MCA_MAX_SLOT_NR; i++) {
mca_dev = mca_find_device_by_slot(i);
len += sprintf(page+len, "Slot %d: ", i+1);
len = get_mca_info_helper(mca_dev, page, len);
}
/* Format POS registers of integrated video subsystem */
mca_dev = mca_find_device_by_slot(MCA_INTEGVIDEO);
len += sprintf(page+len, "Video : ");
len = get_mca_info_helper(mca_dev, page, len);
/* Format POS registers of integrated SCSI subsystem */
mca_dev = mca_find_device_by_slot(MCA_INTEGSCSI);
len += sprintf(page+len, "SCSI : ");
len = get_mca_info_helper(mca_dev, page, len);
/* Format POS registers of motherboard */
mca_dev = mca_find_device_by_slot(MCA_MOTHERBOARD);
len += sprintf(page+len, "Planar: ");
len = get_mca_info_helper(mca_dev, page, len);
} else {
/* Leave it empty if MCA not detected - this should *never*
* happen!
*/
}
if (len <= off+count) *eof = 1;
*start = page + off;
len -= off;
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*--------------------------------------------------------------------*/
static int mca_default_procfn(char* buf, struct mca_device *mca_dev)
{
int len = 0, i;
int slot = mca_dev->slot;
/* Print out the basic information */
if(slot < MCA_MAX_SLOT_NR) {
len += sprintf(buf+len, "Slot: %d\n", slot+1);
} else if(slot == MCA_INTEGSCSI) {
len += sprintf(buf+len, "Integrated SCSI Adapter\n");
} else if(slot == MCA_INTEGVIDEO) {
len += sprintf(buf+len, "Integrated Video Adapter\n");
} else if(slot == MCA_MOTHERBOARD) {
len += sprintf(buf+len, "Motherboard\n");
}
if(mca_dev->dev.name[0]) {
/* Drivers might register a name without /proc handler... */
len += sprintf(buf+len, "Adapter Name: %s\n",
mca_dev->dev.name);
} else {
len += sprintf(buf+len, "Adapter Name: Unknown\n");
}
len += sprintf(buf+len, "Id: %02x%02x\n",
mca_dev->pos[1], mca_dev->pos[0]);
len += sprintf(buf+len, "Enabled: %s\nPOS: ",
mca_isenabled(slot) ? "Yes" : "No");
for(i=0; i<8; i++) {
len += sprintf(buf+len, "%02x ", mca_dev->pos[i]);
}
len += sprintf(buf+len, "\nDriver Installed: %s",
mca_is_adapter_used(slot) ? "Yes" : "No");
buf[len++] = '\n';
buf[len] = 0;
return len;
} /* mca_default_procfn() */
static int get_mca_machine_info(char* page, char **start, off_t off,
int count, int *eof, void *data)
{
int len = 0;
len += sprintf(page+len, "Model Id: 0x%x\n", machine_id);
len += sprintf(page+len, "Submodel Id: 0x%x\n", machine_submodel_id);
len += sprintf(page+len, "BIOS Revision: 0x%x\n", BIOS_revision);
if (len <= off+count) *eof = 1;
*start = page + off;
len -= off;
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
static int mca_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct mca_device *mca_dev = (struct mca_device *)data;
int len = 0;
/* Get the standard info */
len = mca_default_procfn(page, mca_dev);
/* Do any device-specific processing, if there is any */
if(mca_dev->procfn) {
len += mca_dev->procfn(page+len, mca_dev->slot,
mca_dev->proc_dev);
}
if (len <= off+count) *eof = 1;
*start = page + off;
len -= off;
if (len>count) len = count;
if (len<0) len = 0;
return len;
} /* mca_read_proc() */
/*--------------------------------------------------------------------*/
void __init mca_do_proc_init(void)
{
int i;
struct proc_dir_entry *proc_mca;
struct proc_dir_entry* node = NULL;
struct mca_device *mca_dev;
proc_mca = proc_mkdir("mca", &proc_root);
create_proc_read_entry("pos",0,proc_mca,get_mca_info,NULL);
create_proc_read_entry("machine",0,proc_mca,get_mca_machine_info,NULL);
/* Initialize /proc/mca entries for existing adapters */
for(i = 0; i < MCA_NUMADAPTERS; i++) {
mca_dev = mca_find_device_by_slot(i);
if(!mca_dev)
continue;
mca_dev->procfn = NULL;
if(i < MCA_MAX_SLOT_NR) sprintf(mca_dev->procname,"slot%d", i+1);
else if(i == MCA_INTEGVIDEO) sprintf(mca_dev->procname,"video");
else if(i == MCA_INTEGSCSI) sprintf(mca_dev->procname,"scsi");
else if(i == MCA_MOTHERBOARD) sprintf(mca_dev->procname,"planar");
if(!mca_isadapter(i)) continue;
node = create_proc_read_entry(mca_dev->procname, 0, proc_mca,
mca_read_proc, (void *)mca_dev);
if(node == NULL) {
printk("Failed to allocate memory for MCA proc-entries!");
return;
}
}
} /* mca_do_proc_init() */
/**
* mca_set_adapter_procfn - Set the /proc callback
* @slot: slot to configure
* @procfn: callback function to call for /proc
* @dev: device information passed to the callback
*
* This sets up an information callback for /proc/mca/slot?. The
* function is called with the buffer, slot, and device pointer (or
* some equally informative context information, or nothing, if you
* prefer), and is expected to put useful information into the
* buffer. The adapter name, ID, and POS registers get printed
* before this is called though, so don't do it again.
*
* This should be called with a %NULL @procfn when a module
* unregisters, thus preventing kernel crashes and other such
* nastiness.
*/
void mca_set_adapter_procfn(int slot, MCA_ProcFn procfn, void* proc_dev)
{
struct mca_device *mca_dev = mca_find_device_by_slot(slot);
if(!mca_dev)
return;
mca_dev->procfn = procfn;
mca_dev->proc_dev = proc_dev;
}
EXPORT_SYMBOL(mca_set_adapter_procfn);
...@@ -48,7 +48,6 @@ extern int ne2_probe(struct net_device *dev); ...@@ -48,7 +48,6 @@ extern int ne2_probe(struct net_device *dev);
extern int hp100_probe(struct net_device *dev); extern int hp100_probe(struct net_device *dev);
extern int ultra_probe(struct net_device *dev); extern int ultra_probe(struct net_device *dev);
extern int ultra32_probe(struct net_device *dev); extern int ultra32_probe(struct net_device *dev);
extern int ultramca_probe(struct net_device *dev);
extern int wd_probe(struct net_device *dev); extern int wd_probe(struct net_device *dev);
extern int el2_probe(struct net_device *dev); extern int el2_probe(struct net_device *dev);
extern int ne_probe(struct net_device *dev); extern int ne_probe(struct net_device *dev);
...@@ -191,9 +190,6 @@ static struct devprobe eisa_probes[] __initdata = { ...@@ -191,9 +190,6 @@ static struct devprobe eisa_probes[] __initdata = {
static struct devprobe mca_probes[] __initdata = { static struct devprobe mca_probes[] __initdata = {
#ifdef CONFIG_ULTRAMCA
{ultramca_probe, 0},
#endif
#ifdef CONFIG_NE2_MCA #ifdef CONFIG_NE2_MCA
{ne2_probe, 0}, {ne2_probe, 0},
#endif #endif
......
...@@ -1155,8 +1155,8 @@ static void netdev_timer(unsigned long data) ...@@ -1155,8 +1155,8 @@ static void netdev_timer(unsigned long data)
unsigned int old_linkok = np->linkok; unsigned int old_linkok = np->linkok;
if (debug) if (debug)
printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8lx " printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "
"config %8.8lx.\n", dev->name, readl(ioaddr + ISR), "config %8.8x.\n", dev->name, readl(ioaddr + ISR),
readl(ioaddr + TCRRCR)); readl(ioaddr + TCRRCR));
if (np->flags == HAS_MII_XCVR) { if (np->flags == HAS_MII_XCVR) {
...@@ -1184,7 +1184,7 @@ static void tx_timeout(struct net_device *dev) ...@@ -1184,7 +1184,7 @@ static void tx_timeout(struct net_device *dev)
long ioaddr = dev->base_addr; long ioaddr = dev->base_addr;
int i; int i;
printk(KERN_WARNING "%s: Transmit timed out, status %8.8lx," printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
" resetting...\n", dev->name, readl(ioaddr + ISR)); " resetting...\n", dev->name, readl(ioaddr + ISR));
{ {
...@@ -1554,7 +1554,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) ...@@ -1554,7 +1554,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16; np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
if (debug) if (debug)
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4lx.\n", printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
dev->name, readl(ioaddr + ISR)); dev->name, readl(ioaddr + ISR));
writel(np->imrvalue, ioaddr + IMR); writel(np->imrvalue, ioaddr + IMR);
......
...@@ -390,7 +390,7 @@ int __init lance_probe(struct net_device *dev) ...@@ -390,7 +390,7 @@ int __init lance_probe(struct net_device *dev)
static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options) static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options)
{ {
struct lance_private *lp; struct lance_private *lp;
short dma_channels; /* Mark spuriously-busy DMA channels */ long dma_channels; /* Mark spuriously-busy DMA channels */
int i, reset_val, lance_version; int i, reset_val, lance_version;
const char *chipname; const char *chipname;
/* Flags for specific chips or boards. */ /* Flags for specific chips or boards. */
......
...@@ -184,11 +184,41 @@ static struct card { ...@@ -184,11 +184,41 @@ static struct card {
short addr_offset; short addr_offset;
unsigned char *vendor_id; unsigned char *vendor_id;
char *cardname; char *cardname;
unsigned char config; long config;
} cards[] = { } cards[] = {
{ NI65_ID0,NI65_ID1,0x0e,0x10,0x0,0x8,ni_vendor,"ni6510", 0x1 } , {
{ NI65_EB_ID0,NI65_EB_ID1,0x0e,0x18,0x10,0x0,ni_vendor,"ni6510 EtherBlaster", 0x2 } , .id0 = NI65_ID0,
{ NE2100_ID0,NE2100_ID1,0x0e,0x18,0x10,0x0,NULL,"generic NE2100", 0x0 } .id1 = NI65_ID1,
.id_offset = 0x0e,
.total_size = 0x10,
.cmd_offset = 0x0,
.addr_offset = 0x8,
.vendor_id = ni_vendor,
.cardname = "ni6510",
.config = 0x1,
},
{
.id0 = NI65_EB_ID0,
.id1 = NI65_EB_ID1,
.id_offset = 0x0e,
.total_size = 0x18,
.cmd_offset = 0x10,
.addr_offset = 0x0,
.vendor_id = ni_vendor,
.cardname = "ni6510 EtherBlaster",
.config = 0x2,
},
{
.id0 = NE2100_ID0,
.id1 = NE2100_ID1,
.id_offset = 0x0e,
.total_size = 0x18,
.cmd_offset = 0x10,
.addr_offset = 0x0,
.vendor_id = NULL,
.cardname = "generic NE2100",
.config = 0x0,
},
}; };
#define NUM_CARDS 3 #define NUM_CARDS 3
...@@ -415,7 +445,8 @@ static int __init ni65_probe1(struct net_device *dev,int ioaddr) ...@@ -415,7 +445,8 @@ static int __init ni65_probe1(struct net_device *dev,int ioaddr)
else { else {
if(dev->dma == 0) { if(dev->dma == 0) {
/* 'stuck test' from lance.c */ /* 'stuck test' from lance.c */
int dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | (inb(DMA2_STAT_REG) & 0xf0); long dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
(inb(DMA2_STAT_REG) & 0xf0);
for(i=1;i<5;i++) { for(i=1;i<5;i++) {
int dma = dmatab[i]; int dma = dmatab[i];
if(test_bit(dma,&dma_channels) || request_dma(dma,"ni6510")) if(test_bit(dma,&dma_channels) || request_dma(dma,"ni6510"))
......
...@@ -142,14 +142,13 @@ static void __init network_ldisc_init(void) ...@@ -142,14 +142,13 @@ static void __init network_ldisc_init(void)
static void __init special_device_init(void) static void __init special_device_init(void)
{ {
#ifdef CONFIG_NET_SB1000 #ifdef CONFIG_NET_SB1000
{ extern int sb1000_probe(struct net_device *dev);
extern int sb1000_probe(struct net_device *dev);
static struct net_device sb1000_dev = static struct net_device sb1000_dev = {
{ .name = "cm0" __PAD3,
"cm0" __PAD3, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, sb1000_probe .init = sb1000_probe,
}; };
register_netdev(&sb1000_dev); register_netdev(&sb1000_dev);
}
#endif #endif
} }
......
This diff is collapsed.
...@@ -105,6 +105,7 @@ ...@@ -105,6 +105,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h>
#include <linux/mca.h> #include <linux/mca.h>
#include <asm/dma.h> #include <asm/dma.h>
...@@ -182,131 +183,140 @@ param_setup(char *string) ...@@ -182,131 +183,140 @@ param_setup(char *string)
__setup("NCR_D700=", param_setup); __setup("NCR_D700=", param_setup);
#endif #endif
/* private stack allocated structure for passing device information from
* detect to probe */
struct NCR_700_info {
Scsi_Host_Template *tpnt;
int found;
};
/* Detect a D700 card. Note, because of the set up---the chips are /* Detect a D700 card. Note, because of the set up---the chips are
* essentially connectecd to the MCA bus independently, it is easier * essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one * to set them up as two separate host adapters, rather than one
* adapter with two channels */ * adapter with two channels */
STATIC int __init static int
D700_detect(Scsi_Host_Template *tpnt) NCR_D700_probe(struct device *dev)
{ {
int slot = 0;
int found = 0;
int differential; int differential;
int banner = 1; static int banner = 1;
struct mca_device *mca_dev = to_mca_device(dev);
if(!MCA_bus) int slot = mca_dev->slot;
return 0; struct NCR_700_info *info = to_mca_driver(dev->driver)->driver_data;
int found = 0;
#ifdef MODULE int irq, i;
if(NCR_D700) int pos3j, pos3k, pos3a, pos3b, pos4;
param_setup(NCR_D700); __u32 base_addr, offset_addr;
#endif struct Scsi_Host *host = NULL;
/* enable board interrupt */
pos4 = mca_device_read_pos(mca_dev, 4);
pos4 |= 0x4;
mca_device_write_pos(mca_dev, 4, pos4);
mca_device_write_pos(mca_dev, 6, 9);
pos3j = mca_device_read_pos(mca_dev, 3);
mca_device_write_pos(mca_dev, 6, 10);
pos3k = mca_device_read_pos(mca_dev, 3);
mca_device_write_pos(mca_dev, 6, 0);
pos3a = mca_device_read_pos(mca_dev, 3);
mca_device_write_pos(mca_dev, 6, 1);
pos3b = mca_device_read_pos(mca_dev, 3);
base_addr = ((pos3j << 8) | pos3k) & 0xfffffff0;
offset_addr = ((pos3a << 8) | pos3b) & 0xffffff70;
irq = (pos4 & 0x3) + 11;
if(irq >= 13)
irq++;
if(banner) {
printk(KERN_NOTICE "NCR D700: Driver Version " NCR_D700_VERSION "\n"
"NCR D700: Copyright (c) 2001 by James.Bottomley@HansenPartnership.com\n"
"NCR D700:\n");
banner = 0;
}
/* now do the bus related transforms */
irq = mca_device_transform_irq(mca_dev, irq);
base_addr = mca_device_transform_ioport(mca_dev, base_addr);
offset_addr = mca_device_transform_ioport(mca_dev, offset_addr);
printk(KERN_NOTICE "NCR D700: found in slot %d irq = %d I/O base = 0x%x\n", slot, irq, offset_addr);
info->tpnt->proc_name = "NCR_D700";
/*outb(BOARD_RESET, base_addr);*/
/* clear any pending interrupts */
(void)inb(base_addr + 0x08);
/* get modctl, used later for setting diff bits */
switch(differential = (inb(base_addr + 0x08) >> 6)) {
case 0x00:
/* only SIOP1 differential */
differential = 0x02;
break;
case 0x01:
/* Both SIOPs differential */
differential = 0x03;
break;
case 0x03:
/* No SIOPs differential */
differential = 0x00;
break;
default:
printk(KERN_ERR "D700: UNEXPECTED DIFFERENTIAL RESULT 0x%02x\n",
differential);
differential = 0x00;
break;
}
for(slot = 0; (slot = mca_find_adapter(NCR_D700_MCA_ID, slot)) != MCA_NOTFOUND; slot++) { /* plumb in both 700 chips */
int irq, i; for(i=0; i<2; i++) {
int pos3j, pos3k, pos3a, pos3b, pos4; __u32 region = offset_addr | (0x80 * i);
__u32 base_addr, offset_addr; struct NCR_700_Host_Parameters *hostdata =
struct Scsi_Host *host = NULL; kmalloc(sizeof(struct NCR_700_Host_Parameters),
GFP_KERNEL);
/* enable board interrupt */ if(hostdata == NULL) {
pos4 = mca_read_pos(slot, 4); printk(KERN_ERR "NCR D700: Failed to allocate host data for channel %d, detatching\n", i);
pos4 |= 0x4; continue;
mca_write_pos(slot, 4, pos4);
mca_write_pos(slot, 6, 9);
pos3j = mca_read_pos(slot, 3);
mca_write_pos(slot, 6, 10);
pos3k = mca_read_pos(slot, 3);
mca_write_pos(slot, 6, 0);
pos3a = mca_read_pos(slot, 3);
mca_write_pos(slot, 6, 1);
pos3b = mca_read_pos(slot, 3);
base_addr = ((pos3j << 8) | pos3k) & 0xfffffff0;
offset_addr = ((pos3a << 8) | pos3b) & 0xffffff70;
irq = (pos4 & 0x3) + 11;
if(irq >= 13)
irq++;
if(banner) {
printk(KERN_NOTICE "NCR D700: Driver Version " NCR_D700_VERSION "\n"
"NCR D700: Copyright (c) 2001 by James.Bottomley@HansenPartnership.com\n"
"NCR D700:\n");
banner = 0;
} }
printk(KERN_NOTICE "NCR D700: found in slot %d irq = %d I/O base = 0x%x\n", slot, irq, offset_addr); memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
if(request_region(region, 64, "NCR_D700") == NULL) {
tpnt->proc_name = "NCR_D700"; printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", region);
kfree(hostdata);
/*outb(BOARD_RESET, base_addr);*/ continue;
/* clear any pending interrupts */
(void)inb(base_addr + 0x08);
/* get modctl, used later for setting diff bits */
switch(differential = (inb(base_addr + 0x08) >> 6)) {
case 0x00:
/* only SIOP1 differential */
differential = 0x02;
break;
case 0x01:
/* Both SIOPs differential */
differential = 0x03;
break;
case 0x03:
/* No SIOPs differential */
differential = 0x00;
break;
default:
printk(KERN_ERR "D700: UNEXPECTED DIFFERENTIAL RESULT 0x%02x\n",
differential);
differential = 0x00;
break;
} }
/* plumb in both 700 chips */ /* Fill in the three required pieces of hostdata */
for(i=0; i<2; i++) { hostdata->base = region;
__u32 region = offset_addr | (0x80 * i); hostdata->differential = (((1<<i) & differential) != 0);
struct NCR_700_Host_Parameters *hostdata = hostdata->clock = NCR_D700_CLOCK_MHZ;
kmalloc(sizeof(struct NCR_700_Host_Parameters), /* and register the chip */
GFP_KERNEL); if((host = NCR_700_detect(info->tpnt, hostdata)) == NULL) {
if(hostdata == NULL) { kfree(hostdata);
printk(KERN_ERR "NCR D700: Failed to allocate host data for channel %d, detatching\n", i); release_region(host->base, 64);
continue; continue;
} }
memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); host->irq = irq;
if(request_region(region, 64, "NCR_D700") == NULL) { /* FIXME: Read this from SUS */
printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", region); host->this_id = id_array[slot * 2 + i];
kfree(hostdata); printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n",
continue; i, host->this_id);
} if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) {
printk(KERN_ERR "NCR D700, channel %d: irq problem, detatching\n", i);
/* Fill in the three required pieces of hostdata */ scsi_unregister(host);
hostdata->base = region; NCR_700_release(host);
hostdata->differential = (((1<<i) & differential) != 0); continue;
hostdata->clock = NCR_D700_CLOCK_MHZ;
/* and register the chip */
if((host = NCR_700_detect(tpnt, hostdata)) == NULL) {
kfree(hostdata);
release_region(host->base, 64);
continue;
}
host->irq = irq;
/* FIXME: Read this from SUS */
host->this_id = id_array[slot * 2 + i];
printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n",
i, host->this_id);
if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) {
printk(KERN_ERR "NCR D700, channel %d: irq problem, detatching\n", i);
scsi_unregister(host);
NCR_700_release(host);
continue;
}
found++;
mca_set_adapter_name(slot, "NCR D700 SCSI Adapter (version " NCR_D700_VERSION ")");
} }
scsi_set_device(host, dev);
found++;
}
info->found += found;
if(found) {
mca_device_set_claim(mca_dev, 1);
strncpy(dev->name, "NCR_D700", sizeof(dev->name));
} }
return found; return found? 0 : -ENODEV;
} }
...@@ -323,7 +333,38 @@ D700_release(struct Scsi_Host *host) ...@@ -323,7 +333,38 @@ D700_release(struct Scsi_Host *host)
return 1; return 1;
} }
static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
struct mca_driver NCR_D700_driver = {
.id_table = NCR_D700_id_table,
.driver = {
.name = "NCR_D700",
.bus = &mca_bus_type,
.probe = NCR_D700_probe,
},
};
STATIC int __init
D700_detect(Scsi_Host_Template *tpnt)
{
struct NCR_700_info info;
if(!MCA_bus)
return 0;
#ifdef MODULE
if(NCR_D700)
param_setup(NCR_D700);
#endif
info.tpnt = tpnt;
info.found = 0;
NCR_D700_driver.driver_data = &info;
mca_register_driver(&NCR_D700_driver);
return info.found;
}
static Scsi_Host_Template driver_template = NCR_D700_SCSI; static Scsi_Host_Template driver_template = NCR_D700_SCSI;
#include "scsi_module.c" #include "scsi_module.c"
......
...@@ -479,12 +479,6 @@ struct Scsi_Host ...@@ -479,12 +479,6 @@ struct Scsi_Host
*/ */
unsigned int max_host_blocked; unsigned int max_host_blocked;
/*
* For SCSI hosts which are PCI devices, set pci_dev so that
* we can do BIOS EDD 3.0 mappings
*/
struct pci_dev *pci_dev;
/* /*
* Support for driverfs filesystem * Support for driverfs filesystem
*/ */
...@@ -522,11 +516,21 @@ static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) ...@@ -522,11 +516,21 @@ static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
shost->host_lock = lock; shost->host_lock = lock;
} }
static inline void scsi_set_device(struct Scsi_Host *shost,
struct device *dev)
{
shost->host_gendev = dev;
}
static inline struct device *scsi_get_device(struct Scsi_Host *shost)
{
return shost->host_gendev;
}
static inline void scsi_set_pci_device(struct Scsi_Host *shost, static inline void scsi_set_pci_device(struct Scsi_Host *shost,
struct pci_dev *pdev) struct pci_dev *pdev)
{ {
shost->pci_dev = pdev; scsi_set_device(shost, &pdev->dev);
shost->host_gendev = &pdev->dev;
} }
......
...@@ -764,7 +764,7 @@ static inline int should_transform(ide_drive_t *drive, Scsi_Cmnd *cmd) ...@@ -764,7 +764,7 @@ static inline int should_transform(ide_drive_t *drive, Scsi_Cmnd *cmd)
if (disk) { if (disk) {
struct Scsi_Device_Template **p = disk->private_data; struct Scsi_Device_Template **p = disk->private_data;
if (strcmp((*p)->tag, "sg") == 0) if (strcmp((*p)->scsi_driverfs_driver.name, "sg") == 0)
return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
} }
return test_bit(IDESCSI_TRANSFORM, &scsi->transform); return test_bit(IDESCSI_TRANSFORM, &scsi->transform);
......
...@@ -46,6 +46,7 @@ const char * osst_version = "0.99.0p3"; ...@@ -46,6 +46,7 @@ const char * osst_version = "0.99.0p3";
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/blk.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -59,8 +60,6 @@ const char * osst_version = "0.99.0p3"; ...@@ -59,8 +60,6 @@ const char * osst_version = "0.99.0p3";
in the drivers are more widely classified, this may be changed to KERN_DEBUG. */ in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
#define OSST_DEB_MSG KERN_NOTICE #define OSST_DEB_MSG KERN_NOTICE
#define MAJOR_NR OSST_MAJOR
#include <linux/blk.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -5586,14 +5585,14 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5586,14 +5585,14 @@ static int osst_attach(Scsi_Device * SDp)
tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev; tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
tpnt->driverfs_dev_r[mode].bus = SDp->sdev_driverfs_dev.bus; tpnt->driverfs_dev_r[mode].bus = SDp->sdev_driverfs_dev.bus;
tpnt->driverfs_dev_r[mode].driver_data = tpnt->driverfs_dev_r[mode].driver_data =
(void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5)); (void *)(long)__mkdev(OSST_MAJOR, dev_num + (mode << 5));
device_register(&tpnt->driverfs_dev_r[mode]); device_register(&tpnt->driverfs_dev_r[mode]);
device_create_file(&tpnt->driverfs_dev_r[mode], device_create_file(&tpnt->driverfs_dev_r[mode],
&dev_attr_type); &dev_attr_type);
device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
tpnt->de_r[mode] = tpnt->de_r[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, dev_num + (mode << 5), OSST_MAJOR, dev_num + (mode << 5),
S_IFCHR | S_IRUGO | S_IWUGO, S_IFCHR | S_IRUGO | S_IWUGO,
&osst_fops, NULL); &osst_fops, NULL);
/* No-rewind entry */ /* No-rewind entry */
...@@ -5605,7 +5604,7 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5605,7 +5604,7 @@ static int osst_attach(Scsi_Device * SDp)
tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev; tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
tpnt->driverfs_dev_n[mode].bus = SDp->sdev_driverfs_dev.bus; tpnt->driverfs_dev_n[mode].bus = SDp->sdev_driverfs_dev.bus;
tpnt->driverfs_dev_n[mode].driver_data = tpnt->driverfs_dev_n[mode].driver_data =
(void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5) + 128); (void *)(long)__mkdev(OSST_MAJOR, dev_num + (mode << 5) + 128);
device_register(&tpnt->driverfs_dev_n[mode]); device_register(&tpnt->driverfs_dev_n[mode]);
device_create_file(&tpnt->driverfs_dev_n[mode], device_create_file(&tpnt->driverfs_dev_n[mode],
&dev_attr_type); &dev_attr_type);
...@@ -5613,7 +5612,7 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5613,7 +5612,7 @@ static int osst_attach(Scsi_Device * SDp)
&dev_attr_kdev); &dev_attr_kdev);
tpnt->de_n[mode] = tpnt->de_n[mode] =
devfs_register (SDp->de, name, DEVFS_FL_DEFAULT, devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
MAJOR_NR, dev_num + (mode << 5) + 128, OSST_MAJOR, dev_num + (mode << 5) + 128,
S_IFCHR | S_IRUGO | S_IWUGO, S_IFCHR | S_IRUGO | S_IWUGO,
&osst_fops, NULL); &osst_fops, NULL);
} }
...@@ -5686,8 +5685,9 @@ static int __init init_osst(void) ...@@ -5686,8 +5685,9 @@ static int __init init_osst(void)
printk(OSST_DEB_MSG "osst :D: %d s/g segments, write threshold %d bytes.\n", printk(OSST_DEB_MSG "osst :D: %d s/g segments, write threshold %d bytes.\n",
max_sg_segs, osst_write_threshold); max_sg_segs, osst_write_threshold);
#endif #endif
if ((register_chrdev(MAJOR_NR,"osst",&osst_fops) < 0) || scsi_register_device(&osst_template)) { if ((register_chrdev(OSST_MAJOR, "osst", &osst_fops) < 0) ||
printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n",MAJOR_NR); scsi_register_device(&osst_template)) {
printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
return 1; return 1;
} }
...@@ -5700,7 +5700,7 @@ static void __exit exit_osst (void) ...@@ -5700,7 +5700,7 @@ static void __exit exit_osst (void)
OS_Scsi_Tape * STp; OS_Scsi_Tape * STp;
scsi_unregister_device(&osst_template); scsi_unregister_device(&osst_template);
unregister_chrdev(MAJOR_NR, "osst"); unregister_chrdev(OSST_MAJOR, "osst");
if (os_scsi_tapes) { if (os_scsi_tapes) {
for (i=0; i < osst_max_dev; ++i) { for (i=0; i < osst_max_dev; ++i) {
......
...@@ -55,7 +55,6 @@ ...@@ -55,7 +55,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/mempool.h>
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
...@@ -74,24 +73,6 @@ ...@@ -74,24 +73,6 @@
#include <linux/kmod.h> #include <linux/kmod.h>
#endif #endif
#define SG_MEMPOOL_NR 5
#define SG_MEMPOOL_SIZE 32
struct scsi_host_sg_pool {
int size;
char *name;
kmem_cache_t *slab;
mempool_t *pool;
};
#define SP(x) { x, "sgpool-" #x }
struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR] = {
SP(8), SP(16), SP(32), SP(64), SP(MAX_PHYS_SEGMENTS)
};
#undef SP
/*
static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/scsi.c,v 1.38 1997/01/19 23:07:18 davem Exp $";
*/
/* /*
* Definitions and constants. * Definitions and constants.
...@@ -668,10 +649,7 @@ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason) ...@@ -668,10 +649,7 @@ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
*/ */
void scsi_release_command(Scsi_Cmnd * SCpnt) void scsi_release_command(Scsi_Cmnd * SCpnt)
{ {
request_queue_t *q; request_queue_t *q = &SCpnt->device->request_queue;
Scsi_Device * SDpnt;
SDpnt = SCpnt->device;
__scsi_release_command(SCpnt); __scsi_release_command(SCpnt);
...@@ -681,7 +659,6 @@ void scsi_release_command(Scsi_Cmnd * SCpnt) ...@@ -681,7 +659,6 @@ void scsi_release_command(Scsi_Cmnd * SCpnt)
* This won't block - if the device cannot take any more, life * This won't block - if the device cannot take any more, life
* will go on. * will go on.
*/ */
q = &SDpnt->request_queue;
scsi_queue_next_request(q, NULL); scsi_queue_next_request(q, NULL);
} }
...@@ -2082,81 +2059,12 @@ static int __init setup_scsi_default_dev_flags(char *str) ...@@ -2082,81 +2059,12 @@ static int __init setup_scsi_default_dev_flags(char *str)
__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags); __setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags);
#endif #endif
static void *scsi_pool_alloc(int gfp_mask, void *data)
{
return kmem_cache_alloc(data, gfp_mask);
}
static void scsi_pool_free(void *ptr, void *data)
{
kmem_cache_free(data, ptr);
}
struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask)
{
struct scsi_host_sg_pool *sgp;
struct scatterlist *sgl;
int pf_flags;
BUG_ON(!SCpnt->use_sg);
switch (SCpnt->use_sg) {
case 1 ... 8 : SCpnt->sglist_len = 0; break;
case 9 ... 16 : SCpnt->sglist_len = 1; break;
case 17 ... 32 : SCpnt->sglist_len = 2; break;
case 33 ... 64 : SCpnt->sglist_len = 3; break;
case 65 ... MAX_PHYS_SEGMENTS : SCpnt->sglist_len = 4; break;
default: return NULL;
}
sgp = scsi_sg_pools + SCpnt->sglist_len;
pf_flags = current->flags;
current->flags |= PF_NOWARN;
sgl = mempool_alloc(sgp->pool, gfp_mask);
current->flags = pf_flags;
if (sgl) {
memset(sgl, 0, sgp->size);
return sgl;
}
return sgl;
}
void scsi_free_sgtable(struct scatterlist *sgl, int index)
{
struct scsi_host_sg_pool *sgp = scsi_sg_pools + index;
if (unlikely(index > SG_MEMPOOL_NR)) {
printk("scsi_free_sgtable: mempool %d\n", index);
BUG();
}
mempool_free(sgl, sgp->pool);
}
static int __init init_scsi(void) static int __init init_scsi(void)
{ {
int i;
printk(KERN_INFO "SCSI subsystem driver " REVISION "\n"); printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
/* scsi_init_queue();
* setup sg memory pools
*/
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
int size = sgp->size * sizeof(struct scatterlist);
sgp->slab = kmem_cache_create(sgp->name, size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!sgp->slab)
printk(KERN_ERR "SCSI: can't init sg slab %s\n", sgp->name);
sgp->pool = mempool_create(SG_MEMPOOL_SIZE, scsi_pool_alloc, scsi_pool_free, sgp->slab);
if (!sgp->pool)
printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name);
}
scsi_init_procfs(); scsi_init_procfs();
devfs_mk_dir(NULL, "scsi", NULL); devfs_mk_dir(NULL, "scsi", NULL);
scsi_host_init(); scsi_host_init();
...@@ -2168,20 +2076,11 @@ static int __init init_scsi(void) ...@@ -2168,20 +2076,11 @@ static int __init init_scsi(void)
static void __exit exit_scsi(void) static void __exit exit_scsi(void)
{ {
int i;
scsi_sysfs_unregister(); scsi_sysfs_unregister();
scsi_dev_info_list_delete(); scsi_dev_info_list_delete();
devfs_remove("scsi"); devfs_remove("scsi");
scsi_exit_procfs(); scsi_exit_procfs();
scsi_exit_queue();
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
mempool_destroy(sgp->pool);
kmem_cache_destroy(sgp->slab);
sgp->pool = NULL;
sgp->slab = NULL;
}
} }
subsys_initcall(init_scsi); subsys_initcall(init_scsi);
......
...@@ -420,12 +420,6 @@ extern int scsi_partsize(unsigned char *buf, unsigned long capacity, ...@@ -420,12 +420,6 @@ extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds, unsigned int *cyls, unsigned int *hds,
unsigned int *secs); unsigned int *secs);
/*
* sg list allocations
*/
struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask);
void scsi_free_sgtable(struct scatterlist *sgl, int index);
/* /*
* Prototypes for functions in scsi_lib.c * Prototypes for functions in scsi_lib.c
*/ */
...@@ -437,13 +431,13 @@ extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, ...@@ -437,13 +431,13 @@ extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
extern void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt); extern void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt);
extern int scsi_prep_fn(struct request_queue *q, struct request *req); extern int scsi_prep_fn(struct request_queue *q, struct request *req);
extern void scsi_request_fn(request_queue_t * q); extern void scsi_request_fn(request_queue_t * q);
extern int scsi_starvation_completion(Scsi_Device * SDpnt); extern int scsi_init_queue(void);
extern void scsi_exit_queue(void);
/* /*
* Prototypes for functions in scsi.c * Prototypes for functions in scsi.c
*/ */
extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt); extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
extern void scsi_bottom_half_handler(void);
extern void scsi_release_commandblocks(Scsi_Device * SDpnt); extern void scsi_release_commandblocks(Scsi_Device * SDpnt);
extern void scsi_build_commandblocks(Scsi_Device * SDpnt); extern void scsi_build_commandblocks(Scsi_Device * SDpnt);
extern void scsi_adjust_queue_depth(Scsi_Device *, int, int); extern void scsi_adjust_queue_depth(Scsi_Device *, int, int);
...@@ -462,7 +456,6 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd, ...@@ -462,7 +456,6 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
void *buffer, unsigned bufflen, void *buffer, unsigned bufflen,
void (*done) (struct scsi_cmnd *), void (*done) (struct scsi_cmnd *),
int timeout, int retries); int timeout, int retries);
extern int scsi_dev_init(void);
extern int scsi_mlqueue_insert(struct scsi_cmnd *, int); extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
extern int scsi_attach_device(struct scsi_device *); extern int scsi_attach_device(struct scsi_device *);
extern void scsi_detach_device(struct scsi_device *); extern void scsi_detach_device(struct scsi_device *);
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#include "scsi_debug.h" #include "scsi_debug.h"
static const char * scsi_debug_version_str = "Version: 1.65 (20021119)"; static const char * scsi_debug_version_str = "Version: 1.66 (20021205)";
#ifndef SCSI_CMD_READ_16 #ifndef SCSI_CMD_READ_16
#define SCSI_CMD_READ_16 0x88 #define SCSI_CMD_READ_16 0x88
...@@ -397,7 +397,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -397,7 +397,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
if ((errsts = check_reset(SCpnt, devip))) if ((errsts = check_reset(SCpnt, devip)))
break; break;
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14);
errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); errsts = (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
break; break;
} }
return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay); return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay);
...@@ -417,7 +417,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip) ...@@ -417,7 +417,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
if (devip->reset) { if (devip->reset) {
devip->reset = 0; devip->reset = 0;
mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14); mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
return 0; return 0;
} }
...@@ -478,7 +478,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -478,7 +478,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
arr[0] = pq_pdt; arr[0] = pq_pdt;
if (0x2 & cmd[1]) { /* CMDDT bit set */ if (0x2 & cmd[1]) { /* CMDDT bit set */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} else if (0x1 & cmd[1]) { /* EVPD bit set */ } else if (0x1 & cmd[1]) { /* EVPD bit set */
int dev_id_num, len; int dev_id_num, len;
char dev_id_str[6]; char dev_id_str[6];
...@@ -503,7 +503,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -503,7 +503,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
} else { } else {
/* Illegal request, invalid field in cdb */ /* Illegal request, invalid field in cdb */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
memcpy(buff, arr, min_len); memcpy(buff, arr, min_len);
return 0; return 0;
...@@ -616,7 +616,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -616,7 +616,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
if (0x3 == pcontrol) { /* Saving values not supported */ if (0x3 == pcontrol) { /* Saving values not supported */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
dev_spec = DEV_READONLY(target) ? 0x80 : 0x0; dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
if (msense_6) { if (msense_6) {
...@@ -659,7 +659,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -659,7 +659,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
break; break;
default: default:
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
if (msense_6) if (msense_6)
arr[0] = offset - 1; arr[0] = offset - 1;
...@@ -683,14 +683,14 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -683,14 +683,14 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
(block >= OPT_MEDIUM_ERR_ADDR) && (block >= OPT_MEDIUM_ERR_ADDR) &&
(block < (OPT_MEDIUM_ERR_ADDR + num))) { (block < (OPT_MEDIUM_ERR_ADDR + num))) {
mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14); mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14);
/* claim unrecoverable read error */ /* claim unrecoverable read error */
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
read_lock_irqsave(&atomic_rw, iflags); read_lock_irqsave(&atomic_rw, iflags);
sgcount = 0; sgcount = 0;
...@@ -732,7 +732,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -732,7 +732,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
write_lock_irqsave(&atomic_rw, iflags); write_lock_irqsave(&atomic_rw, iflags);
...@@ -773,7 +773,7 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff, ...@@ -773,7 +773,7 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
if ((alloc_len < 16) || (select_report > 2)) { if ((alloc_len < 16) || (select_report > 2)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
} }
if (bufflen > 3) { if (bufflen > 3) {
lun_cnt = min((int)(bufflen / sizeof(ScsiLun)), lun_cnt = min((int)(bufflen / sizeof(ScsiLun)),
......
...@@ -393,12 +393,13 @@ int scsi_ioctl_send_command(Scsi_Device * dev, Scsi_Ioctl_Command * sic) ...@@ -393,12 +393,13 @@ int scsi_ioctl_send_command(Scsi_Device * dev, Scsi_Ioctl_Command * sic)
* any copy_to_user() error on failure there * any copy_to_user() error on failure there
*/ */
static int static int
scsi_ioctl_get_pci(Scsi_Device * dev, void *arg) scsi_ioctl_get_pci(Scsi_Device * sdev, void *arg)
{ {
struct device *dev = scsi_get_device(sdev->host);
if (!dev->host->pci_dev) return -ENXIO; if (!dev) return -ENXIO;
return copy_to_user(arg, dev->host->pci_dev->slot_name, return copy_to_user(arg, dev->bus_id,
sizeof(dev->host->pci_dev->slot_name)); sizeof(dev->bus_id));
} }
......
...@@ -11,12 +11,30 @@ ...@@ -11,12 +11,30 @@
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mempool.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#define SG_MEMPOOL_NR 5
#define SG_MEMPOOL_SIZE 32
struct scsi_host_sg_pool {
size_t size;
char *name;
kmem_cache_t *slab;
mempool_t *pool;
};
#define SP(x) { x, "sgpool-" #x }
struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR] = {
SP(8), SP(16), SP(32), SP(64), SP(MAX_PHYS_SEGMENTS)
};
#undef SP
/* /*
* Function: scsi_insert_special_cmd() * Function: scsi_insert_special_cmd()
* *
...@@ -348,6 +366,51 @@ static Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, ...@@ -348,6 +366,51 @@ static Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt,
return NULL; return NULL;
} }
static struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask)
{
struct scsi_host_sg_pool *sgp;
struct scatterlist *sgl;
BUG_ON(!SCpnt->use_sg);
switch (SCpnt->use_sg) {
case 1 ... 8:
SCpnt->sglist_len = 0;
break;
case 9 ... 16:
SCpnt->sglist_len = 1;
break;
case 17 ... 32:
SCpnt->sglist_len = 2;
break;
case 33 ... 64:
SCpnt->sglist_len = 3;
break;
case 65 ... MAX_PHYS_SEGMENTS:
SCpnt->sglist_len = 4;
break;
default:
return NULL;
}
sgp = scsi_sg_pools + SCpnt->sglist_len;
sgl = mempool_alloc(sgp->pool, gfp_mask);
if (sgl)
memset(sgl, 0, sgp->size);
return sgl;
}
static void scsi_free_sgtable(struct scatterlist *sgl, int index)
{
struct scsi_host_sg_pool *sgp;
BUG_ON(index > SG_MEMPOOL_NR);
sgp = scsi_sg_pools + index;
mempool_free(sgl, sgp->pool);
}
/* /*
* Function: scsi_release_buffers() * Function: scsi_release_buffers()
* *
...@@ -374,15 +437,10 @@ static void scsi_release_buffers(Scsi_Cmnd * SCpnt) ...@@ -374,15 +437,10 @@ static void scsi_release_buffers(Scsi_Cmnd * SCpnt)
/* /*
* Free up any indirection buffers we allocated for DMA purposes. * Free up any indirection buffers we allocated for DMA purposes.
*/ */
if (SCpnt->use_sg) { if (SCpnt->use_sg)
struct scatterlist *sgpnt;
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len); scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len);
} else { else if (SCpnt->request_buffer != req->buffer)
if (SCpnt->request_buffer != req->buffer) kfree(SCpnt->request_buffer);
kfree(SCpnt->request_buffer);
}
/* /*
* Zero these out. They now point to freed memory, and it is * Zero these out. They now point to freed memory, and it is
...@@ -462,22 +520,16 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, ...@@ -462,22 +520,16 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
* For the case of a READ, we need to copy the data out of the * For the case of a READ, we need to copy the data out of the
* bounce buffer and into the real buffer. * bounce buffer and into the real buffer.
*/ */
if (SCpnt->use_sg) { if (SCpnt->use_sg)
struct scatterlist *sgpnt;
sgpnt = (struct scatterlist *) SCpnt->buffer;
scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len); scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len);
} else { else if (SCpnt->buffer != req->buffer) {
if (SCpnt->buffer != req->buffer) { if (rq_data_dir(req) == READ) {
if (rq_data_dir(req) == READ) { unsigned long flags;
unsigned long flags; char *to = bio_kmap_irq(req->bio, &flags);
char *to = bio_kmap_irq(req->bio, &flags); memcpy(to, SCpnt->buffer, SCpnt->bufflen);
bio_kunmap_irq(to, &flags);
memcpy(to, SCpnt->buffer, SCpnt->bufflen);
bio_kunmap_irq(to, &flags);
}
kfree(SCpnt->buffer);
} }
kfree(SCpnt->buffer);
} }
if (blk_pc_request(req)) { if (blk_pc_request(req)) {
...@@ -1093,3 +1145,41 @@ void scsi_register_blocked_host(struct Scsi_Host * SHpnt) ...@@ -1093,3 +1145,41 @@ void scsi_register_blocked_host(struct Scsi_Host * SHpnt)
void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt) void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt)
{ {
} }
int __init scsi_init_queue(void)
{
int i;
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
int size = sgp->size * sizeof(struct scatterlist);
sgp->slab = kmem_cache_create(sgp->name, size, 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!sgp->slab) {
printk(KERN_ERR "SCSI: can't init sg slab %s\n",
sgp->name);
}
sgp->pool = mempool_create(SG_MEMPOOL_SIZE,
mempool_alloc_slab, mempool_free_slab,
sgp->slab);
if (!sgp->pool) {
printk(KERN_ERR "SCSI: can't init sg mempool %s\n",
sgp->name);
}
}
return 0;
}
void __exit scsi_exit_queue(void)
{
int i;
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
mempool_destroy(sgp->pool);
kmem_cache_destroy(sgp->slab);
}
}
...@@ -373,11 +373,12 @@ static void scsi_initialize_merge_fn(struct scsi_device *sd) ...@@ -373,11 +373,12 @@ static void scsi_initialize_merge_fn(struct scsi_device *sd)
{ {
request_queue_t *q = &sd->request_queue; request_queue_t *q = &sd->request_queue;
struct Scsi_Host *sh = sd->host; struct Scsi_Host *sh = sd->host;
struct device *dev = scsi_get_device(sh);
u64 bounce_limit; u64 bounce_limit;
if (sh->highmem_io) { if (sh->highmem_io) {
if (sh->pci_dev && PCI_DMA_BUS_IS_PHYS) { if (dev && dev->dma_mask && PCI_DMA_BUS_IS_PHYS) {
bounce_limit = sh->pci_dev->dma_mask; bounce_limit = *dev->dma_mask;
} else { } else {
/* /*
* Platforms with virtual-DMA translation * Platforms with virtual-DMA translation
......
...@@ -132,39 +132,115 @@ void scsi_upper_driver_unregister(struct Scsi_Device_Template *sdev_tp) ...@@ -132,39 +132,115 @@ void scsi_upper_driver_unregister(struct Scsi_Device_Template *sdev_tp)
} }
/** /*
* scsi_device_type_read - copy out the SCSI type * show_function: macro to create an attr function that can be used to
* @dev: device to check * show a non-bit field.
* @page: copy data into this area */
* @count: number of bytes to copy #define show_function(field, format_string) \
* @off: start at this offset in page static ssize_t \
* show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
* Return: { \
* number of bytes written into page. struct scsi_device *sdev; \
**/ if (off) \
static ssize_t scsi_device_type_read(struct device *dev, char *page, return 0; \
size_t count, loff_t off) sdev = to_scsi_device(dev); \
{ return snprintf (buf, count, format_string, sdev->field); \
struct scsi_device *sdev = to_scsi_device(dev); } \
const char *type;
if (off) /*
return 0; * sdev_rd_attr: macro to create a function and attribute variable for a
* read only field.
*/
#define sdev_rd_attr(field, format_string) \
show_function(field, format_string) \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL)
/*
* sdev_rd_attr: create a function and attribute variable for a
* read/write field.
*/
#define sdev_rw_attr(field, format_string) \
show_function(field, format_string) \
\
static ssize_t \
store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\
{ \
struct scsi_device *sdev; \
\
if (off) \
return 0; \
sdev = to_scsi_device(dev); \
return snscanf (buf, count, format_string, &sdev->field); \
} \
static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, store_##field)
if ((sdev->type > MAX_SCSI_DEVICE_CODE) || /*
(scsi_device_types[(int)sdev->type] == NULL)) * sdev_rd_attr: create a function and attribute variable for a
type = "Unknown"; * read/write bit field.
else */
type = scsi_device_types[(int)sdev->type]; #define sdev_rw_attr_bit(field) \
show_function(field, "%d\n") \
\
static ssize_t \
store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\
{ \
int ret; \
struct scsi_device *sdev; \
\
if (off) \
return 0; \
ret = scsi_sdev_check_buf_bit(buf); \
if (ret >= 0) { \
sdev = to_scsi_device(dev); \
sdev->field = ret; \
ret = count; \
} \
return ret; \
} \
static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, store_##field)
return snprintf(page, count, "%s\n", type); /*
* scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
* else return -EINVAL.
*/
static int scsi_sdev_check_buf_bit(const char *buf)
{
if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
if (buf[0] == '1')
return 1;
else if (buf[0] == '0')
return 0;
else
return -EINVAL;
} else
return -EINVAL;
} }
/* /*
* Create dev_attr_type. This is different from the dev_attr_type in scsi * Create the actual show/store functions and data structures.
* upper level drivers.
*/ */
static DEVICE_ATTR(type,S_IRUGO,scsi_device_type_read,NULL); sdev_rd_attr (device_blocked, "%d\n");
sdev_rd_attr (current_queue_depth, "%d\n");
sdev_rd_attr (new_queue_depth, "%d\n");
sdev_rd_attr (type, "%d\n");
sdev_rd_attr (access_count, "%d\n");
sdev_rd_attr (vendor, "%.8s\n");
sdev_rd_attr (model, "%.16s\n");
sdev_rd_attr (rev, "%.4s\n");
sdev_rw_attr_bit (online);
static struct device_attribute * const sdev_attrs[] = {
&dev_attr_device_blocked,
&dev_attr_current_queue_depth,
&dev_attr_new_queue_depth,
&dev_attr_type,
&dev_attr_access_count,
&dev_attr_vendor,
&dev_attr_model,
&dev_attr_rev,
&dev_attr_online,
};
/** /**
* scsi_device_register - register a scsi device with the scsi bus * scsi_device_register - register a scsi device with the scsi bus
...@@ -175,7 +251,7 @@ static DEVICE_ATTR(type,S_IRUGO,scsi_device_type_read,NULL); ...@@ -175,7 +251,7 @@ static DEVICE_ATTR(type,S_IRUGO,scsi_device_type_read,NULL);
**/ **/
int scsi_device_register(struct scsi_device *sdev) int scsi_device_register(struct scsi_device *sdev)
{ {
int error = 0; int error = 0, i;
sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d", sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
...@@ -186,9 +262,12 @@ int scsi_device_register(struct scsi_device *sdev) ...@@ -186,9 +262,12 @@ int scsi_device_register(struct scsi_device *sdev)
if (error) if (error)
return error; return error;
error = device_create_file(&sdev->sdev_driverfs_dev, &dev_attr_type); for (i = 0; !error && i < ARRAY_SIZE(sdev_attrs); i++)
error = device_create_file(&sdev->sdev_driverfs_dev,
sdev_attrs[i]);
if (error) if (error)
device_unregister(&sdev->sdev_driverfs_dev); scsi_device_unregister(sdev);
return error; return error;
} }
...@@ -199,6 +278,9 @@ int scsi_device_register(struct scsi_device *sdev) ...@@ -199,6 +278,9 @@ int scsi_device_register(struct scsi_device *sdev)
**/ **/
void scsi_device_unregister(struct scsi_device *sdev) void scsi_device_unregister(struct scsi_device *sdev)
{ {
device_remove_file(&sdev->sdev_driverfs_dev, &dev_attr_type); int i;
for (i = 0; i < ARRAY_SIZE(sdev_attrs); i++)
device_remove_file(&sdev->sdev_driverfs_dev, sdev_attrs[i]);
device_unregister(&sdev->sdev_driverfs_dev); device_unregister(&sdev->sdev_driverfs_dev);
} }
...@@ -33,7 +33,7 @@ static char *verstr = "20021015"; ...@@ -33,7 +33,7 @@ static char *verstr = "20021015";
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp_lock.h> #include <linux/blk.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -54,9 +54,6 @@ static char *verstr = "20021015"; ...@@ -54,9 +54,6 @@ static char *verstr = "20021015";
#define DEBC(a) #define DEBC(a)
#endif #endif
#define MAJOR_NR SCSI_TAPE_MAJOR
#define DEVICE_NR(device) (minor(device) & 0x7f)
#include <linux/blk.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -3768,13 +3765,14 @@ static int st_attach(Scsi_Device * SDp) ...@@ -3768,13 +3765,14 @@ static int st_attach(Scsi_Device * SDp)
tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma; tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
bounce_limit = BLK_BOUNCE_HIGH; /* Borrowed from scsi_merge.c */ bounce_limit = BLK_BOUNCE_HIGH; /* Borrowed from scsi_merge.c */
if (SDp->host->highmem_io) { if (SDp->host->highmem_io) {
struct device *dev = scsi_get_device(SDp->host);
if (!PCI_DMA_BUS_IS_PHYS) if (!PCI_DMA_BUS_IS_PHYS)
/* Platforms with virtual-DMA translation /* Platforms with virtual-DMA translation
* hardware have no practical limit. * hardware have no practical limit.
*/ */
bounce_limit = BLK_BOUNCE_ANY; bounce_limit = BLK_BOUNCE_ANY;
else if (SDp->host->pci_dev) else if (dev && dev->dma_mask)
bounce_limit = SDp->host->pci_dev->dma_mask; bounce_limit = *dev->dma_mask;
} else if (SDp->host->unchecked_isa_dma) } else if (SDp->host->unchecked_isa_dma)
bounce_limit = BLK_BOUNCE_ISA; bounce_limit = BLK_BOUNCE_ISA;
bounce_limit >>= PAGE_SHIFT; bounce_limit >>= PAGE_SHIFT;
......
/* -*- mode: c; c-basic-offset: 8 -*- */
/* Platform specific MCA defines */
#ifndef _ASM_MCA_H
#define _ASM_MCA_H
/* Maximal number of MCA slots - actually, some machines have less, but
* they all have sufficient number of POS registers to cover 8.
*/
#define MCA_MAX_SLOT_NR 8
/* Most machines have only one MCA bus. The only multiple bus machines
* I know have at most two */
#define MAX_MCA_BUSSES 2
#define MCA_PRIMARY_BUS 0
#define MCA_SECONDARY_BUS 1
/* Dummy slot numbers on primary MCA for integrated functions */
#define MCA_INTEGSCSI (MCA_MAX_SLOT_NR)
#define MCA_INTEGVIDEO (MCA_MAX_SLOT_NR+1)
#define MCA_MOTHERBOARD (MCA_MAX_SLOT_NR+2)
/* Dummy POS values for integrated functions */
#define MCA_DUMMY_POS_START 0x10000
#define MCA_INTEGSCSI_POS (MCA_DUMMY_POS_START+1)
#define MCA_INTEGVIDEO_POS (MCA_DUMMY_POS_START+2)
#define MCA_MOTHERBOARD_POS (MCA_DUMMY_POS_START+3)
/* MCA registers */
#define MCA_MOTHERBOARD_SETUP_REG 0x94
#define MCA_ADAPTER_SETUP_REG 0x96
#define MCA_POS_REG(n) (0x100+(n))
#define MCA_ENABLED 0x01 /* POS 2, set if adapter enabled */
/* Max number of adapters, including both slots and various integrated
* things.
*/
#define MCA_NUMADAPTERS (MCA_MAX_SLOT_NR+3)
/* lock to protect access to the MCA registers */
extern spinlock_t mca_lock;
#endif
...@@ -214,7 +214,7 @@ struct hdlcdrv_state { ...@@ -214,7 +214,7 @@ struct hdlcdrv_state {
struct hdlcdrv_hdlctx { struct hdlcdrv_hdlctx {
struct hdlcdrv_hdlcbuffer hbuf; struct hdlcdrv_hdlcbuffer hbuf;
int in_hdlc_tx; long in_hdlc_tx;
/* /*
* 0 = send flags * 0 = send flags
* 1 = send txtail (flags) * 1 = send txtail (flags)
......
/* -*- mode: c; c-basic-offset: 8 -*- */
/* This is the function prototypes for the old legacy MCA interface
*
* Please move your driver to the new sysfs based one instead */
#ifndef _LINUX_MCA_LEGACY_H
#define _LINUX_MCA_LEGACY_H
/* MCA_NOTFOUND is an error condition. The other two indicate
* motherboard POS registers contain the adapter. They might be
* returned by the mca_find_adapter() function, and can be used as
* arguments to mca_read_stored_pos(). I'm not going to allow direct
* access to the motherboard registers until we run across an adapter
* that requires it. We don't know enough about them to know if it's
* safe.
*
* See Documentation/mca.txt or one of the existing drivers for
* more information.
*/
#define MCA_NOTFOUND (-1)
/* Returns the slot of the first enabled adapter matching id. User can
* specify a starting slot beyond zero, to deal with detecting multiple
* devices. Returns MCA_NOTFOUND if id not found. Also checks the
* integrated adapters.
*/
extern int mca_find_adapter(int id, int start);
extern int mca_find_unused_adapter(int id, int start);
/* adapter state info - returns 0 if no */
extern int mca_isadapter(int slot);
extern int mca_isenabled(int slot);
extern int mca_is_adapter_used(int slot);
extern int mca_mark_as_used(int slot);
extern void mca_mark_as_unused(int slot);
/* gets a byte out of POS register (stored in memory) */
extern unsigned char mca_read_stored_pos(int slot, int reg);
/* This can be expanded later. Right now, it gives us a way of
* getting meaningful information into the MCA_info structure,
* so we can have a more interesting /proc/mca.
*/
extern void mca_set_adapter_name(int slot, char* name);
extern char* mca_get_adapter_name(int slot);
/* These routines actually mess with the hardware POS registers. They
* temporarily disable the device (and interrupts), so make sure you know
* what you're doing if you use them. Furthermore, writing to a POS may
* result in two devices trying to share a resource, which in turn can
* result in multiple devices sharing memory spaces, IRQs, or even trashing
* hardware. YOU HAVE BEEN WARNED.
*
* You can only access slots with this. Motherboard registers are off
* limits.
*/
/* read a byte from the specified POS register. */
extern unsigned char mca_read_pos(int slot, int reg);
/* write a byte to the specified POS register. */
extern void mca_write_pos(int slot, int reg, unsigned char byte);
#endif
...@@ -6,6 +6,14 @@ ...@@ -6,6 +6,14 @@
#ifndef _LINUX_MCA_H #ifndef _LINUX_MCA_H
#define _LINUX_MCA_H #define _LINUX_MCA_H
/* FIXME: This shouldn't happen, but we need everything that previously
* included mca.h to compile. Take it out later when the MCA #includes
* are sorted out */
#include <linux/device.h>
/* get the platform specific defines */
#include <asm/mca.h>
/* The detection of MCA bus is done in the real mode (using BIOS). /* The detection of MCA bus is done in the real mode (using BIOS).
* The information is exported to the protected code, where this * The information is exported to the protected code, where this
* variable is set to one in case MCA bus was detected. * variable is set to one in case MCA bus was detected.
...@@ -14,58 +22,6 @@ ...@@ -14,58 +22,6 @@
extern int MCA_bus; extern int MCA_bus;
#endif #endif
/* Maximal number of MCA slots - actually, some machines have less, but
* they all have sufficient number of POS registers to cover 8.
*/
#define MCA_MAX_SLOT_NR 8
/* MCA_NOTFOUND is an error condition. The other two indicate
* motherboard POS registers contain the adapter. They might be
* returned by the mca_find_adapter() function, and can be used as
* arguments to mca_read_stored_pos(). I'm not going to allow direct
* access to the motherboard registers until we run across an adapter
* that requires it. We don't know enough about them to know if it's
* safe.
*
* See Documentation/mca.txt or one of the existing drivers for
* more information.
*/
#define MCA_NOTFOUND (-1)
#define MCA_INTEGSCSI (MCA_MAX_SLOT_NR)
#define MCA_INTEGVIDEO (MCA_MAX_SLOT_NR+1)
#define MCA_MOTHERBOARD (MCA_MAX_SLOT_NR+2)
/* Max number of adapters, including both slots and various integrated
* things.
*/
#define MCA_NUMADAPTERS (MCA_MAX_SLOT_NR+3)
/* Returns the slot of the first enabled adapter matching id. User can
* specify a starting slot beyond zero, to deal with detecting multiple
* devices. Returns MCA_NOTFOUND if id not found. Also checks the
* integrated adapters.
*/
extern int mca_find_adapter(int id, int start);
extern int mca_find_unused_adapter(int id, int start);
/* adapter state info - returns 0 if no */
extern int mca_isadapter(int slot);
extern int mca_isenabled(int slot);
extern int mca_is_adapter_used(int slot);
extern int mca_mark_as_used(int slot);
extern void mca_mark_as_unused(int slot);
/* gets a byte out of POS register (stored in memory) */
extern unsigned char mca_read_stored_pos(int slot, int reg);
/* This can be expanded later. Right now, it gives us a way of
* getting meaningful information into the MCA_info structure,
* so we can have a more interesting /proc/mca.
*/
extern void mca_set_adapter_name(int slot, char* name);
extern char* mca_get_adapter_name(int slot);
/* This sets up an information callback for /proc/mca/slot?. The /* This sets up an information callback for /proc/mca/slot?. The
* function is called with the buffer, slot, and device pointer (or * function is called with the buffer, slot, and device pointer (or
* some equally informative context information, or nothing, if you * some equally informative context information, or nothing, if you
...@@ -78,28 +34,115 @@ extern char* mca_get_adapter_name(int slot); ...@@ -78,28 +34,115 @@ extern char* mca_get_adapter_name(int slot);
* nastiness. * nastiness.
*/ */
typedef int (*MCA_ProcFn)(char* buf, int slot, void* dev); typedef int (*MCA_ProcFn)(char* buf, int slot, void* dev);
extern void mca_set_adapter_procfn(int slot, MCA_ProcFn, void* dev);
/* These routines actually mess with the hardware POS registers. They
* temporarily disable the device (and interrupts), so make sure you know
* what you're doing if you use them. Furthermore, writing to a POS may
* result in two devices trying to share a resource, which in turn can
* result in multiple devices sharing memory spaces, IRQs, or even trashing
* hardware. YOU HAVE BEEN WARNED.
*
* You can only access slots with this. Motherboard registers are off
* limits.
*/
/* read a byte from the specified POS register. */
extern unsigned char mca_read_pos(int slot, int reg);
/* write a byte to the specified POS register. */
extern void mca_write_pos(int slot, int reg, unsigned char byte);
/* Should only be called by the NMI interrupt handler, this will do some /* Should only be called by the NMI interrupt handler, this will do some
* fancy stuff to figure out what might have generated a NMI. * fancy stuff to figure out what might have generated a NMI.
*/ */
extern void mca_handle_nmi(void); extern void mca_handle_nmi(void);
enum MCA_AdapterStatus {
MCA_ADAPTER_NORMAL = 0,
MCA_ADAPTER_NONE = 1,
MCA_ADAPTER_DISABLED = 2,
MCA_ADAPTER_ERROR = 3
};
struct mca_device {
u64 dma_mask;
int pos_id;
int slot;
/* index into id_table, set by the bus match routine */
int index;
/* is there a driver installed? 0 - No, 1 - Yes */
int driver_loaded;
/* POS registers */
unsigned char pos[8];
/* if a pseudo adapter of the motherboard, this is the motherboard
* register value to use for setup cycles */
short pos_register;
enum MCA_AdapterStatus status;
#ifdef CONFIG_MCA_PROC_FS
/* name of the proc/mca file */
char procname[8];
/* /proc info callback */
MCA_ProcFn procfn;
/* device/context info for proc callback */
void *proc_dev;
#endif
struct device dev;
};
#define to_mca_device(mdev) container_of(mdev, struct mca_device, dev)
struct mca_bus_accessor_functions {
unsigned char (*mca_read_pos)(struct mca_device *, int reg);
void (*mca_write_pos)(struct mca_device *, int reg,
unsigned char byte);
int (*mca_transform_irq)(struct mca_device *, int irq);
int (*mca_transform_ioport)(struct mca_device *,
int region);
void * (*mca_transform_memory)(struct mca_device *,
void *memory);
};
struct mca_bus {
u64 default_dma_mask;
int number;
struct mca_bus_accessor_functions f;
struct device dev;
};
#define to_mca_bus(mdev) container_of(mdev, struct mca_bus, dev)
struct mca_driver {
const short *id_table;
void *driver_data;
struct device_driver driver;
};
#define to_mca_driver(mdriver) container_of(mdriver, struct mca_driver, driver)
/* Ongoing supported API functions */
extern struct mca_device *mca_find_device_by_slot(int slot);
extern int mca_system_init(void);
extern struct mca_bus *mca_attach_bus(int);
extern unsigned char mca_device_read_stored_pos(struct mca_device *mca_dev,
int reg);
extern unsigned char mca_device_read_pos(struct mca_device *mca_dev, int reg);
extern void mca_device_write_pos(struct mca_device *mca_dev, int reg,
unsigned char byte);
extern int mca_device_transform_irq(struct mca_device *mca_dev, int irq);
extern int mca_device_transform_ioport(struct mca_device *mca_dev, int port);
extern void *mca_device_transform_memory(struct mca_device *mca_dev,
void *mem);
extern int mca_device_claimed(struct mca_device *mca_dev);
extern void mca_device_set_claim(struct mca_device *mca_dev, int val);
extern enum MCA_AdapterStatus mca_device_status(struct mca_device *mca_dev);
extern struct bus_type mca_bus_type;
extern int mca_register_driver(struct mca_driver *drv);
extern void mca_unregister_driver(struct mca_driver *drv);
/* WARNING: only called by the boot time device setup */
extern int mca_register_device(int bus, struct mca_device *mca_dev);
#ifdef CONFIG_MCA_LEGACY
#include <linux/mca-legacy.h>
#endif
#ifdef CONFIG_MCA_PROC_FS
extern void mca_do_proc_init(void);
extern void mca_set_adapter_procfn(int slot, MCA_ProcFn, void* dev);
#else
static inline void mca_do_proc_init(void)
{
}
static inline void mca_set_adapter_procfn(int slot, MCA_ProcFn *fn, void* dev)
{
}
#endif
#endif /* _LINUX_MCA_H */ #endif /* _LINUX_MCA_H */
...@@ -225,6 +225,8 @@ int init_module(void) ...@@ -225,6 +225,8 @@ int init_module(void)
void cleanup_module(void) void cleanup_module(void)
{ {
int i;
for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++) for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++)
devfs_remove("netlink/%s", entries[i].name); devfs_remove("netlink/%s", entries[i].name);
for (i = 0; i < 16; i++) for (i = 0; i < 16; 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