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

📄 am53c974.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
hostdata->disconnecting = 0;hostdata->dma_busy = 0;hostdata->busy[cmd->target] &= ~(1 << cmd->lun);AM53C974_write_8(CMDREG, CMDREG_CFIFO);DEB(printk("disconnect; issue_queue: 0x%lx, disconnected_queue: 0x%lx\n",        (long)hostdata->issue_queue, (long)hostdata->disconnected_queue));cmd->scsi_done(cmd);if (!hostdata->selecting) {   AM53C974_set_async(instance, cmd->target);    AM53C974_write_8(CMDREG, CMDREG_ESR); } /* allow reselect */return;EXIT_UNFINISHED:hostdata->msgout[0] = NOP;hostdata->sel_cmd = NULL;hostdata->connected = NULL;hostdata->aborted = 0;hostdata->selecting = 0;hostdata->disconnecting = 0;hostdata->dma_busy = 0;DEB(printk("disconnect; issue_queue: 0x%lx, disconnected_queue: 0x%lx\n",        (long)hostdata->issue_queue, (long)hostdata->disconnected_queue));if (!hostdata->selecting) {   AM53C974_set_async(instance, cmd->target);    AM53C974_write_8(CMDREG, CMDREG_ESR); } /* allow reselect */return;}/************************************************************************** * Function : int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg)** Purpose : setup message string for sync. negotiation** Inputs : instance -- which AM53C974*          target -- which SCSI target to deal with*          msg -- input message string* * Returns : 0 if parameters accepted or 1 if not accepted** Side effects: hostdata is changed** Note: we assume here that fastclk is enabled**************************************************************************/static int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg) {AM53C974_local_declare(); struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;int                      period, offset, i, rate, rate_rem;AM53C974_setio(instance);period = (DEF_CLK * msg[3] * 8 + 1000) / 2000;if (period < MIN_PERIOD) {    period = MIN_PERIOD;    hostdata->msgout[3] = period / 4; }   else    if (period > MAX_PERIOD) {       period = MAX_PERIOD;       hostdata->msgout[3] = period / 4; }      else       hostdata->msgout[3] = msg[3];offset = msg[4]; if (offset > MAX_OFFSET) offset = MAX_OFFSET;hostdata->msgout[4] = offset;hostdata->sync_per[target] = period;hostdata->sync_off[target] = offset;for (i = 0; i < 3; i++) hostdata->msgout[i] = msg[i];if ((hostdata->msgout[3] != msg[3]) || (msg[4] != offset)) return(1);rate = DEF_CLK / period;rate_rem = 10 * (DEF_CLK - period * rate) / period;if (offset)   printk("\ntarget %d: rate=%d.%d Mhz, synchronous, sync offset=%d bytes\n",          target, rate, rate_rem, offset);  else   printk("\ntarget %d: rate=%d.%d Mhz, asynchronous\n", target, rate, rate_rem);return(0);}/************************************************************************** * Function : AM53C974_set_async(struct Scsi_Host *instance, int target)** Purpose : put controller into async. mode** Inputs : instance -- which AM53C974*          target -- which SCSI target to deal with* * Returns : nothing**************************************************************************/static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target){AM53C974_local_declare(); struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;AM53C974_setio(instance);AM53C974_write_8(STPREG, hostdata->sync_per[target]);AM53C974_write_8(SOFREG, (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4));}/************************************************************************** * Function : AM53C974_set_sync(struct Scsi_Host *instance, int target)** Purpose : put controller into sync. mode** Inputs : instance -- which AM53C974*          target -- which SCSI target to deal with* * Returns : nothing**************************************************************************/static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target){AM53C974_local_declare(); struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;AM53C974_setio(instance);AM53C974_write_8(STPREG, hostdata->sync_per[target]);AM53C974_write_8(SOFREG, (SOFREG_SO & hostdata->sync_off[target]) |                 (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4));}/************************************************************************ Function : AM53C974_information_transfer(struct Scsi_Host *instance, **                          unsigned char statreg, unsigned char isreg, **                         unsigned char instreg, unsigned char cfifo,  **                         unsigned char dmastatus)                     **                                                                      ** Purpose : handle phase changes                                       **                                                                      ** Inputs : instance - which AM53C974                                   **          statreg - status register                                     **          isreg - internal state register                             **          instreg - interrupt status register                         **          cfifo - number of bytes in FIFO                             **          dmastatus - dma status register                             **                                                                      ** Returns : nothing                                                    *************************************************************************/static void AM53C974_information_transfer(struct Scsi_Host *instance,                                           unsigned char statreg, unsigned char isreg,                                          unsigned char instreg, unsigned char cfifo,                                          unsigned char dmastatus){AM53C974_local_declare(); struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;Scsi_Cmnd                *cmd = (Scsi_Cmnd *)hostdata->connected;int                      ret, i, len, residual=-1;AM53C974_setio(instance);DEB_INFO(printk(SEPARATOR_LINE));switch (statreg & STATREG_PHASE) {	/* scsi phase */  case PHASE_DATAOUT:    DEB_INFO(printk("Dataout phase; cmd=0x%lx, sel_cmd=0x%lx, this_residual=%d, buffers_residual=%d\n",                    (long)hostdata->connected, (long)hostdata->sel_cmd, cmd->SCp.this_residual, cmd->SCp.buffers_residual));    cmd->SCp.phase = PHASE_DATAOUT;    goto PHASE_DATA_IO;  case PHASE_DATAIN:    DEB_INFO(printk("Datain phase; cmd=0x%lx, sel_cmd=0x%lx, this_residual=%d, buffers_residual=%d\n",                     (long)hostdata->connected, (long)hostdata->sel_cmd, cmd->SCp.this_residual, cmd->SCp.buffers_residual));    cmd->SCp.phase = PHASE_DATAIN;    PHASE_DATA_IO:    if (hostdata->aborted) {       AM53C974_write_8(DMACMD, DMACMD_IDLE);       AM53C974_write_8(CMDREG, CMDREG_CFIFO);       AM53C974_write_8(CMDREG, CMDREG_SATN);       return; }    if ((!cmd->SCp.this_residual) && cmd->SCp.buffers_residual) {       cmd->SCp.buffer++;       cmd->SCp.buffers_residual--;       cmd->SCp.ptr = (unsigned char *)cmd->SCp.buffer->address;       cmd->SCp.this_residual = cmd->SCp.buffer->length; }    if (cmd->SCp.this_residual) {       if (!(AM53C974_read_8(DMACMD) & DMACMD_START)) {          hostdata->dma_busy = 0;          AM53C974_transfer_dma(instance, statreg & STATREG_IO,                                (unsigned long)cmd->SCp.this_residual,                                cmd->SCp.ptr); }         else          hostdata->dma_busy = 1;       }    return;  case PHASE_MSGIN:    DEB_INFO(printk("Message-In phase; cmd=0x%lx, sel_cmd=0x%lx\n",                    (long)hostdata->connected, (long)hostdata->sel_cmd));    AM53C974_set_async(instance, cmd->target);    if (cmd->SCp.phase == PHASE_DATAIN)       AM53C974_dma_blast(instance, dmastatus, statreg);    if ((cmd->SCp.phase == PHASE_DATAOUT) && (AM53C974_read_8(DMACMD) & DMACMD_START)) {       AM53C974_write_8(DMACMD, DMACMD_IDLE);       residual = cfifo + (AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) |                          (AM53C974_read_8(CTCHREG) << 16));       cmd->SCp.ptr += cmd->SCp.this_residual - residual;       cmd->SCp.this_residual = residual;       if (cfifo) { AM53C974_write_8(CMDREG, CMDREG_CFIFO); cfifo = 0; }       }    if (cmd->SCp.phase == PHASE_STATIN) {       while ((AM53C974_read_8(CFIREG) & CFIREG_CF) < 2) ;       cmd->SCp.Status = AM53C974_read_8(FFREG);       cmd->SCp.Message = AM53C974_read_8(FFREG);        DEB_INFO(printk("Message-In phase; status=0x%02x, message=0x%02x\n",                       cmd->SCp.Status, cmd->SCp.Message));       ret = AM53C974_message(instance, cmd, cmd->SCp.Message); }      else {       if (!cfifo) {          AM53C974_write_8(CMDREG, CMDREG_IT);           AM53C974_poll_int();          cmd->SCp.Message = AM53C974_read_8(FFREG);          }       ret = AM53C974_message(instance, cmd, cmd->SCp.Message);       }    cmd->SCp.phase = PHASE_MSGIN;    AM53C974_set_sync(instance, cmd->target);    break;  case PHASE_MSGOUT:    DEB_INFO(printk("Message-Out phase; cfifo=%d; msgout[0]=0x%02x\n",                    AM53C974_read_8(CFIREG) & CFIREG_CF, hostdata->msgout[0]));    AM53C974_write_8(DMACMD, DMACMD_IDLE);    AM53C974_set_async(instance, cmd->target);    for (i = 0; i < sizeof(hostdata->last_message); i++)         hostdata->last_message[i] = hostdata->msgout[i];    if ((hostdata->msgout[0] == 0) || INSIDE(hostdata->msgout[0], 0x02, 0x1F) ||         INSIDE(hostdata->msgout[0], 0x80, 0xFF))        len = 1;      else {       if (hostdata->msgout[0] == EXTENDED_MESSAGE) {#ifdef AM53C974_DEBUG_INFO          printk("Extended message dump:\n");          for (i = 0; i < hostdata->msgout[1] + 2; i++) {              printk("%02x ", hostdata->msgout[i]);              if (i && !(i % 16)) printk("\n"); }          printk("\n");#endif          len = hostdata->msgout[1] + 2; }         else          len = 2;       }    for (i = 0; i < len; i++) AM53C974_write_8(FFREG, hostdata->msgout[i]);    AM53C974_write_8(CMDREG, CMDREG_IT);    cmd->SCp.phase = PHASE_MSGOUT;    hostdata->msgout[0] = NOP;    AM53C974_set_sync(instance, cmd->target);    break;  case PHASE_CMDOUT:    DEB_INFO(printk("Command-Out phase\n"));    AM53C974_set_async(instance, cmd->target);    for (i = 0; i < cmd->cmd_len; i++) AM53C974_write_8(FFREG, cmd->cmnd[i]);    AM53C974_write_8(CMDREG, CMDREG_IT);    cmd->SCp.phase = PHASE_CMDOUT;    AM53C974_set_sync(instance, cmd->target);    break;  case PHASE_STATIN:    DEB_INFO(printk("Status phase\n"));    if (cmd->SCp.phase == PHASE_DATAIN)       AM53C974_dma_blast(instance, dmastatus, statreg);    AM53C974_set_async(instance, cmd->target);    if (cmd->SCp.phase == PHASE_DATAOUT) {       unsigned long residual;       if (AM53C974_read_8(DMACMD) & DMACMD_START) {          AM53C974_write_8(DMACMD, DMACMD_IDLE);          residual = cfifo + (AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) |                              (AM53C974_read_8(CTCHREG) << 16));          cmd->SCp.ptr += cmd->SCp.this_residual - residual;          cmd->SCp.this_residual = residual; }       if (cfifo) { AM53C974_write_8(CMDREG, CMDREG_CFIFO); cfifo = 0; }       }    cmd->SCp.phase = PHASE_STATIN;    AM53C974_write_8(CMDREG, CMDREG_ICCS);  /* command complete */    break;  case PHASE_RES_0:  case PHASE_RES_1:#ifdef AM53C974_DEBUG   deb_stop = 1;#endif    DEB_INFO(printk("Reserved phase\n"));    break;  }KEYWAIT();}/******************************************************************************* Function : int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd,*                                 unsigned char msg)                ** Purpose : handle SCSI messages** Inputs : instance -- which AM53C974*          cmd -- SCSI command the message belongs to*          msg -- message id byte* * Returns : 1 on success, 0 on failure.**************************************************************************/static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd,                            unsigned char msg){AM53C974_local_declare(); static unsigned char     extended_msg[10];unsigned char            statreg;int                      len, ret = 0;unsigned char            *p;#ifdef AM53C974_DEBUG_MSGint                      j;#endifstruct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;AM53C974_setio(instance);DEB_MSG(printk(SEPARATOR_LINE));/* Linking lets us reduce the time required to get the  * next command out to the device, hopefully this will * mean we don't waste another revolution due to the delays * required by ARBITRATION and another SELECTION. * In the current implementation proposal, low level drivers * merely have to start the next command, pointed to by  *

⌨️ 快捷键说明

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