printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n" "              On ldn 7-14 SCSI-commands everywhere in progress.\n" "              Reporting DID_NO_CONNECT for device (%d,%d).\n", target, cmd->device->lun); 
scmd_printk(KERN_WARNING, cmd, "IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n" "              On ldn 7-14 SCSI-commands everywhere in progress.\n" "              Reporting DID_NO_CONNECT for device.\n"); 
static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)){	unsigned int ldn;	unsigned int scsi_cmd;	struct im_scb *scb;	struct Scsi_Host *shpnt;	int current_ldn;	int id, lun;	int target;	int host_index;	int max_pun;	int i;	struct scatterlist *sl;	shpnt = cmd->device->host;	/* search for the right hostadapter */	for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);	if (!hosts[host_index]) {	/* invalid hostadapter descriptor address */		cmd->result = DID_NO_CONNECT << 16;		if (done)			done(cmd);		return 0;	}	max_pun = subsystem_maxid(host_index);	if (ibm_ansi_order) {		target = max_pun - 1 - cmd->device->id;		if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index)))			target--;		else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index)))			target++;	} else		target = cmd->device->id;	/* if (target,lun) is NO LUN or not existing at all, return error */	if ((get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {		cmd->result = DID_NO_CONNECT << 16;		if (done)			done(cmd);		return 0;	}	/*if (target,lun) unassigned, do further checks... */	ldn = get_ldn(host_index)[target][cmd->device->lun];	if (ldn >= MAX_LOG_DEV) {	/* on invalid ldn do special stuff */		if (ldn > MAX_LOG_DEV) {	/* dynamical remapping if ldn unassigned */			current_ldn = next_ldn(host_index);	/* stop-value for one circle */			while (ld(host_index)[next_ldn(host_index)].cmd) {	/* search for a occupied, but not in */				/* command-processing ldn. */				next_ldn(host_index)++;				if (next_ldn(host_index) >= MAX_LOG_DEV)					next_ldn(host_index) = 7;				if (current_ldn == next_ldn(host_index)) {	/* One circle done ? */					/* no non-processing ldn found */					printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n" "              On ldn 7-14 SCSI-commands everywhere in progress.\n" "              Reporting DID_NO_CONNECT for device (%d,%d).\n", target, cmd->device->lun);					cmd->result = DID_NO_CONNECT << 16;	/* return no connect */					if (done)						done(cmd);					return 0;				}			}			/* unmap non-processing ldn */			for (id = 0; id < max_pun; id++)				for (lun = 0; lun < 8; lun++) {					if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) {						get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;						get_scsi(host_index)[id][lun] = TYPE_NO_DEVICE;						/* unmap entry */					}				}			/* set reduced interrupt_handler-mode for checking */			local_checking_phase_flag(host_index) = 1;			/* map found ldn to pun,lun */			get_ldn(host_index)[target][cmd->device->lun] = next_ldn(host_index);			/* change ldn to the right value, that is now next_ldn */			ldn = next_ldn(host_index);			/* unassign all ldns (pun,lun,ldn does not matter for remove) */			immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);			/* set only LDN for remapped device */			immediate_assign(host_index, target, cmd->device->lun, ldn, SET_LDN);			/* get device information for ld[ldn] */			if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) {				ld(host_index)[ldn].cmd = NULL;	/* To prevent panic set 0, because								   devices that were not assigned,								   should have nothing in progress. */				get_scsi(host_index)[target][cmd->device->lun] = ld(host_index)[ldn].device_type;				/* increase assignment counters for statistics in /proc */				IBM_DS(host_index).dynamical_assignments++;				IBM_DS(host_index).ldn_assignments[ldn]++;			} else				/* panic here, because a device, found at boottime has				   vanished */				panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->device->lun);			/* unassign again all ldns (pun,lun,ldn does not matter for remove) */			immediate_assign(host_index, 0, 0, 0, REMOVE_LDN);			/* remap all ldns, as written in the pun/lun table */			lun = 0;#ifdef CONFIG_SCSI_MULTI_LUN			for (lun = 0; lun < 8; lun++)#endif				for (id = 0; id < max_pun; id++) {					if (get_ldn(host_index)[id][lun] <= MAX_LOG_DEV)						immediate_assign(host_index, id, lun, get_ldn(host_index)[id][lun], SET_LDN);				}			/* set back to normal interrupt_handling */			local_checking_phase_flag(host_index) = 0;#ifdef IM_DEBUG_PROBE			/* Information on syslog terminal */			printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->device->lun);#endif			/* increase next_ldn for next dynamical assignment */			next_ldn(host_index)++;			if (next_ldn(host_index) >= MAX_LOG_DEV)				next_ldn(host_index) = 7;		} else {	/* wall against Linux accesses to the subsystem adapter */			cmd->result = DID_BAD_TARGET << 16;			if (done)				done(cmd);			return 0;		}	}	/*verify there is no command already in progress for this log dev */	if (ld(host_index)[ldn].cmd)		panic("IBM MCA SCSI: cmd already in progress for this ldn.\n");	/*save done in cmd, and save cmd for the interrupt handler */	cmd->scsi_done = done;	ld(host_index)[ldn].cmd = cmd;	/*fill scb information independent of the scsi command */	scb = &(ld(host_index)[ldn].scb);	ld(host_index)[ldn].tsb.dev_status = 0;	scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;	scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb));	scsi_cmd = cmd->cmnd[0];	if (cmd->use_sg) {		i = cmd->use_sg;		sl = (struct scatterlist *) (cmd->request_buffer);		if (i > 16)			panic("IBM MCA SCSI: scatter-gather list too long.\n");		while (--i >= 0) {			ld(host_index)[ldn].sge[i].address = (void *) (isa_page_to_bus(sl[i].page) + sl[i].offset);			ld(host_index)[ldn].sge[i].byte_length = sl[i].length;		}		scb->enable |= IM_POINTER_TO_LIST;		scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0]));		scb->sys_buf_length = cmd->use_sg * sizeof(struct im_sge);	} else {		scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer);		/* recent Linux midlevel SCSI places 1024 byte for inquiry		 * command. Far too much for old PS/2 hardware. */		switch (scsi_cmd) {			/* avoid command errors by setting bufferlengths to			 * ANSI-standard. Beware of forcing it to 255,			 * this could SEGV the kernel!!! */		case INQUIRY:		case REQUEST_SENSE:		case MODE_SENSE:		case MODE_SELECT:			if (cmd->request_bufflen > 255)				scb->sys_buf_length = 255;			else				scb->sys_buf_length = cmd->request_bufflen;			break;		case TEST_UNIT_READY:			scb->sys_buf_length = 0;			break;		default:			scb->sys_buf_length = cmd->request_bufflen;			break;		}	}	/*fill scb information dependent on scsi command */#ifdef IM_DEBUG_CMD	printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);#endif	/* for specific device-type debugging: */#ifdef IM_DEBUG_CMD_SPEC_DEV	if (ld(host_index)[ldn].device_type == IM_DEBUG_CMD_DEVICE)		printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn);#endif	/* for possible panics store current command */	last_scsi_command(host_index)[ldn] = scsi_cmd;	last_scsi_type(host_index)[ldn] = IM_SCB;	/* update statistical info */	IBM_DS(host_index).total_accesses++;	IBM_DS(host_index).ldn_access[ldn]++;	switch (scsi_cmd) {	case READ_6:	case WRITE_6:	case READ_10:	case WRITE_10:	case READ_12:	case WRITE_12:		/* Distinguish between disk and other devices. Only disks (that are the		   most frequently accessed devices) should be supported by the		   IBM-SCSI-Subsystem commands. */		switch (ld(host_index)[ldn].device_type) {		case TYPE_DISK:	/* for harddisks enter here ... */		case TYPE_MOD:	/* ... try it also for MO-drives (send flames as */			/*     you like, if this won't work.) */			if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) {				/* read command preparations */				scb->enable |= IM_READ_CONTROL;				IBM_DS(host_index).ldn_read_access[ldn]++;	/* increase READ-access on ldn stat. */				scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT;			} else {	/* write command preparations */				IBM_DS(host_index).ldn_write_access[ldn]++;	/* increase write-count on ldn stat. */				scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT;			}			if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) {				scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) | (((unsigned) cmd->cmnd[2]) << 8) | ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16);				scb->u2.blk.count = (unsigned) cmd->cmnd[4];			} else {				scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24);				scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8);			}			last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr;			last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count;			scb->u2.blk.length = ld(host_index)[ldn].block_length;			break;			/* for other devices, enter here. Other types are not known by			   Linux! TYPE_NO_LUN is forbidden as valid device. */		case TYPE_ROM:		case TYPE_TAPE:		case TYPE_PROCESSOR:		case TYPE_WORM:		case TYPE_SCANNER:		case TYPE_MEDIUM_CHANGER:			/* If there is a sequential-device, IBM recommends to use			   IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE.			   This includes CD-ROM devices, too, due to the partial sequential			   read capabilities. */			scb->command = IM_OTHER_SCSI_CMD_CMD;			if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12)				/* enable READ */				scb->enable |= IM_READ_CONTROL;			scb->enable |= IM_BYPASS_BUFFER;			scb->u1.scsi_cmd_length = cmd->cmd_len;			memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);			last_scsi_type(host_index)[ldn] = IM_LONG_SCB;			/* Read/write on this non-disk devices is also displayworthy,			   so flash-up the LED/display. */			break;		}		break;	case INQUIRY:		IBM_DS(host_index).ldn_inquiry_access[ldn]++;		scb->command = IM_DEVICE_INQUIRY_CMD;		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;		scb->u1.log_blk_adr = 0;		break;	case TEST_UNIT_READY:		scb->command = IM_OTHER_SCSI_CMD_CMD;		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;		scb->u1.log_blk_adr = 0;		scb->u1.scsi_cmd_length = 6;		memcpy(scb->u2.scsi_command, cmd->cmnd, 6);		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;		break;	case READ_CAPACITY:		/* the length of system memory buffer must be exactly 8 bytes */		scb->command = IM_READ_CAPACITY_CMD;		scb->enable |= IM_READ_CONTROL | IM_BYPASS_BUFFER;		if (scb->sys_buf_length > 8)			scb->sys_buf_length = 8;		break;		/* Commands that need read-only-mode (system <- device): */	case REQUEST_SENSE:		scb->command = IM_REQUEST_SENSE_CMD;		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;		break;		/* Commands that need write-only-mode (system -> device): */	case MODE_SELECT:	case MODE_SELECT_10:		IBM_DS(host_index).ldn_modeselect_access[ldn]++;		scb->command = IM_OTHER_SCSI_CMD_CMD;		scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;	/*Select needs WRITE-enabled */		scb->u1.scsi_cmd_length = cmd->cmd_len;		memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;		break;		/* For other commands, read-only is useful. Most other commands are		   running without an input-data-block. */	default:		scb->command = IM_OTHER_SCSI_CMD_CMD;		scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;		scb->u1.scsi_cmd_length = cmd->cmd_len;		memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);		last_scsi_type(host_index)[ldn] = IM_LONG_SCB;		break;	}	/*issue scb command, and return */	if (++disk_rw_in_progress == 1)		PS2_DISK_LED_ON(shpnt->host_no, target);	if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) {		issue_cmd(host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);		IBM_DS(host_index).long_scbs++;	} else {		issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn);		IBM_DS(host_index).scbs++;	}	return 0;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/017560fca496f72ed9dd734ffde63ce39dfe0411/ibmmca.c/buggy/drivers/scsi/ibmmca.c