ibmmca.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,680 行 · 第 1/5 页
C
1,680 行
*device_type = TYPE_ROM; *block_length = 2048; /* (standard blocksize for yellow-/red-book) */ return 1; } if (*buf == TYPE_WORM) { *device_type = TYPE_WORM; *block_length = 2048; return 1; } if (*buf == TYPE_DISK) { *device_type = TYPE_DISK; if (read_capacity(host_index, ldn)) { *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24); return 1; } else return 0; } if (*buf == TYPE_MOD) { *device_type = TYPE_MOD; if (read_capacity(host_index, ldn)) { *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24); return 1; } else return 0; } if (*buf == TYPE_TAPE) { *device_type = TYPE_TAPE; *block_length = 0; /* not in use (setting by mt and mtst in op.) */ return 1; } if (*buf == TYPE_PROCESSOR) { *device_type = TYPE_PROCESSOR; *block_length = 0; /* they set their stuff on drivers */ return 1; } if (*buf == TYPE_SCANNER) { *device_type = TYPE_SCANNER; *block_length = 0; /* they set their stuff on drivers */ return 1; } if (*buf == TYPE_MEDIUM_CHANGER) { *device_type = TYPE_MEDIUM_CHANGER; *block_length = 0; /* One never knows, what to expect on a medium changer device. */ return 1; } return 0;}static void internal_ibmmca_scsi_setup(char *str, int *ints){ int i, j, io_base, id_base; char *token; io_base = 0; id_base = 0; if (str) { j = 0; while ((token = strsep(&str, ",")) != NULL) { if (!strcmp(token, "activity")) display_mode |= LED_ACTIVITY; if (!strcmp(token, "display")) display_mode |= LED_DISP; if (!strcmp(token, "adisplay")) display_mode |= LED_ADISP; if (!strcmp(token, "normal")) ibm_ansi_order = 0; if (!strcmp(token, "ansi")) ibm_ansi_order = 1; if (!strcmp(token, "fast")) global_adapter_speed = 0; if (!strcmp(token, "medium")) global_adapter_speed = 4; if (!strcmp(token, "slow")) global_adapter_speed = 7; if ((*token == '-') || (isdigit(*token))) { if (!(j % 2) && (io_base < IM_MAX_HOSTS)) io_port[io_base++] = simple_strtoul(token, NULL, 0); if ((j % 2) && (id_base < IM_MAX_HOSTS)) scsi_id[id_base++] = simple_strtoul(token, NULL, 0); j++; } } } else if (ints) { for (i = 0; i < IM_MAX_HOSTS && 2 * i + 2 < ints[0]; i++) { io_port[i] = ints[2 * i + 2]; scsi_id[i] = ints[2 * i + 2]; } } return;}static int ibmmca_getinfo(char *buf, int slot, void *dev_id){ struct Scsi_Host *shpnt; int len, speciale, connectore, k; unsigned int pos[8]; unsigned long flags; struct Scsi_Host *dev = dev_id; spin_lock_irqsave(dev->host_lock, flags); shpnt = dev; /* assign host-structure to local pointer */ len = 0; /* set filled text-buffer index to 0 */ /* get the _special contents of the hostdata structure */ speciale = ((struct ibmmca_hostdata *) shpnt->hostdata)->_special; connectore = ((struct ibmmca_hostdata *) shpnt->hostdata)->_connector_size; for (k = 2; k < 4; k++) pos[k] = ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k]; if (speciale == FORCED_DETECTION) { /* forced detection */ len += sprintf(buf + len, "Adapter category: forced detected\n" "***************************************\n" "*** Forced detected SCSI Adapter ***\n" "*** No chip-information available ***\n" "***************************************\n"); } else if (speciale == INTEGRATED_SCSI) { /* if the integrated subsystem has been found automatically: */ len += sprintf(buf + len, "Adapter category: integrated\n" "Chip revision level: %d\n" "Chip status: %s\n" "8 kByte NVRAM status: %s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 1) ? "enabled" : "disabled", (pos[2] & 2) ? "locked" : "accessible"); } else if ((speciale >= 0) && (speciale < (sizeof(subsys_list) / sizeof(struct subsys_list_struct)))) { /* if the subsystem is a slot adapter */ len += sprintf(buf + len, "Adapter category: slot-card\n" "ROM Segment Address: "); if ((pos[2] & 0xf0) == 0xf0) len += sprintf(buf + len, "off\n"); else len += sprintf(buf + len, "0x%x\n", ((pos[2] & 0xf0) << 13) + 0xc0000); len += sprintf(buf + len, "Chip status: %s\n", (pos[2] & 1) ? "enabled" : "disabled"); len += sprintf(buf + len, "Adapter I/O Offset: 0x%x\n", ((pos[2] & 0x0e) << 2)); } else { len += sprintf(buf + len, "Adapter category: unknown\n"); } /* common subsystem information to write to the slotn file */ len += sprintf(buf + len, "Subsystem PUN: %d\n", shpnt->this_id); len += sprintf(buf + len, "I/O base address range: 0x%x-0x%x\n", (unsigned int) (shpnt->io_port), (unsigned int) (shpnt->io_port + 7)); len += sprintf(buf + len, "MCA-slot size: %d bits", connectore); /* Now make sure, the bufferlength is devidable by 4 to avoid * paging problems of the buffer. */ while (len % sizeof(int) != (sizeof(int) - 1)) len += sprintf(buf + len, " "); len += sprintf(buf + len, "\n"); spin_unlock_irqrestore(shpnt->host_lock, flags); return len;}int ibmmca_detect(Scsi_Host_Template * scsi_template){ struct Scsi_Host *shpnt; int port, id, i, j, k, list_size, slot; int devices_on_irq_11 = 0; int devices_on_irq_14 = 0; int IRQ14_registered = 0; int IRQ11_registered = 0; found = 0; /* make absolutely sure, that found is set to 0 */ /* First of all, print the version number of the driver. This is * important to allow better user bugreports in case of already * having problems with the MCA_bus probing. */ printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION); /* if this is not MCA machine, return "nothing found" */ if (!MCA_bus) { printk(KERN_INFO "IBM MCA SCSI: No Microchannel-bus present --> Aborting.\n" " This machine does not have any IBM MCA-bus\n" " or the MCA-Kernel-support is not enabled!\n"); return 0; }#ifdef MODULE /* If the driver is run as module, read from conf.modules or cmd-line */ if (boot_options) option_setup(boot_options);#endif /* get interrupt request level */ if (request_irq(IM_IRQ, interrupt_handler, SA_SHIRQ, "ibmmcascsi", hosts)) { printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ); return 0; } else IRQ14_registered++; /* if ibmmcascsi setup option was passed to kernel, return "found" */ for (i = 0; i < IM_MAX_HOSTS; i++) if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) { printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]); if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], FORCED_DETECTION, "forced detected SCSI Adapter"))) { for (k = 2; k < 7; k++) ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = 0; ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = FORCED_DETECTION; mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter"); mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); mca_mark_as_used(MCA_INTEGSCSI); devices_on_irq_14++; } } if (found) return found; /* The POS2-register of all PS/2 model SCSI-subsystems has the following * interpretation of bits: * Bit 7 - 4 : Chip Revision ID (Release) * Bit 3 - 2 : Reserved * Bit 1 : 8k NVRAM Disabled * Bit 0 : Chip Enable (EN-Signal) * The POS3-register is interpreted as follows: * Bit 7 - 5 : SCSI ID * Bit 4 : Reserved = 0 * Bit 3 - 0 : Reserved = 0 * (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common * Interfaces (1991)"). * In short words, this means, that IBM PS/2 machines only support * 1 single subsystem by default. The slot-adapters must have another * configuration on pos2. Here, one has to assume the following * things for POS2-register: * Bit 7 - 4 : Chip Revision ID (Release) * Bit 3 - 1 : port offset factor * Bit 0 : Chip Enable (EN-Signal) * As I found a patch here, setting the IO-registers to 0x3540 forced, * as there was a 0x05 in POS2 on a model 56, I assume, that the * port 0x3540 must be fix for integrated SCSI-controllers. * Ok, this discovery leads to the following implementation: (M.Lang) */ /* first look for the IBM SCSI integrated subsystem on the motherboard */ for (j = 0; j < 8; j++) /* read the pos-information */ pos[j] = mca_read_stored_pos(MCA_INTEGSCSI, j); /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but * if we ignore the settings of all surrounding pos registers, it is not * completely sufficient to only check pos2 and pos3. */ /* Therefore, now the following if statement is used to * make sure, we see a real integrated onboard SCSI-interface and no * internal system information, which gets mapped to some pos registers * on models 95xx. */ if ((!pos[0] && !pos[1] && pos[2] > 0 && pos[3] > 0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || (pos[0] == 0xff && pos[1] == 0xff && pos[2] < 0xff && pos[3] < 0xff && pos[4] == 0xff && pos[5] == 0xff && pos[6] == 0xff && pos[7] == 0xff)) { if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ port = IM_IO_PORT; else { /* if disabled, no IRQs will be generated, as the chip won't * listen to the incoming commands and will do really nothing, * except for listening to the pos-register settings. If this * happens, I need to hugely think about it, as one has to * write something to the MCA-Bus pos register in order to * enable the chip. Normally, IBM-SCSI won't pass the POST, * when the chip is disabled (see IBM tech. ref.). */ port = IM_IO_PORT; /* anyway, set the portnumber and warn */ printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" " SCSI-operations may not work.\n"); } id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */ /* give detailed information on the subsystem. This helps me * additionally during debugging and analyzing bug-reports. */ printk(KERN_INFO "IBM MCA SCSI: IBM Integrated SCSI Controller ffound, io=0x%x, scsi id=%d,\n", port, id); printk(KERN_INFO " chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled."); /* register the found integrated SCSI-subsystem */ if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) { for (k = 2; k < 7; k++) ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI; mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller"); mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); mca_mark_as_used(MCA_INTEGSCSI); devices_on_irq_14++; } } /* now look for other adapters in MCA slots, */ /* determine the number of known IBM-SCSI-subsystem types */ /* see the pos[2] dependence to get the adapter port-offset. */ list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); for (i = 0; i < list_size; i++) { /* scan each slot for a fitting adapter id */ slot = 0; /* start at slot 0 */ while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot)) != MCA_NOTFOUND) { /* scan through all slots */ for (j = 0; j < 8; j++) /* read the pos-information */ pos[j] = mca_read_stored_pos(slot, j); if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ /* (explanations see above) */ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); else { /* anyway, set the portnumber and warn */ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); printk(KERN_WARNING " SCSI-operations may not work.\n"); } if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) { printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); printk(KERN_ERR " Impossible to determine adapter PUN!\n"); printk(KERN_ERR " Guessing adapter PUN = 7.\n"); id = 7; } else { id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ if (i == IBM_SCSI2_FW) { id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit * for F/W adapters */ } } if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) { /* IRQ11 is used by SCSI-2 F/W Adapter/A */ printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); /* get interrupt request level */ if (request_irq(IM_IRQ_FW, interrupt_handler, SA_SHIRQ, "ibmmcascsi", hosts)) { printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW); } else IRQ11_registered++; } printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id); if ((pos[2] & 0xf0) == 0xf0) printk(KERN_DEBUG" ROM Addr.=off,"); else printk(KERN_DEBUG " ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000); printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); /* register the hostadapter */ if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) { for (k = 2; k < 8; k++) ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i; mca_set_adapter_name(slot, subsys_list[i].description); mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt); mca_mark_as_used(slot); if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) devices_on_irq_11++; else devices_on_irq_14++; } slot++; /* advance to next slot */ } /* advance to next adapter id in the list of IBM-SCSI-subsystems */ } /* now check for SCSI-adapters, mapped to the integrated SCSI * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here, * as this is a known effect on some models 95xx. */ list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); for (i = 0; i < list_size; i++) { /* scan each slot for a fitting adapter id */ slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI); if (slot != MCA_NOTFOUND) { /* scan through all slots */ for (j = 0; j < 8; j++) /* read the pos-information */ pos[j] = mca_rea
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?