patch-2.1.126 linux/arch/i386/kernel/mca.c
Next file: linux/arch/i386/kernel/setup.c
Previous file: linux/arch/i386/kernel/bios32.c
Back to the patch index
Back to the overall index
- Lines: 815
- Date:
Sat Oct 17 15:33:45 1998
- Orig file:
v2.1.125/linux/arch/i386/kernel/mca.c
- Orig date:
Wed Aug 26 11:37:33 1998
diff -u --recursive --new-file v2.1.125/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
@@ -3,11 +3,29 @@
* Written by Martin Kolinek, February 1996
*
* Changes:
- * July 28, 1996: fixed up integrated SCSI detection. Chris Beauregard
- * August 3rd, 1996: made mca_info local, made integrated registers
- * accessible through standard function calls, added name field,
- * more sanity checking. Chris Beauregard
- * August 9, 1996: Rewrote /proc/mca. cpbeaure
+ *
+ * Chris Beauregard July 28th, 1996
+ * - Fixed up integrated SCSI detection
+ *
+ * Chris Beauregard August 3rd, 1996
+ * - Made mca_info local
+ * - Made integrated registers accessible through standard function calls
+ * - Added name field
+ * - More sanity checking
+ *
+ * Chris Beauregard August 9th, 1996
+ * - Rewrote /proc/mca
+ *
+ * Chris Beauregard January 7th, 1997
+ * - Added basic NMI-processing
+ * - Added more information to mca_info structure
+ *
+ * David Weinehall October 12th, 1998
+ * - Made a lot of cleaning up in the source
+ * - Added use of save_flags / restore_flags
+ * - Added the 'driver_loaded' flag in MCA_adapter
+ * - Added an alternative implemention of ZP Gu's mca_find_unused_adapter
+ *
*/
#include <linux/types.h>
@@ -29,19 +47,38 @@
* eight POS registers. Then the machine may have integrated video and
* SCSI subsystems, which also have eight POS registers.
* Other miscellaneous information follows.
-*/
+ */
+
+typedef enum {
+ MCA_ADAPTER_NORMAL = 0,
+ MCA_ADAPTER_NONE = 1,
+ MCA_ADAPTER_DISABLED = 2,
+ MCA_ADAPTER_ERROR = 3
+} MCA_AdapterStatus;
+
struct MCA_adapter {
- unsigned char pos[8]; /* POS registers */
- char name[32]; /* name of the device - provided by driver */
- char procname[8]; /* name of /proc/mca file */
- MCA_ProcFn procfn; /* /proc info callback */
- void* dev; /* device/context info for callback */
+ MCA_AdapterStatus status; /* is there a valid adapter? */
+ int id; /* adapter id value */
+ unsigned char pos[8]; /* POS registers */
+ int driver_loaded; /* is there a driver installed? */
+ /* 0 - No, 1 - Yes */
+ char name[48]; /* adapter-name provided by driver */
+ char procname[8]; /* name of /proc/mca file */
+ MCA_ProcFn procfn; /* /proc info callback */
+ void* dev; /* device/context info for callback */
};
struct MCA_info {
- /* one for each of the 8 possible slots, plus one for integrated SCSI
- and one for integrated video. */
+/* one for each of the 8 possible slots, plus one for integrated SCSI
+ and one for integrated video. */
+
struct MCA_adapter slot[MCA_NUMADAPTERS];
+
+/* two potential addresses for integrated SCSI adapter - this will
+ * track which one we think it is
+ */
+
+ unsigned char which_scsi;
};
/* The mca_info structure pointer. If MCA bus is present, the function
@@ -49,70 +86,145 @@
* adapters into setup mode, allocates and fills an MCA_info structure,
* and points this pointer to the structure. Otherwise the pointer
* is set to zero.
-*/
+ */
+
static struct MCA_info* mca_info = 0;
-/*MCA registers*/
-#define MCA_MOTHERBOARD_SETUP_REG 0x94
-#define MCA_ADAPTER_SETUP_REG 0x96
-#define MCA_POS_REG(n) (0x100+(n))
+/* 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 */
/*--------------------------------------------------------------------*/
#ifdef CONFIG_PROC_FS
+
static void mca_do_proc_init( void );
static int mca_default_procfn( char* buf, int slot );
static ssize_t proc_mca_read( struct file*, char*, size_t, loff_t *);
+
static struct file_operations proc_mca_operations = {
- NULL, proc_mca_read,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ NULL, /* array_lseek */
+ proc_mca_read, /* array_read */
+ NULL, /* array_write */
+ NULL, /* array_readdir */
+ NULL, /* array_poll */
+ NULL, /* array_ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* flush */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
};
+
static struct inode_operations proc_mca_inode_operations = {
- &proc_mca_operations,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ &proc_mca_operations, /* default base directory file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
};
#endif
/*--------------------------------------------------------------------*/
+/* Build the status info for the adapter */
+
+static void mca_configure_adapter_status( int slot ) {
+ mca_info->slot[slot].status = MCA_ADAPTER_NONE;
+
+ mca_info->slot[slot].id = mca_info->slot[slot].pos[0]
+ + (mca_info->slot[slot].pos[1] << 8);
+
+ if( !mca_info->slot[slot].id ) {
+
+ /* id = 0x0000 usually indicates hardware failure,
+ * however, ZP Gu (zpg@castle.net> reports that his 9556
+ * has 0x0000 as id and everything still works.
+ */
+
+ mca_info->slot[slot].status = MCA_ADAPTER_ERROR;
+
+ return;
+ } else if( mca_info->slot[slot].id != 0xffff ) {
+
+ /* 0xffff usually indicates that there's no adapter,
+ * however, some integrated adapters may have 0xffff as
+ * their id and still be valid. Examples are on-board
+ * VGA of the 55sx, the integrated SCSI of the 56 & 57,
+ * and possibly also the 95 ULTIMEDIA.
+ */
+
+ mca_info->slot[slot].status = MCA_ADAPTER_NORMAL;
+ }
+
+ if( (mca_info->slot[slot].id == 0xffff ||
+ mca_info->slot[slot].id == 0x0000) && slot >= MCA_MAX_SLOT_NR ) {
+ int j;
+
+ for( j = 2; j < 8; j++ ) {
+ if( mca_info->slot[slot].pos[j] != 0xff ) {
+ mca_info->slot[slot].status = MCA_ADAPTER_NORMAL;
+ break;
+ }
+ }
+ }
+
+ if( !(mca_info->slot[slot].pos[2] & MCA_ENABLED) ) {
+
+ /* enabled bit is in pos 2 */
+
+ mca_info->slot[slot].status = MCA_ADAPTER_DISABLED;
+ }
+} /* mca_configure_adapter_status */
+
+/*--------------------------------------------------------------------*/
+
__initfunc(void mca_init(void))
{
unsigned int i, j;
- int foundscsi = 0;
+ unsigned long flags;
/* WARNING: Be careful when making changes here. Putting an adapter
* and the motherboard simultaneously into setup mode may result in
* damage to chips (according to The Indispensible PC Hardware Book
* by Hans-Peter Messmer). Also, we disable system interrupts (so
* that we are not disturbed in the middle of this).
- */
-
- /*
- * Make sure the MCA bus is present
*/
+
+ /* Make sure the MCA bus is present */
if (!MCA_bus)
return;
+ printk( "Micro Channel bus detected.\n" );
+ save_flags( flags );
cli();
- /*
- * Allocate MCA_info structure (at address divisible by 8)
- */
+ /* Allocate MCA_info structure (at address divisible by 8) */
mca_info = kmalloc(sizeof(struct MCA_info), GFP_ATOMIC);
- /*
- * Make sure adapter setup is off
- */
+ /* Make sure adapter setup is off */
outb_p(0, MCA_ADAPTER_SETUP_REG);
- /*
- * Put motherboard into video setup mode, read integrated video
+ /* Put motherboard into video setup mode, read integrated video
* pos registers, and turn motherboard setup off.
*/
@@ -121,6 +233,7 @@
for (j=0; j<8; j++) {
mca_info->slot[MCA_INTEGVIDEO].pos[j] = inb_p(MCA_POS_REG(j));
}
+ mca_configure_adapter_status(MCA_INTEGVIDEO);
/* Put motherboard into scsi setup mode, read integrated scsi
* pos registers, and turn motherboard setup off.
@@ -132,51 +245,57 @@
* a good bet that only one could be valid at a time. This could
* screw up though if one is used for something else on the other
* machine.
- */
+ */
outb_p(0xf7, MCA_MOTHERBOARD_SETUP_REG);
mca_info->slot[MCA_INTEGSCSI].name[0] = 0;
for (j=0; j<8; j++) {
if( (mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j))) != 0xff )
{
- /* 0xff all across means no device. 0x00 means something's
- broken, but a device is probably there. However, if you get
- 0x00 from a motherboard register it won't matter what we
- find. For the record, on the 57SLC, the integrated SCSI
- adapter has 0xffff for the adapter ID, but nonzero for
- other registers. */
- foundscsi = 1;
+ /* 0xff all across means no device. 0x00 means something's
+ * broken, but a device is probably there. However, if you get
+ * 0x00 from a motherboard register it won't matter what we
+ * find. For the record, on the 57SLC, the integrated SCSI
+ * adapter has 0xffff for the adapter ID, but nonzero for
+ * other registers.
+ */
+
+ mca_info->which_scsi = 0xf7;
}
}
- if( !foundscsi )
- {
- /*
- * Didn't find it at 0xfd, try somewhere else...
- */
+ if( !mca_info->which_scsi ) {
+
+ /* Didn't find it at 0xf7, try somewhere else... */
+ mca_info->which_scsi = 0xfd;
+
outb_p(0xfd, MCA_MOTHERBOARD_SETUP_REG);
for (j=0; j<8; j++)
mca_info->slot[MCA_INTEGSCSI].pos[j] = inb_p(MCA_POS_REG(j));
}
-
+ mca_configure_adapter_status(MCA_INTEGSCSI);
+
/* turn off motherboard setup */
+
outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
- /*
- * Now loop over MCA slots: put each adapter into setup mode, and
- * read its pos registers. Then put adapter setup off.
+ /* Now loop over MCA slots: put each adapter into setup mode, and
+ * read its pos registers. Then put adapter setup off.
*/
for (i=0; i<MCA_MAX_SLOT_NR; i++) {
outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);
- for (j=0; j<8; j++) mca_info->slot[i].pos[j]=inb_p(MCA_POS_REG(j));
+ for (j=0; j<8; j++) {
+ mca_info->slot[i].pos[j]=inb_p(MCA_POS_REG(j));
+ }
mca_info->slot[i].name[0] = 0;
+ mca_info->slot[i].driver_loaded = 0;
+ mca_configure_adapter_status(i);
}
outb_p(0, MCA_ADAPTER_SETUP_REG);
- /*
- * Enable interrupts and return memory start
- */
- sti();
+ /* Enable interrupts and return memory start */
+
+ restore_flags( flags );
request_region(0x60,0x01,"system control port B (MCA)");
request_region(0x90,0x01,"arbitration (MCA)");
@@ -193,29 +312,89 @@
/*--------------------------------------------------------------------*/
-int mca_find_adapter( int id, int start )
+static void mca_handle_nmi_slot( int slot, int check_flag )
{
- int slot_id = 0;
- unsigned char status = 0;
+ if( slot < MCA_MAX_SLOT_NR ) {
+ printk( "NMI: caused by MCA adapter in slot %d (%s)\n", slot+1,
+ mca_info->slot[slot].name );
+ } else if( slot == MCA_INTEGSCSI ) {
+ printk( "NMI: caused by MCA integrated SCSI adapter (%s)\n",
+ mca_info->slot[slot].name );
+ } else if( slot == MCA_INTEGVIDEO ) {
+ printk( "NMI: caused by MCA integrated video adapter (%s)\n",
+ mca_info->slot[slot].name );
+ }
+
+ /* more info available in pos 6 and 7? */
+
+ if( check_flag ) {
+ unsigned char pos6, pos7;
+
+ pos6 = mca_read_pos( slot, 6 );
+ pos7 = mca_read_pos( slot, 7 );
+
+ printk( "NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7 );
+ }
+
+} /* mca_handle_nmi_slot */
+
+/*--------------------------------------------------------------------*/
+
+void mca_handle_nmi( void )
+{
+
+ int i;
+ unsigned char pos5;
+
+ /* First try - scan the various adapters and see if a specific
+ * adapter was responsible for the error
+ */
+
+ for( i = 0; i < MCA_NUMADAPTERS; i += 1 ) {
+
+ /* bit 7 of POS 5 is reset when this adapter has a hardware
+ * error. bit 7 it reset if there's error information
+ * available in pos 6 and 7. */
+
+ pos5 = mca_read_pos( i, 5 );
+
+ if( !(pos5 & 0x80) ) {
+ mca_handle_nmi_slot( i, !(pos5 & 0x40) );
+ return;
+ }
+ }
+
+ /* if I recall correctly, there's a whole bunch of other things that
+ * we can do to check for NMI problems, but that's all I know about
+ * at the moment.
+ */
+
+ printk( "NMI generated from unknown source!\n" );
+} /* mca_handle_nmi */
+/*--------------------------------------------------------------------*/
+
+int mca_find_adapter( int id, int start )
+{
if( mca_info == 0 || id == 0 || id == 0xffff ) {
return MCA_NOTFOUND;
}
for( ; start >= 0 && start < MCA_NUMADAPTERS; start += 1 ) {
- slot_id = (mca_info->slot[start].pos[1] << 8)
- + mca_info->slot[start].pos[0];
- status = mca_info->slot[start].pos[2];
/* not sure about this. There's no point in returning
- adapters that aren't enabled, since they can't actually
- be used. However, they might be needed for statistical
- purposes or something... */
- if( !(status & MCA_ENABLED) ) {
+ * adapters that aren't enabled, since they can't actually
+ * be used. However, they might be needed for statistical
+ * purposes or something... But if that is the case, the
+ * user is free to write a routine that manually iterates
+ * through the adapters.
+ */
+
+ if( mca_info->slot[start].status == MCA_ADAPTER_DISABLED ) {
continue;
}
- if( id == slot_id ) {
+ if( id == mca_info->slot[start].id ) {
return start;
}
}
@@ -225,6 +404,37 @@
/*--------------------------------------------------------------------*/
+int mca_find_unused_adapter( int id, int start )
+{
+ if( mca_info == 0 || id == 0 || id == 0xffff ) {
+ return MCA_NOTFOUND;
+ }
+
+ for( ; start >= 0 && start < MCA_NUMADAPTERS; start += 1 ) {
+
+ /* not sure about this. There's no point in returning
+ * adapters that aren't enabled, since they can't actually
+ * be used. However, they might be needed for statistical
+ * purposes or something... But if that is the case, the
+ * user is free to write a routine that manually iterates
+ * through the adapters.
+ */
+
+ if( mca_info->slot[start].status == MCA_ADAPTER_DISABLED ||
+ mca_info->slot[start].driver_loaded ) {
+ continue;
+ }
+
+ if( id == mca_info->slot[start].id ) {
+ return start;
+ }
+ }
+
+ return MCA_NOTFOUND;
+} /* mca_find_unused_adapter() */
+
+/*--------------------------------------------------------------------*/
+
unsigned char mca_read_stored_pos( int slot, int reg )
{
if( slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0 ) return 0;
@@ -237,57 +447,97 @@
unsigned char mca_read_pos( int slot, int reg )
{
unsigned int byte = 0;
+ unsigned long flags;
- if( slot < 0 || slot >= MCA_MAX_SLOT_NR || mca_info == 0 ) return 0;
+ if( slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0 ) return 0;
if( reg < 0 || reg >= 8 ) return 0;
+ save_flags( flags );
cli();
- /*make sure motherboard setup is off*/
+ /* make sure motherboard setup is off */
+
outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
/* read in the appropriate register */
- outb_p(0x8|(slot&0xf), MCA_ADAPTER_SETUP_REG);
- byte = inb_p(MCA_POS_REG(reg));
- outb_p(0, MCA_ADAPTER_SETUP_REG);
- sti();
+ if( slot == MCA_INTEGSCSI && mca_info->which_scsi ) {
+
+ /* disable adapter setup, enable motherboard setup */
+
+ outb_p(0, MCA_ADAPTER_SETUP_REG);
+ outb_p(mca_info->which_scsi, MCA_MOTHERBOARD_SETUP_REG);
+
+ byte = inb_p(MCA_POS_REG(reg));
+ outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
+ } else if( slot == MCA_INTEGVIDEO ) {
+
+ /* disable adapter setup, enable motherboard setup */
+
+ outb_p(0, MCA_ADAPTER_SETUP_REG);
+ outb_p(0xdf, MCA_MOTHERBOARD_SETUP_REG);
+
+ byte = inb_p(MCA_POS_REG(reg));
+ outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
+ } else if( slot < MCA_MAX_SLOT_NR ) {
+
+ /* make sure motherboard setup is off */
+
+ outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
+
+ /* read the appropriate register */
+
+ outb_p(0x8|(slot&0xf), MCA_ADAPTER_SETUP_REG);
+ byte = inb_p(MCA_POS_REG(reg));
+ outb_p(0, MCA_ADAPTER_SETUP_REG);
+ }
/* make sure the stored values are consistent, while we're here */
+
mca_info->slot[slot].pos[reg] = byte;
+ restore_flags( flags );
+
return byte;
} /* mca_read_pos() */
/*--------------------------------------------------------------------*/
+
/* Note that this a technically a Bad Thing, as IBM tech stuff says
- you should only set POS values through their utilities.
- However, some devices such as the 3c523 recommend that you write
- back some data to make sure the configuration is consistent.
- I'd say that IBM is right, but I like my drivers to work.
- This function can't do checks to see if multiple devices end up
- with the same resources, so you might see magic smoke if someone
- screws up. */
+ * you should only set POS values through their utilities.
+ * However, some devices such as the 3c523 recommend that you write
+ * back some data to make sure the configuration is consistent.
+ * I'd say that IBM is right, but I like my drivers to work.
+ * This function can't do checks to see if multiple devices end up
+ * with the same resources, so you might see magic smoke if someone
+ * screws up.
+ */
void mca_write_pos( int slot, int reg, unsigned char byte )
{
+ unsigned long flags;
+
if( slot < 0 || slot >= MCA_MAX_SLOT_NR ) return;
if( reg < 0 || reg >= 8 ) return;
if (mca_info == 0 ) return;
+ save_flags( flags );
cli();
- /*make sure motherboard setup is off*/
+ /* make sure motherboard setup is off */
+
outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
/* read in the appropriate register */
+
outb_p(0x8|(slot&0xf), MCA_ADAPTER_SETUP_REG);
outb_p( byte, MCA_POS_REG(reg) );
outb_p(0, MCA_ADAPTER_SETUP_REG);
- sti();
+ restore_flags( flags );
/* update the global register list, while we have the byte */
+
mca_info->slot[slot].pos[reg] = byte;
} /* mca_write_pos() */
@@ -298,8 +548,14 @@
if( mca_info == 0 ) return;
if( slot >= 0 && slot < MCA_NUMADAPTERS ) {
- strncpy( mca_info->slot[slot].name, name,
- sizeof(mca_info->slot[slot].name) );
+ if( name != NULL ) {
+ strncpy( mca_info->slot[slot].name, name,
+ sizeof(mca_info->slot[slot].name)-1 );
+ mca_info->slot[slot].name[
+ sizeof(mca_info->slot[slot].name)-1] = 0;
+ } else {
+ mca_info->slot[slot].name[0] = 0;
+ }
}
}
@@ -313,6 +569,23 @@
}
}
+int mca_is_adapter_used( int slot )
+{
+ return mca_info->slot[slot].driver_loaded;
+}
+
+int mca_mark_as_used( int slot )
+{
+ if(mca_info->slot[slot].driver_loaded) return 1;
+ mca_info->slot[slot].driver_loaded = 1;
+ return 0;
+}
+
+void mca_mark_as_unused( int slot )
+{
+ mca_info->slot[slot].driver_loaded = 0;
+}
+
char *mca_get_adapter_name( int slot )
{
if( mca_info == 0 ) return 0;
@@ -328,19 +601,9 @@
{
if( mca_info == 0 ) return 0;
- if( slot >= MCA_MAX_SLOT_NR ) {
- /* some integrated adapters have 0xffff for an ID, but
- are still there. VGA, for example. */
- int i;
- for( i = 0; i < 8; i ++ ) {
- if( mca_info->slot[slot].pos[i] != 0xff ) {
- return 1;
- }
- }
- return 0;
- } else if( slot >= 0 && slot < MCA_NUMADAPTERS ) {
- return (mca_info->slot[slot].pos[0] != 0xff ||
- mca_info->slot[slot].pos[1] != 0xff);
+ if( slot >= 0 && slot < MCA_NUMADAPTERS ) {
+ return (( mca_info->slot[slot].status == MCA_ADAPTER_NORMAL )
+ || (mca_info->slot[slot].status == MCA_ADAPTER_DISABLED ) );
}
return 0;
@@ -351,7 +614,7 @@
if( mca_info == 0 ) return 0;
if( slot >= 0 && slot < MCA_NUMADAPTERS ) {
- return (mca_info->slot[slot].pos[2] & MCA_ENABLED);
+ return (mca_info->slot[slot].status == MCA_ADAPTER_NORMAL);
}
return 0;
@@ -367,9 +630,8 @@
if( MCA_bus && mca_info != 0 )
{
- /*
- * Format pos registers of eight MCA slots
- */
+ /* Format pos registers of eight MCA slots */
+
for (i=0; i<MCA_MAX_SLOT_NR; i++)
{
len += sprintf(buf+len, "Slot %d: ", i+1);
@@ -378,29 +640,24 @@
len += sprintf( buf+len, " %s\n", mca_info->slot[i].name );
}
- /*
- * Format pos registers of integrated video subsystem
- */
+ /* Format pos registers of integrated video subsystem */
- len += sprintf(buf+len, "Video: ");
+ len += sprintf(buf+len, "Video : ");
for (j=0; j<8; j++)
len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]);
len += sprintf( buf+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name );
- /*
- * Format pos registers of integrated SCSI subsystem
- */
+ /* Format pos registers of integrated SCSI subsystem */
- len += sprintf(buf+len, "SCSI: ");
+ len += sprintf(buf+len, "SCSI : ");
for (j=0; j<8; j++)
len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]);
len += sprintf( buf+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name );
}
else
{
- /*
- * Leave it empty if MCA not detected
- * this should never happen
+ /* Leave it empty if MCA not detected - this should *never*
+ * happen!
*/
}
@@ -409,12 +666,13 @@
/*--------------------------------------------------------------------*/
+
__initfunc(void mca_do_proc_init( void ))
{
int i = 0;
struct proc_dir_entry* node = 0;
- if( mca_info == 0 ) return; /* never happens */
+ if( mca_info == 0 ) return; /* should never happen */
proc_register( &proc_mca, &(struct proc_dir_entry) {
PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
@@ -424,7 +682,8 @@
PROC_MCA_MACHINE, 7, "machine", S_IFREG|S_IRUGO,
1, 0, 0, 0, &proc_mca_inode_operations,} );
- /* initialize /proc entries for existing adapters */
+ /* initialize /proc/mca entries for existing adapters */
+
for( i = 0; i < MCA_NUMADAPTERS; i += 1 ) {
mca_info->slot[i].procfn = 0;
mca_info->slot[i].dev = 0;
@@ -460,6 +719,7 @@
int len = 0, i;
/* this really shouldn't happen... */
+
if( mca_info == 0 ) {
*buf = 0;
return 0;
@@ -475,7 +735,9 @@
len += sprintf( buf+len, "Integrated Video Adapter\n" );
}
if( mca_info->slot[slot].name[0] ) {
+
/* drivers might register a name without /proc handler... */
+
len += sprintf( buf+len, "Adapter Name: %s\n",
mca_info->slot[slot].name );
} else {
@@ -485,6 +747,8 @@
mca_info->slot[slot].pos[1], mca_info->slot[slot].pos[0] );
len += sprintf( buf+len, "Enabled: %s\nPOS: ",
mca_isenabled(slot) ? "Yes" : "No" );
+ len += sprintf( buf+len, "Driver Installed: %s\n",
+ mca_is_adapter_used(slot) ? "Yes" : "No" );
for (i=0; i<8; i++) {
len += sprintf(buf+len, "%02x ", mca_info->slot[slot].pos[i]);
}
@@ -505,13 +769,6 @@
return len;
}
-/*
-static int mca_not_implemented( char* buf )
-{
- return sprintf( buf, "Sorry, not implemented yet...\n" );
-}
-*/
-
static int mca_fill( char* page, int pid, int type, char** start,
loff_t *offset, int length)
{
@@ -540,9 +797,11 @@
/* if we made it here, we better have a valid slot */
/* get the standard info */
+
len = mca_default_procfn( page, slot );
/* do any device-specific processing, if there is any */
+
if( mca_info->slot[slot].procfn ) {
len += mca_info->slot[slot].procfn( page+len, slot,
mca_info->slot[slot].dev );
@@ -551,9 +810,7 @@
return len;
} /* mca_fill() */
-/*
- * Blatantly stolen from fs/proc/array.c, and thus is probably overkill
- */
+/* Blatantly stolen from fs/proc/array.c, and thus is probably overkill */
#define PROC_BLOCK_SIZE (3*1024)
@@ -587,11 +844,13 @@
}
if (start != 0) {
/* We have had block-adjusting processing! */
+
copy_to_user(buf, start, length);
*ppos += length;
count = length;
} else {
/* Static 4kB (or whatever) block capacity */
+
if (*ppos >= length) {
free_page(page);
return 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov