📄 aha152x.c
字号:
#if defined(AHA152X_STAT) } else { HOSTDATA(shpnt)->busfree_without_done_command++;#endif } if(ISSUE_SC) CURRENT_SC = remove_first_SC(&ISSUE_SC); DO_UNLOCK(flags); if(CURRENT_SC) {#if defined(AHA152X_STAT) action++;#endif CURRENT_SC->SCp.phase |= selecting; DPRINTK(debug_selection, DEBUG_LEAD "selecting target\n", CMDINFO(CURRENT_SC)); /* clear selection timeout */ SETPORT(SSTAT1, SELTO); SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); SETPORT(SXFRCTL1, (PARITY ? ENSPCHK : 0 ) | ENSTIMER); SETPORT(SCSISEQ, ENSELO | ENAUTOATNO | (DISCONNECTED_SC ? ENRESELI : 0)); } else {#if defined(AHA152X_STAT) HOSTDATA(shpnt)->busfree_without_new_command++;#endif SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0); }#if defined(AHA152X_STAT) if(!action) HOSTDATA(shpnt)->busfree_without_any_action++;#endif}/* * Selection done (OUT) * - queue IDENTIFY message and SDTR to selected target for message out * (ATN asserted automagically via ENAUTOATNO in busfree()) */static void seldo_run(struct Scsi_Host *shpnt){ SETPORT(SCSISIG, 0); SETPORT(SSTAT1, CLRBUSFREE); SETPORT(SSTAT1, CLRPHASECHG); CURRENT_SC->SCp.phase &= ~(selecting|not_issued); SETPORT(SCSISEQ, 0); if (TESTLO(SSTAT0, SELDO)) { printk(ERR_LEAD "aha152x: passing bus free condition\n", CMDINFO(CURRENT_SC)); done(shpnt, DID_NO_CONNECT << 16); return; } SETPORT(SSTAT0, CLRSELDO); ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->lun)); if (CURRENT_SC->SCp.phase & aborting) { ADDMSGO(ABORT); } else if (CURRENT_SC->SCp.phase & resetting) { ADDMSGO(BUS_DEVICE_RESET); } else if (SYNCNEG==0 && SYNCHRONOUS) { CURRENT_SC->SCp.phase |= syncneg; ADDMSGO(EXTENDED_MESSAGE); ADDMSGO(3); ADDMSGO(EXTENDED_SDTR); ADDMSGO(50); /* 200ns */ ADDMSGO(8); /* 8 byte req/ack offset */ SYNCNEG=1; /* negotiation in progress */ } SETRATE(SYNCRATE);}/* * Selection timeout * - return command to mid-level with failure cause * */static void selto_run(struct Scsi_Host *shpnt){ SETPORT(SCSISEQ, 0); SETPORT(SSTAT1, CLRSELTIMO); DPRINTK(debug_selection, DEBUG_LEAD "selection timeout\n", CMDINFO(CURRENT_SC)); if(!CURRENT_SC) { DPRINTK(debug_selection, DEBUG_LEAD "!CURRENT_SC\n", CMDINFO(CURRENT_SC)); return; } CURRENT_SC->SCp.phase &= ~selecting; if (CURRENT_SC->SCp.phase & aborted) { DPRINTK(debug_selection, DEBUG_LEAD "aborted\n", CMDINFO(CURRENT_SC)); done(shpnt, DID_ABORT << 16); } else if (TESTLO(SSTAT0, SELINGO)) { DPRINTK(debug_selection, DEBUG_LEAD "arbitration not won\n", CMDINFO(CURRENT_SC)); done(shpnt, DID_BUS_BUSY << 16); } else { /* ARBITRATION won, but SELECTION failed */ DPRINTK(debug_selection, DEBUG_LEAD "selection failed\n", CMDINFO(CURRENT_SC)); done(shpnt, DID_NO_CONNECT << 16); }}/* * Selection in done * - put current command back to issue queue * (reconnection of a disconnected nexus instead * of successful selection out) * */static void seldi_run(struct Scsi_Host *shpnt){ int selid; int target; unsigned long flags; SETPORT(SCSISIG, 0); SETPORT(SSTAT0, CLRSELDI); SETPORT(SSTAT1, CLRBUSFREE); SETPORT(SSTAT1, CLRPHASECHG); if(CURRENT_SC) { if(!(CURRENT_SC->SCp.phase & not_issued)) printk(ERR_LEAD "command should not have been issued yet\n", CMDINFO(CURRENT_SC)); DPRINTK(debug_selection, ERR_LEAD "command requeued - reselection\n", CMDINFO(CURRENT_SC)); DO_LOCK(flags); append_SC(&ISSUE_SC, CURRENT_SC); DO_UNLOCK(flags); CURRENT_SC = 0; } if(!DISCONNECTED_SC) { DPRINTK(debug_selection, DEBUG_LEAD "unexpected SELDI ", CMDINFO(CURRENT_SC)); return; } RECONN_TARGET=-1; selid = GETPORT(SELID) & ~(1 << shpnt->this_id); if (selid==0) { printk("aha152x%d: target id unknown (%02x)\n", HOSTNO, selid); return; } for(target=7; !(selid & (1 << target)); target--) ; if(selid & ~(1 << target)) { printk("aha152x%d: multiple targets reconnected (%02x)\n", HOSTNO, selid); } SETPORT(SCSIID, (shpnt->this_id << OID_) | target); SETPORT(SCSISEQ, 0); SETRATE(HOSTDATA(shpnt)->syncrate[target]); RECONN_TARGET=target; DPRINTK(debug_selection, DEBUG_LEAD "target %d reselected (%02x).\n", CMDINFO(CURRENT_SC), target, selid);}/* * message in phase * - handle initial message after reconnection to identify * reconnecting nexus * - queue command on DISCONNECTED_SC on DISCONNECT message * - set completed flag on COMMAND COMPLETE * (other completition code moved to busfree_run) * - handle response to SDTR * - clear synchronous transfer agreements on BUS RESET * * FIXME: what about SAVE POINTERS, RESTORE POINTERS? * */static void msgi_run(struct Scsi_Host *shpnt){ for(;;) { int sstat1 = GETPORT(SSTAT1); if(sstat1 & (PHASECHG|PHASEMIS|BUSFREE) || !(sstat1 & REQINIT)) return; if(TESTLO(SSTAT0,SPIORDY)) { DPRINTK(debug_msgi, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC)); return; } ADDMSGI(GETPORT(SCSIDAT));#if defined(AHA152X_DEBUG) if (HOSTDATA(shpnt)->debug & debug_msgi) { printk(INFO_LEAD "inbound message %02x ", CMDINFO(CURRENT_SC), MSGI(0)); print_msg(&MSGI(0)); printk("\n"); }#endif if(!CURRENT_SC) { if(LASTSTATE!=seldi) { printk(KERN_ERR "aha152x%d: message in w/o current command not after reselection\n", HOSTNO); } /* * Handle reselection */ if(!(MSGI(0) & IDENTIFY_BASE)) { printk(KERN_ERR "aha152x%d: target didn't identify after reselection\n", HOSTNO); continue; } CURRENT_SC = remove_lun_SC(&DISCONNECTED_SC, RECONN_TARGET, MSGI(0) & 0x3f); if (!CURRENT_SC) { show_queues(shpnt); printk(KERN_ERR "aha152x%d: no disconnected command for target %d/%d\n", HOSTNO, RECONN_TARGET, MSGI(0) & 0x3f); continue; } DPRINTK(debug_msgi, DEBUG_LEAD "target reconnected\n", CMDINFO(CURRENT_SC)); CURRENT_SC->SCp.Message = MSGI(0); CURRENT_SC->SCp.phase &= ~disconnected; MSGILEN=0; /* next message if any */ continue; } CURRENT_SC->SCp.Message = MSGI(0); switch (MSGI(0)) { case DISCONNECT: if (!RECONNECT) printk(WARN_LEAD "target was not allowed to disconnect\n", CMDINFO(CURRENT_SC)); CURRENT_SC->SCp.phase |= disconnected; break; case COMMAND_COMPLETE: if(CURRENT_SC->SCp.phase & completed) DPRINTK(debug_msgi, DEBUG_LEAD "again COMMAND COMPLETE\n", CMDINFO(CURRENT_SC)); CURRENT_SC->SCp.phase |= completed; break; case MESSAGE_REJECT: if (SYNCNEG==1) { printk(INFO_LEAD "Synchronous Data Transfer Request was rejected\n", CMDINFO(CURRENT_SC)); SYNCNEG=2; /* negotiation completed */ } else printk(INFO_LEAD "inbound message (MESSAGE REJECT)\n", CMDINFO(CURRENT_SC)); break; case SAVE_POINTERS: break; case RESTORE_POINTERS: break; case EXTENDED_MESSAGE: if(MSGILEN<2 || MSGILEN<MSGI(1)+2) { /* not yet completed */ continue; } switch (MSGI(2)) { case EXTENDED_SDTR: { long ticks; if (MSGI(1) != 3) { printk(ERR_LEAD "SDTR message length!=3\n", CMDINFO(CURRENT_SC)); break; } if (!HOSTDATA(shpnt)->synchronous) break; printk(INFO_LEAD, CMDINFO(CURRENT_SC)); print_msg(&MSGI(0)); printk("\n"); ticks = (MSGI(3) * 4 + 49) / 50; if (syncneg) { /* negotiation in progress */ if (ticks > 9 || MSGI(4) < 1 || MSGI(4) > 8) { ADDMSGO(MESSAGE_REJECT); printk(INFO_LEAD "received Synchronous Data Transfer Request invalid - rejected\n", CMDINFO(CURRENT_SC)); break; } SYNCRATE |= ((ticks - 2) << 4) + MSGI(4); } else if (ticks <= 9 && MSGI(4) >= 1) { ADDMSGO(EXTENDED_MESSAGE); ADDMSGO(3); ADDMSGO(EXTENDED_SDTR); if (ticks < 4) { ticks = 4; ADDMSGO(50); } else ADDMSGO(MSGI(3)); if (MSGI(4) > 8) MSGI(4) = 8; ADDMSGO(MSGI(4)); SYNCRATE |= ((ticks - 2) << 4) + MSGI(4); } else { /* requested SDTR is too slow, do it asynchronously */ printk(INFO_LEAD "Synchronous Data Transfer Request too slow - Rejecting\n", CMDINFO(CURRENT_SC)); ADDMSGO(MESSAGE_REJECT); } SYNCNEG=2; /* negotiation completed */ SETRATE(SYNCRATE); } break; case BUS_DEVICE_RESET: { int i; for(i=0; i<8; i++) { HOSTDATA(shpnt)->syncrate[i]=0; HOSTDATA(shpnt)->syncneg[i]=0; } } break; case EXTENDED_MODIFY_DATA_POINTER: case EXTENDED_EXTENDED_IDENTIFY: case EXTENDED_WDTR: default: ADDMSGO(MESSAGE_REJECT); break; } break; } MSGILEN=0; }}static void msgi_end(struct Scsi_Host *shpnt){ if(MSGILEN>0) printk(WARN_LEAD "target left before message completed (%d)\n", CMDINFO(CURRENT_SC), MSGILEN); if (MSGOLEN > 0 && !(GETPORT(SSTAT1) & BUSFREE)) { DPRINTK(debug_msgi, DEBUG_LEAD "msgo pending\n", CMDINFO(CURRENT_SC)); SETPORT(SCSISIG, P_MSGI | SIG_ATNO); } }/* * message out phase * */static void msgo_init(struct Scsi_Host *shpnt){ if(MSGOLEN==0) { if((CURRENT_SC->SCp.phase & syncneg) && SYNCNEG==2 && SYNCRATE==0) { ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->lun)); } else { printk(INFO_LEAD "unexpected MESSAGE OUT phase; rejecting\n", CMDINFO(CURRENT_SC)); ADDMSGO(MESSAGE_REJECT); } }#if defined(AHA152X_DEBUG) if(HOSTDATA(shpnt)->debug & debug_msgo) { int i; printk(DEBUG_LEAD "messages( ", CMDINFO(CURRENT_SC)); for (i=0; i<MSGOLEN; i+=print_msg(&MSGO(i)), printk(" ")) ; printk(")\n"); }#endif}/* * message out phase * */static void msgo_run(struct Scsi_Host *shpnt){ if(MSGO_I==MSGOLEN) DPRINTK(debug_msgo, DEBUG_LEAD "messages all sent (%d/%d)\n", CMDINFO(CURRENT_SC), MSGO_I, MSGOLEN); while(MSGO_I<MSGOLEN) { DPRINTK(debug_msgo, DEBUG_LEAD "message byte %02x (%d/%d)\n", CMDINFO(CURRENT_SC), MSGO(MSGO_I), MSGO_I, MSGOLEN); if(TESTLO(SSTAT0, SPIORDY)) { DPRINTK(debug_msgo, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC)); return; } if (MSGO_I==MSGOLEN-1) { /* Leave MESSAGE OUT after transfer */ SETPORT(SSTAT1, CLRATNO); } if (MSGO(MSGO_I) & IDENTIFY_BASE) CURRENT_SC->SCp.phase |= identified; if (MSGO(MSGO_I)==ABORT) CURRENT_SC->SCp.phase |= aborted; if (MSGO(MSGO_I)==BUS_DEVICE_RESET) CURRENT_SC->SCp.phase |= resetted; SETPORT(SCSIDAT, MSGO(MSGO_I++)); }}static void msgo_end(struct Scsi_Host *shpnt){ if(MSGO_I<MSGOLEN) { printk(ERR_LEAD "message sent incompletely (%d/%d)\n", CMDINFO(CURRENT_SC), MSGO_I, MSGOLEN); if(SYNCNEG==1) { printk(INFO_LEAD "Synchronous Data Transfer Request was rejected\n", CMDINFO(CURRENT_SC)); SYNCNEG=2; } } MSGO_I = 0; MSGOLEN = 0;}/* * command phase * */static void cmd_init(struct Scsi_Host *shpnt){ if (CURRENT_SC->SCp.sent_command) { printk(ERR_LEAD "command already sent\n", CMDINFO(CURRENT_SC)); done(shpnt, DID_ERROR << 16); return; }#if defined(AHA152X_DEBUG) if (HOSTDATA(shpnt)->debug & debug_cmd) { printk(DEBUG_LEAD "cmd_init: ", CMDINFO(CURRENT_SC)); print_command(CURRENT_SC->cmnd); }#endif CMD_I=0;}/* * command phase * */static void cmd_run(struct Scsi_Host *shpnt){ if(CMD_I==CURRENT_SC->cmd_len) { DPRINTK(debug_cmd, DEBUG_LEAD "command already completely sent (%d/%d)", CMDINFO(CURRENT_SC), CMD_I, CURRENT_SC->cmd_len); disp_ports(shpnt); } while(CMD_I<CURRENT_SC->cmd_len) { DPRINTK(debug_cmd, DEBUG_LEAD "command byte %02x (%d/%d)\n", CMDINFO(CURRENT_SC), CURRENT_SC->cmnd[CMD_I], CMD_I, CURRENT_SC->cmd_len); if(TESTLO(SSTAT0, SPIORDY)) { DPRINTK(debug_cmd, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC)); return; } SETPORT(SCSIDAT, CURRENT_SC->cmnd[CMD_I++]); }}static void cmd_end(struct Scsi_Host *shpnt){ if(CMD_I<CURRENT_SC->cmd_len) printk(ERR_LEAD "command sent incompletely (%d/%d)\n", CMDINFO(CURRENT_SC), CMD_I, CURRENT_SC->cmd_len); else CURRENT_SC->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -