⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acornscsi.c.2

📁 arm平台上的uclinux系统全部源代码
💻 2
📖 第 1 页 / 共 5 页
字号:
    /* wait for MSGIN-XFER-PAUSED */    while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0);    sbic_arm_read (host->scsi.io_port, SSR);    return message;}/* * Function: void acornscsi_message (AS_Host *host) * Purpose : Read complete message from connected target & action message * Params  : host - host connected to target */staticvoid acornscsi_message (AS_Host *host){    unsigned char message[16];    unsigned int msgidx = 0, msglen = 1;    do {	message[msgidx] = acornscsi_readmessagebyte (host);	switch (msgidx) {	case 0:	    if (message[0] == EXTENDED_MESSAGE ||		(message[0] >= 0x20 && message[0] <= 0x2f))		msglen = 2;	    break;	case 1:	    if (message[0] == EXTENDED_MESSAGE)		msglen += message[msgidx];	    break;	}	msgidx += 1;	if (msgidx < msglen) {	    sbic_arm_write (host->scsi.io_port, CMND, CMND_NEGATEACK);	    /* wait for next msg-in */	    while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0);	    sbic_arm_read (host->scsi.io_port, SSR);	}    } while (msgidx < msglen);#if (DEBUG & DEBUG_MESSAGES)    printk (KERN_DEBUG "scsi%d.%c: message in: ",	    host->host->host_no, acornscsi_target (host));    print_msg (message);    printk ("\n");#endif    if (host->scsi.phase == PHASE_RECONNECTED) {	/*	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)	 * 'Whenever a target reconnects to an initiator to continue	 *  a tagged I/O process, the SIMPLE QUEUE TAG message shall	 *  be sent immediately following the IDENTIFY message...'	 */	if (message[0] == SIMPLE_QUEUE_TAG)	    host->scsi.reconnected.tag = message[1];	if (acornscsi_reconnect_finish (host))	    host->scsi.phase = PHASE_MSGIN;    }    switch (message[0]) {    case ABORT:    case ABORT_TAG:    case COMMAND_COMPLETE:	if (host->scsi.phase != PHASE_STATUSIN)	    printk (KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",		    host->host->host_no, acornscsi_target (host));	host->scsi.phase = PHASE_DONE;	host->scsi.SCp.Message = message[0];	break;    case SAVE_POINTERS:	/*	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.20)	 * 'The SAVE DATA POINTER message is sent from a target to	 *  direct the initiator to copy the active data pointer to	 *  the saved data pointer for the current I/O process.	 */	acornscsi_dma_cleanup (host);	host->SCpnt->SCp = host->scsi.SCp;	host->SCpnt->SCp.sent_command = 0;	host->scsi.phase = PHASE_MSGIN;	break;    case RESTORE_POINTERS:	/*	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.19)	 * 'The RESTORE POINTERS message is sent from a target to	 *  direct the initiator to copy the most recently saved	 *  command, data, and status pointers for the I/O process	 *  to the corresponding active pointers.  The command and	 *  status pointers shall be restored to the beginning of	 *  the present command and status areas.'	 */	acornscsi_dma_cleanup (host);	host->scsi.SCp = host->SCpnt->SCp;	host->scsi.phase = PHASE_MSGIN;	break;    case DISCONNECT:	/*	 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 6.4.2)	 * 'On those occasions when an error or exception condition occurs	 *  and the target elects to repeat the information transfer, the	 *  target may repeat the transfer either issuing a RESTORE POINTERS	 *  message or by disconnecting without issuing a SAVE POINTERS	 *  message.  When reconnection is completed, the most recent	 *  saved pointer values are restored.'	 */	acornscsi_dma_cleanup (host);	host->scsi.phase = PHASE_DISCONNECT;	break;    case MESSAGE_REJECT:#if 0 /* this isn't needed any more */	/*	 * If we were negociating sync transfer, we don't yet know if	 * this REJECT is for the sync transfer or for the tagged queue/wide	 * transfer.  Re-initiate sync transfer negociation now, and if	 * we got a REJECT in response to SDTR, then it'll be set to DONE.	 */	if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST)	    host->device[host->SCpnt->target].sync_state = SYNC_NEGOCIATE;#endif	/*	 * If we have any messages waiting to go out, then assert ATN now	 */	if (msgqueue_msglength (&host->scsi.msgs))	    sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);	switch (host->scsi.last_message) {#ifdef SCSI2_TAG	case HEAD_OF_QUEUE_TAG:	case ORDERED_QUEUE_TAG:	case SIMPLE_QUEUE_TAG:	    /*	     * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)	     *  If a target does not implement tagged queuing and a queue tag	     *  message is received, it shall respond with a MESSAGE REJECT	     *  message and accept the I/O process as if it were untagged.	     */	    printk (KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",		    host->host->host_no, acornscsi_target (host));	    host->SCpnt->device->tagged_queue = 0;	    set_bit (host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);	    break;#endif	case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):	    /*	     * Target can't handle synchronous transfers	     */	    printk (KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",		    host->host->host_no, acornscsi_target (host));	    host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA;	    host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS;	    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);	    break;	default:	    break;	}	break;    case QUEUE_FULL:	/* TODO: target queue is full */	break;    case SIMPLE_QUEUE_TAG:	/* tag queue reconnect... message[1] = queue tag.  Print something to indicate something happened! */	printk ("scsi%d.%c: reconnect queue tag %02X\n",		host->host->host_no, acornscsi_target (host),		message[1]);	break;    case EXTENDED_MESSAGE:	switch (message[2]) {#ifdef SCSI2_SYNC	case EXTENDED_SDTR:	    if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST) {		/*		 * We requested synchronous transfers.  This isn't quite right...		 * We can only say if this succeeded if we proceed on to execute the		 * command from this message.  If we get a MESSAGE PARITY ERROR,		 * and the target retries fail, then we fallback to asynchronous mode		 */		host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED;		printk (KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",			host->host->host_no, acornscsi_target(host),			message[4], message[3] * 4);		host->device[host->SCpnt->target].sync_xfer =			calc_sync_xfer (message[3] * 4, message[4]);	    } else {		unsigned char period, length;		/*		 * Target requested synchronous transfers.  The agreement is only		 * to be in operation AFTER the target leaves message out phase.		 */		sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);		period = max (message[3], sdtr_period / 4);		length = min (message[4], sdtr_size);		msgqueue_addmsg (&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,				 EXTENDED_SDTR, period, length);		host->device[host->SCpnt->target].sync_xfer =			calc_sync_xfer (period * 4, length);	    }	    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);	    break;#else	    /* We do not accept synchronous transfers.  Respond with a	     * MESSAGE_REJECT.	     */#endif	case EXTENDED_WDTR:	    /* The WD33C93A is only 8-bit.  We respond with a MESSAGE_REJECT	     * to a wide data transfer request.	     */	default:	    sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);	    msgqueue_flush (&host->scsi.msgs);	    msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT);	    break;	}	break;#ifdef SCSI2_LINK    case LINKED_CMD_COMPLETE:    case LINKED_FLG_CMD_COMPLETE:	/*	 * We don't support linked commands yet	 */	if (0) {#if (DEBUG & DEBUG_LINK)	    printk (KERN_DEBUG "scsi%d.%c: lun %d tag %d linked command complete\n",		    host->host->host_no, acornscsi_target(host), host->SCpnt->tag);#endif	    /*	     * A linked command should only terminate with one of these messages	     * if there are more linked commands available.	     */	    if (!host->SCpnt->next_link) {		printk (KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",			instance->host_no, acornscsi_target (host), host->SCpnt->tag);		sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);		msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);	    } else {		Scsi_Cmnd *SCpnt = host->SCpnt;		acornscsi_dma_cleanup (host);		host->SCpnt = host->SCpnt->next_link;		host->SCpnt->tag = SCpnt->tag;		SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status;		SCpnt->done (SCpnt);		/* initialise host->SCpnt->SCp */	    }	    break;	}#endif    default: /* reject message */	printk (KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",		host->host->host_no, acornscsi_target (host),		message[0]);	sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);	msgqueue_flush (&host->scsi.msgs);	msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT);	host->scsi.phase = PHASE_MSGIN;	break;    }    sbic_arm_write (host->scsi.io_port, CMND, CMND_NEGATEACK);}/* * Function: int acornscsi_buildmessages (AS_Host *host) * Purpose : build the connection messages for a host * Params  : host - host to add messages to */staticvoid acornscsi_buildmessages (AS_Host *host){#if 0    /* does the device need resetting? */    if (cmd_reset) {	msgqueue_addmsg (&host->scsi.msgs, 1, BUS_DEVICE_RESET);	return;    }#endif    msgqueue_addmsg (&host->scsi.msgs, 1,		     IDENTIFY(host->device[host->SCpnt->target].disconnect_ok,			     host->SCpnt->lun));#if 0    /* does the device need the current command aborted */    if (cmd_aborted) {	acornscsi_abortcmd (host->SCpnt->tag);	return;    }#endif#ifdef SCSI2_TAG    if (host->SCpnt->tag) {	unsigned int tag_type;	if (host->SCpnt->cmnd[0] == REQUEST_SENSE ||	    host->SCpnt->cmnd[0] == TEST_UNIT_READY ||	    host->SCpnt->cmnd[0] == INQUIRY)	    tag_type = HEAD_OF_QUEUE_TAG;	else	    tag_type = SIMPLE_QUEUE_TAG;	msgqueue_addmsg (&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);    }#endif#ifdef SCSI2_SYNC    if (host->device[host->SCpnt->target].sync_state == SYNC_ASYNCHRONOUS ||	host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) {	host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED;	msgqueue_addmsg (&host->scsi.msgs, 5,			 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,			 sdtr_period / 4, sdtr_size);    }#endif}/* * Function: int acornscsi_starttransfer (AS_Host *host) * Purpose : transfer data to/from connected target * Params  : host - host to which target is connected * Returns : 0 if failure */staticint acornscsi_starttransfer (AS_Host *host){    int residual;    if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) {	printk (KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",		host->host->host_no, acornscsi_target (host));	return 0;    }    residual = host->SCpnt->request_bufflen - host->scsi.SCp.have_data_in;    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);    sbic_arm_writenext (host->scsi.io_port, residual >> 16);    sbic_arm_writenext (host->scsi.io_port, residual >> 8);    sbic_arm_writenext (host->scsi.io_port, residual);    sbic_arm_write (host->scsi.io_port, CMND, CMND_XFERINFO);    return 1;}/* ========================================================================================= * Connection & Disconnection *//* * Function : acornscsi_reconnect (AS_Host *host) * Purpose  : reconnect a previously disconnected command * Params   : host - host specific data * Remarks  : SCSI spec says: *		'The set of active pointers is restored from the set *		 of saved pointers upon reconnection of the I/O process' */staticint acornscsi_reconnect (AS_Host *host){    unsigned int target, lun, ok = 0;    target = sbic_arm_read (host->scsi.io_port, SOURCEID);    if (!(target & 8))	printk (KERN_ERR "scsi%d: invalid source id after reselection "		"- device fault?\n",		host->host->host_no);    target &= 7;    if (host->SCpnt && !host->scsi.disconnectable) {	printk (KERN_ERR "scsi%d.%d: reconnected while command in "		"progress to target %d?\n",		host->host->host_no, target, host->SCpnt->target);	host->SCpnt = NULL;    }    lun = sbic_arm_read (host->scsi.io_port, DATA) & 7;    host->scsi.reconnected.target = target;    host->scsi.reconnected.lun = lun;    host->scsi.reconnected.tag = 0;    if (host->scsi.disconnectable && host->SCpnt &&	host->SCpnt->target == target && host->SCpnt->lun == lun)	ok = 1;    if (!ok && queue_probetgtlun (&host->queues.disconnected, target, lun))	ok = 1;    ADD_STATUS(target, 0x81, host->scsi.phase, 0);    if (ok) {	host->scsi.phase = PHASE_RECONNECTED;    } else {	printk (KERN_ERR "scsi%d.%c: reselected with no command "		"to reconnect with\n",		host->host->host_no, '0' + target);	acornscsi_dumplog (host, target);	sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);	msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);	host->scsi.phase = PHASE_ABORTED;    }    sbic_arm_write (host->scsi.io_port, CMND, CMND_NEGATEACK);    return !ok;}/* * Function: int acornscsi_reconect_finish (AS_Host *host) * Purpose : finish reconnecting a command * Params  : host - host to complete * Returns : 0 if failed */staticint acornscsi_reconnect_finish (AS_Host *host){    if (host->scsi.disconnectable && host->SCpnt) {	host->scsi.disconnectable = 0;	if (host->SCpnt->target == host->scsi.reconnected.target &&	    host->SCpnt->lun	== host->scsi.reconnected.lun &&	    host->SCpnt->tag	== host->scsi.reconnected.tag) {#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))	    DBG(host->SCpnt, printk ("scsi%d.%c: reconnected",		    host->host->host_no, acornscsi_target (host)));#endif	} else {	    queue_add_cmd_tail (&host->queues.disconnected, host->SCpnt);#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -