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 + -
显示快捷键?