📄 mca.c
字号:
EXPORT_SYMBOL(mca_read_stored_pos);/*--------------------------------------------------------------------*//** * mca_read_pos - read POS register from card * @slot: slot number 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_read_stored_pos and * may not be invoked from interrupt context. It handles the * deep magic required for onboard devices transparently. */unsigned char mca_read_pos(int slot, int reg){ unsigned int byte = 0; unsigned long flags; if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == NULL) return 0; if(reg < 0 || reg >= 8) return 0; save_flags(flags); cli(); /* Make sure motherboard setup is off */ outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); /* Read in the appropriate register */ 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_MOTHERBOARD) { /* Disable adapter setup, enable motherboard setup */ outb_p(0, MCA_ADAPTER_SETUP_REG); outb_p(0x7f, 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() */EXPORT_SYMBOL(mca_read_pos);/*--------------------------------------------------------------------*//** * mca_write_pos - read POS register from card * @slot: slot number to read from * @reg: register to read from * @byte: byte to write to the POS registers * * Store a POS value directly from 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. * * 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. */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 == NULL) return; save_flags(flags); cli(); /* 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); restore_flags(flags); /* Update the global register list, while we have the byte */ mca_info->slot[slot].pos[reg] = byte;} /* mca_write_pos() */EXPORT_SYMBOL(mca_write_pos);/*--------------------------------------------------------------------*//** * mca_set_adapter_name - Set the description of the card * @slot: slot to name * @name: text string for the namen * * This function sets the name reported via /proc for this * adapter slot. This is for user information only. Setting a * name deletes any previous name. */void mca_set_adapter_name(int slot, char* name){ if(mca_info == NULL) return; if(slot >= 0 && slot < MCA_NUMADAPTERS) { 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; } }}EXPORT_SYMBOL(mca_set_adapter_name);/** * 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* dev){ if(mca_info == NULL) return; if(slot >= 0 && slot < MCA_NUMADAPTERS) { mca_info->slot[slot].procfn = procfn; mca_info->slot[slot].dev = dev; }}EXPORT_SYMBOL(mca_set_adapter_procfn);/** * mca_is_adapter_used - check if claimed by driver * @slot: slot to check * * Returns 1 if the slot has been claimed by a driver */int mca_is_adapter_used(int slot){ return mca_info->slot[slot].driver_loaded;}EXPORT_SYMBOL(mca_is_adapter_used);/** * mca_mark_as_used - claim an MCA device * @slot: slot to claim * FIXME: should we make this threadsafe * * Claim an MCA slot for a device driver. If the * slot is already taken the function returns 1, * if it is not taken it is claimed and 0 is * returned. */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;}EXPORT_SYMBOL(mca_mark_as_used);/** * mca_mark_as_unused - release an MCA device * @slot: slot to claim * * Release the slot for other drives to use. */void mca_mark_as_unused(int slot){ mca_info->slot[slot].driver_loaded = 0;}EXPORT_SYMBOL(mca_mark_as_unused);/** * mca_get_adapter_name - get the adapter description * @slot: slot to query * * Return the adapter description if set. If it has not been * set or the slot is out range then return NULL. */char *mca_get_adapter_name(int slot){ if(mca_info == NULL) return 0; if(slot >= 0 && slot < MCA_NUMADAPTERS) { return mca_info->slot[slot].name; } return 0;}EXPORT_SYMBOL(mca_get_adapter_name);/** * mca_isadapter - check if the slot holds an adapter * @slot: slot to query * * Returns zero if the slot does not hold an adapter, non zero if * it does. */int mca_isadapter(int slot){ if(mca_info == NULL) return 0; 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;}EXPORT_SYMBOL(mca_isadapter);/** * mca_isadapter - check if the slot holds an adapter * @slot: slot to query * * Returns a non zero value if the slot holds an enabled adapter * and zero for any other case. */int mca_isenabled(int slot){ if(mca_info == NULL) return 0; if(slot >= 0 && slot < MCA_NUMADAPTERS) { return (mca_info->slot[slot].status == MCA_ADAPTER_NORMAL); } return 0;}EXPORT_SYMBOL(mca_isenabled);/*--------------------------------------------------------------------*/#ifdef CONFIG_PROC_FSint get_mca_info(char *page, char **start, off_t off, int count, int *eof, void *data){ int i, j, len = 0; if(MCA_bus && mca_info != NULL) { /* Format POS registers of eight MCA slots */ for(i=0; i<MCA_MAX_SLOT_NR; i++) { len += sprintf(page+len, "Slot %d: ", i+1); for(j=0; j<8; j++) len += sprintf(page+len, "%02x ", mca_info->slot[i].pos[j]); len += sprintf(page+len, " %s\n", mca_info->slot[i].name); } /* Format POS registers of integrated video subsystem */ len += sprintf(page+len, "Video : "); for(j=0; j<8; j++) len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]); len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name); /* Format POS registers of integrated SCSI subsystem */ len += sprintf(page+len, "SCSI : "); for(j=0; j<8; j++) len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]); len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name); /* Format POS registers of motherboard */ len += sprintf(page+len, "Planar: "); for(j=0; j<8; j++) len += sprintf(page+len, "%02x ", mca_info->slot[MCA_MOTHERBOARD].pos[j]); len += sprintf(page+len, " %s\n", mca_info->slot[MCA_MOTHERBOARD].name); } 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_adapter *p){ int len = 0, i; int slot = p - mca_info->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(p->name[0]) { /* Drivers might register a name without /proc handler... */ len += sprintf(buf+len, "Adapter Name: %s\n", p->name); } else { len += sprintf(buf+len, "Adapter Name: Unknown\n"); } len += sprintf(buf+len, "Id: %02x%02x\n", p->pos[1], p->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 ", p->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_adapter *p = (struct MCA_adapter *)data; int len = 0; /* Get the standard info */ len = mca_default_procfn(page, p); /* Do any device-specific processing, if there is any */ if(p->procfn) { len += p->procfn(page+len, p-mca_info->slot, p->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_adapter *p; if(mca_info == NULL) return; /* Should never happen */ 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++) { p = &mca_info->slot[i]; p->procfn = 0; if(i < MCA_MAX_SLOT_NR) sprintf(p->procname,"slot%d", i+1); else if(i == MCA_INTEGVIDEO) sprintf(p->procname,"video"); else if(i == MCA_INTEGSCSI) sprintf(p->procname,"scsi"); else if(i == MCA_MOTHERBOARD) sprintf(p->procname,"planar"); if(!mca_isadapter(i)) continue; node = create_proc_read_entry(p->procname, 0, proc_mca, mca_read_proc, (void *)p); if(node == NULL) { printk("Failed to allocate memory for MCA proc-entries!"); return; } }} /* mca_do_proc_init() */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -