📄 ibmmca.c
字号:
if (*buf == TYPE_ROM) { *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;}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) { token = strtok(str,","); j = 0; while (token) { 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++; } token = strtok(NULL,","); } } 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){ struct Scsi_Host *shpnt; int len, speciale, connectore, k; unsigned int pos[8]; unsigned long flags; IBMLOCK 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"); IBMUNLOCK 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("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION); /* if this is not MCA machine, return "nothing found" */ if (!MCA_bus) { printk("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("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 incomming 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("IBM MCA SCSI: IBM Integrated SCSI Controller found, io=0x%x, scsi id=%d,\n" " chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", port, id, ((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("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" " SCSI-operations may not work.\n"); } if ((i==IBM_SCSI2_FW)&&(pos[6]!=0)) { printk("IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n" " Impossible to determine adapter PUN!\n" " 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("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("IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW); } else IRQ11_registered++; } printk("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(" ROM Addr.=off,"); else printk(" ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000); printk(" port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); /* register the hostadapter */ if ((shpnt = ibmmca_registe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -