print_command(cmd->cmnd); 
__scsi_print_command(cmd->cmnd); 
create_cmd (Scsi_Cmnd *cmd) {    NCR53c7x0_local_declare();    struct Scsi_Host *host = cmd->device->host;    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)        host->hostdata[0];	    struct NCR53c7x0_cmd *tmp; 	/* NCR53c7x0_cmd structure for this command */    int datain,  		/* Number of instructions per phase */	dataout;    int data_transfer_instructions, /* Count of dynamic instructions */    	i;			/* Counter */    u32 *cmd_datain,		/* Address of datain/dataout code */	*cmd_dataout;		/* Incremented as we assemble */#ifdef notyet    unsigned char *msgptr;	/* Current byte in select message */    int msglen;			/* Length of whole select message */#endif    unsigned long flags;    u32 exp_select_indirect;	/* Used in sanity check */    NCR53c7x0_local_setup(cmd->device->host);    if (!(tmp = allocate_cmd (cmd)))	return NULL;    /*     * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd.     * We do this because NCR53c7x0_cmd may have a special cache mode     * selected to cope with lack of bus snooping, etc.     */    memcpy(tmp->cmnd, cmd->cmnd, 12);    tmp->result = cmd->result;    /*     * Decide whether we need to generate commands for DATA IN,     * DATA OUT, neither, or both based on the SCSI command      */    switch (cmd->cmnd[0]) {    /* These commands do DATA IN */    case INQUIRY:    case MODE_SENSE:    case READ_6:    case READ_10:    case READ_CAPACITY:    case REQUEST_SENSE:    case READ_BLOCK_LIMITS:    case READ_TOC:	datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;    	dataout = 0;	break;    /* These commands do DATA OUT */    case MODE_SELECT:     case WRITE_6:    case WRITE_10:#if 0	printk("scsi%d : command is ", host->host_no);	print_command(cmd->cmnd);#endif#if 0	printk ("scsi%d : %d scatter/gather segments\n", host->host_no,	    cmd->use_sg);#endif    	datain = 0;	dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;#if 0	hostdata->options |= OPTION_DEBUG_INTR;#endif	break;    /*      * These commands do no data transfer, we should force an     * interrupt if a data phase is attempted on them.     */    case TEST_UNIT_READY:    case ALLOW_MEDIUM_REMOVAL:    case START_STOP:    	datain = dataout = 0;	break;    /*     * We don't know about these commands, so generate code to handle     * both DATA IN and DATA OUT phases.  More efficient to identify them     * and add them to the above cases.     */    default:	printk("scsi%d : datain+dataout for command ", host->host_no);	print_command(cmd->cmnd);	datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;    }    /*     * New code : so that active pointers work correctly regardless     * 	of where the saved data pointer is at, we want to immediately     * 	enter the dynamic code after selection, and on a non-data     * 	phase perform a CALL to the non-data phase handler, with     * 	returns back to this address.     *     * 	If a phase mismatch is encountered in the middle of a      * 	Block MOVE instruction, we want to _leave_ that instruction     *	unchanged as the current case is, modify a temporary buffer,     *	and point the active pointer (TEMP) at that.     *     * 	Furthermore, we want to implement a saved data pointer,      * 	set by the SAVE_DATA_POINTERs message.     *     * 	So, the data transfer segments will change to      *		CALL data_transfer, WHEN NOT data phase     *		MOVE x, x, WHEN data phase     *		( repeat )     *		JUMP other_transfer     */    data_transfer_instructions = datain + dataout;    /*     * When we perform a request sense, we overwrite various things,     * including the data transfer code.  Make sure we have enough     * space to do that.     */    if (data_transfer_instructions < 2)    	data_transfer_instructions = 2;    /*     * The saved data pointer is set up so that a RESTORE POINTERS message      * will start the data transfer over at the beginning.     */    tmp->saved_data_pointer = virt_to_bus (hostdata->script) + 	hostdata->E_data_transfer;    /*     * Initialize Linux specific fields.     */    tmp->cmd = cmd;    tmp->next = NULL;    tmp->flags = 0;    tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next - 	hostdata->dsa_start;    tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start;    /*      * Calculate addresses of dynamic code to fill in DSA     */    tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end -     	hostdata->dsa_start) / sizeof(u32);    tmp->data_transfer_end = tmp->data_transfer_start +     	2 * data_transfer_instructions;    cmd_datain = datain ? tmp->data_transfer_start : NULL;    cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp->    	data_transfer_start) : NULL;    /*     * Fill in the NCR53c7x0_cmd structure as follows     * dsa, with fixed up DSA code     * datain code     * dataout code     */    /* Copy template code into dsa and perform all necessary fixups */    if (hostdata->dsa_fixup)    	hostdata->dsa_fixup(tmp);    patch_dsa_32(tmp->dsa, dsa_next, 0, 0);    /*     * XXX is this giving 53c710 access to the Scsi_Cmnd in some way?     * Do we need to change it for caching reasons?     */    patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd));    if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) {	exp_select_indirect = ((1 << cmd->device->id) << 16) |			(hostdata->sync[cmd->device->id].sxfer_sanity << 8);	if (hostdata->sync[cmd->device->id].select_indirect !=				exp_select_indirect) {	    printk ("scsi%d :  sanity check failed select_indirect=0x%x\n",		host->host_no, hostdata->sync[cmd->device->id].select_indirect);	    FATAL(host);	}    }    patch_dsa_32(tmp->dsa, dsa_select, 0,		hostdata->sync[cmd->device->id].select_indirect);    /*     * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on     * different commands; although it should be trivial to do them     * both at the same time.     */    if (hostdata->initiate_wdtr & (1 << cmd->device->id)) {	memcpy ((void *) (tmp->select + 1), (void *) wdtr_message,	    sizeof(wdtr_message));    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message));	local_irq_save(flags);	hostdata->initiate_wdtr &= ~(1 << cmd->device->id);	local_irq_restore(flags);    } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) {	memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, 	    sizeof(sdtr_message));    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message));	tmp->flags |= CMD_FLAG_SDTR;	local_irq_save(flags);	hostdata->initiate_sdtr &= ~(1 << cmd->device->id);	local_irq_restore(flags);        }#if 1    else if (!(hostdata->talked_to & (1 << cmd->device->id)) &&		!(hostdata->options & OPTION_NO_ASYNC)) {	memcpy ((void *) (tmp->select + 1), (void *) async_message, 	    sizeof(async_message));    	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message));	tmp->flags |= CMD_FLAG_SDTR;    } #endif    else     	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1);    hostdata->talked_to |= (1 << cmd->device->id);    tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? 	IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun);    patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select));    patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len);    patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd));    patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ?     	    virt_to_bus (cmd_dataout)	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer);    patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ?     	    virt_to_bus (cmd_datain) 	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer);    /*      * XXX - need to make endian aware, should use separate variables     * for both status and message bytes.     */    patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1);/*  * FIXME : these only works for little endian.  We probably want to  * 	provide message and status fields in the NCR53c7x0_cmd  *	structure, and assign them to cmd->result when we're done. */#ifdef BIG_ENDIAN    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2);    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3);#else    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1);    patch_dsa_32(tmp->dsa, dsa_status, 0, 1);    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result));#endif    patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1);    patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, 	virt_to_bus(&(hostdata->NCR53c7xx_msg_nop)));        /*     * Generate code for zero or more of the DATA IN, DATA OUT phases      * in the format      *     * CALL data_transfer, WHEN NOT phase     * MOVE first buffer length, first buffer address, WHEN phase     * ...     * MOVE last buffer length, last buffer address, WHEN phase     * JUMP other_transfer     *//*  * See if we're getting to data transfer by generating an unconditional  * interrupt. */#if 0    if (datain) {	cmd_datain[0] = 0x98080000;	cmd_datain[1] = 0x03ffd00d;	cmd_datain += 2;    }#endif/*  * XXX - I'm undecided whether all of this nonsense is faster * in the long run, or whether I should just go and implement a loop * on the NCR chip using table indirect mode? * * In any case, this is how it _must_ be done for 53c700/700-66 chips, * so this stays even when we come up with something better. * * When we're limited to 1 simultaneous command, no overlapping processing, * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M * drive. * * Not bad, not good. We'll see. */    tmp->bounce.len = 0;	/* Assume aligned buffer */    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 	cmd_dataout += 4, ++i) {	u32 vbuf = cmd->use_sg	    ? (u32)page_address(((struct scatterlist *)cmd->buffer)[i].page)+	      ((struct scatterlist *)cmd->buffer)[i].offset	    : (u32)(cmd->request_buffer);	u32 bbuf = virt_to_bus((void *)vbuf);	u32 count = cmd->use_sg ?	    ((struct scatterlist *)cmd->buffer)[i].length :	    cmd->request_bufflen;	/*	 * If we have buffers which are not aligned with 16 byte cache	 * lines, then we just hope nothing accesses the other parts of	 * those cache lines while the transfer is in progress.  That would	 * fill the cache, and subsequent reads of the dma data would pick	 * up the wrong thing.	 * XXX We need a bounce buffer to handle that correctly.	 */	if (((bbuf & 15) || (count & 15)) && (datain || dataout))	{	    /* Bounce buffer needed */	    if (cmd->use_sg)		printk ("53c7xx: Non-aligned buffer with use_sg\n");	    else if (datain && dataout)                printk ("53c7xx: Non-aligned buffer with datain && dataout\n");            else if (count > 256)		printk ("53c7xx: Non-aligned transfer > 256 bytes\n");	    else	    {		    if (datain)		    {			tmp->bounce.len = count;			tmp->bounce.addr = vbuf;			bbuf = virt_to_bus(tmp->bounce.buf);			tmp->bounce.buf[0] = 0xff;			tmp->bounce.buf[1] = 0xfe;			tmp->bounce.buf[2] = 0xfd;			tmp->bounce.buf[3] = 0xfc;	    	    }	    	    if (dataout)	    	    {			memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count);			bbuf = virt_to_bus(tmp->bounce.buf);		    }	    }	}	if (datain) {            cache_clear(virt_to_phys((void *)vbuf), count);	    /* CALL other_in, WHEN NOT DATA_IN */  	    cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | 		DCMD_TCI_IO) << 24) | 		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;	    cmd_datain[1] = virt_to_bus (hostdata->script) + 		hostdata->E_other_in;	    /* MOVE count, buf, WHEN DATA_IN */	    cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO)     	    	<< 24) | count;	    cmd_datain[3] = bbuf;#if 0	    print_insn (host, cmd_datain, "dynamic ", 1);	    print_insn (host, cmd_datain + 2, "dynamic ", 1);#endif	}	if (dataout) {            cache_push(virt_to_phys((void *)vbuf), count);	    /* CALL other_out, WHEN NOT DATA_OUT */	    cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | 		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;	    cmd_dataout[1] = virt_to_bus(hostdata->script) +     	    	hostdata->E_other_out;	    /* MOVE count, buf, WHEN DATA+OUT */	    cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) 		| count;	    cmd_dataout[3] = bbuf;#if 0	    print_insn (host, cmd_dataout, "dynamic ", 1);	    print_insn (host, cmd_dataout + 2, "dynamic ", 1);#endif	}    }    /*     * Install JUMP instructions after the data transfer routines to return     * control to the do_other_transfer routines.     */          if (datain) {	cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |    	    DBC_TCI_TRUE;	cmd_datain[1] = virt_to_bus(hostdata->script) +     	    hostdata->E_other_transfer;#if 0	print_insn (host, cmd_datain, "dynamic jump ", 1);#endif	cmd_datain += 2;     }#if 0    if (datain) {	cmd_datain[0] = 0x98080000;	cmd_datain[1] = 0x03ffdeed;	cmd_datain += 2;    }#endif    if (dataout) {	cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) |    	    DBC_TCI_TRUE;	cmd_dataout[1] = virt_to_bus(hostdata->script) +     	    hostdata->E_other_transfer;#if 0	print_insn (host, cmd_dataout, "dynamic jump ", 1);#endif	cmd_dataout += 2;    }    return tmp;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/db9dff366ba78085d0323364fadbf09bec0e77ee/53c7xx.c/buggy/drivers/scsi/53c7xx.c