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

📄 am53c974.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
   printk ("AM53C974: probe only enabled, aborting initialization\n");   return 0;#endifinstance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata));hostdata = (struct AM53C974_hostdata *)instance->hostdata;instance->base = NULL;instance->io_port = pci_config._base0 & (pci_config._base0 & 0x1 ?                                          0xFFFFFFFC : 0xFFFFFFF0);instance->irq = pci_config._int_line;instance->dma_channel = -1;AM53C974_setio(instance);#ifdef AM53C974_SCSI_IDinstance->this_id = AM53C974_SCSI_ID;AM53C974_write_8(CNTLREG1, instance->this_id & CNTLREG1_SID);#elseinstance->this_id = AM53C974_read_8(CNTLREG1) & CNTLREG1_SID;if (instance->this_id != 7)    printk("scsi%d: WARNING: unusual hostadapter SCSI id %d; please verify!\n",           instance->host_no, instance->this_id);#endiffor (i = 0; i < sizeof(hostdata->msgout); i++) {    hostdata->msgout[i] = NOP;    hostdata->last_message[i] = NOP; }for (i = 0; i < 8; i++) {    hostdata->busy[i] = 0;    hostdata->sync_per[i] = DEF_STP;    hostdata->sync_off[i] = 0;    hostdata->sync_neg[i] = 0;    hostdata->sync_en[i] = DEFAULT_SYNC_NEGOTIATION_ENABLED;    hostdata->max_rate[i] = DEFAULT_RATE;    hostdata->max_offset[i] = DEFAULT_SYNC_OFFSET; }/* overwrite defaults by LILO overrides */for (i = 0; i < commandline_current; i++) {    if (overrides[i].host_scsi_id == instance->this_id) {       j = overrides[i].target_scsi_id;       hostdata->sync_en[j] = 1;       hostdata->max_rate[j] = overrides[i].max_rate;       hostdata->max_offset[j] = overrides[i].max_offset;        }    }hostdata->sel_cmd = NULL;hostdata->connected = NULL;hostdata->issue_queue = NULL;hostdata->disconnected_queue = NULL;hostdata->in_reset = 0;hostdata->aborted = 0;hostdata->selecting = 0;hostdata->disconnecting = 0;hostdata->dma_busy = 0;/* Set up an interrupt handler if we aren't already sharing an IRQ with another board */for (search = first_host;      search && ( ((the_template != NULL) && (search->hostt != the_template)) ||                  (search->irq != instance->irq) || (search == instance) );     search = search->next);if (!search) {   if (request_irq(instance->irq, AM53C974_intr, SA_INTERRUPT, "AM53C974", NULL)) {      printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq);      scsi_unregister(instance);      return 0; }    }  else {   printk("scsi%d: using interrupt handler previously installed for scsi%d\n",	  instance->host_no, search->host_no); }if (!the_template) {   the_template = instance->hostt;   first_instance = instance; }/* do hard reset */AM53C974_write_8(CMDREG, CMDREG_RDEV);     /* reset device */udelay(5);AM53C974_write_8(CMDREG, CMDREG_NOP);AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id); AM53C974_write_8(CMDREG, CMDREG_RBUS);     /* reset SCSI bus */udelay(10);AM53C974_config_after_reset(instance);udelay(500000);return(1);}/********************************************************************** Function : AM53C974_config_after_reset(struct Scsi_Host *instance) **                                                                    ** Purpose : initializes chip registers after reset                   **                                                                    ** Inputs : instance - which AM53C974                                 **                                                                    ** Returns : nothing                                                  ***********************************************************************/static void AM53C974_config_after_reset(struct Scsi_Host *instance){AM53C974_local_declare(); AM53C974_setio(instance);/* clear SCSI FIFO */AM53C974_write_8(CMDREG, CMDREG_CFIFO);/* configure device */AM53C974_write_8(STIMREG, DEF_SCSI_TIMEOUT);AM53C974_write_8(STPREG, DEF_STP & STPREG_STP);AM53C974_write_8(SOFREG, (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4));AM53C974_write_8(CLKFREG, DEF_CLKF & CLKFREG_MASK);AM53C974_write_8(CNTLREG1, (DEF_ETM<<7) | CNTLREG1_DISR | (DEF_PERE<<4) | instance->this_id);AM53C974_write_8(CNTLREG2, (DEF_ENF<<6));AM53C974_write_8(CNTLREG3, (DEF_ADIDCHK<<7) | (DEF_FASTSCSI<<4) | (DEF_FASTCLK<<3));AM53C974_write_8(CNTLREG4, (DEF_GLITCH<<6) | (DEF_PWD<<5) | (DEF_RAE<<3) | (DEF_RADE<<2) | CNTLREG4_RES);}/************************************************************************ Function : const char *AM53C974_info(struct Scsi_Host *instance)     **                                                                      ** Purpose : return device driver information                           **                                                                      ** Inputs : instance - which AM53C974                                   **                                                                      ** Returns : info string                                                *************************************************************************/const char *AM53C974_info(struct Scsi_Host *instance){static char       info[100];sprintf(info, "AM53/79C974 PCscsi driver rev. %d.%d; host I/O address: 0x%x; irq: %d\n",         AM53C974_DRIVER_REVISION_MAJOR, AM53C974_DRIVER_REVISION_MINOR,        instance->io_port, instance->irq);return (info);}/************************************************************************** * Function : int AM53C974_command (Scsi_Cmnd *SCpnt)                      **                                                                         ** Purpose : the unqueued SCSI command function, replaced by the           **           AM53C974_queue_command function                               **                                                                         ** Inputs : SCpnt - pointer to command structure                           **                                                                         ** Returns :status, see hosts.h for details                                ****************************************************************************/int AM53C974_command(Scsi_Cmnd *SCpnt){DEB(printk("AM53C974_command called\n"));return 0;}/*************************************************************************** Function : void initialize_SCp(Scsi_Cmnd *cmd)                          **                                                                         ** Purpose : initialize the saved data pointers for cmd to point to the    **	    start of the buffer.                                          *                              *                                                                         ** Inputs : cmd - Scsi_Cmnd structure to have pointers reset.              **                                                                         ** Returns : nothing                                                       ***************************************************************************/static __inline__ void initialize_SCp(Scsi_Cmnd *cmd){if (cmd->use_sg) {   cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;   cmd->SCp.buffers_residual = cmd->use_sg - 1;   cmd->SCp.ptr = (char *)cmd->SCp.buffer->address;   cmd->SCp.this_residual = cmd->SCp.buffer->length; }  else {   cmd->SCp.buffer = NULL;   cmd->SCp.buffers_residual = 0;   cmd->SCp.ptr = (char *)cmd->request_buffer;   cmd->SCp.this_residual = cmd->request_bufflen; }}/*************************************************************************** Function : run_main(void)                                               **                                                                         ** Purpose : insure that the coroutine is running and will process our     ** 	    request.  main_running is checked/set here (in an inline      **           function rather than in AM53C974_main itself to reduce the    **           chances of stack overflow.                                    **                                                                         **                                                                         ** Inputs : none                                                           **                                                                         ** Returns : nothing                                                       ***************************************************************************/static __inline__ void run_main(void){cli();if (!main_running) {   /* main_running is cleared in AM53C974_main once it can't do       more work, and AM53C974_main exits with interrupts disabled. */   main_running = 1;   AM53C974_main();   sti(); }  else    sti();}/************************************************************************** * Function : int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))** Purpose : writes SCSI command into AM53C974 FIFO ** Inputs : cmd - SCSI command, done - function called on completion, with*	a pointer to the command descriptor.* * Returns : status, see hosts.h for details** Side effects : *      cmd is added to the per instance issue_queue, with minor *	twiddling done to the host specific fields of cmd.  If the *	main coroutine is not running, it is restarted.**************************************************************************/int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)){struct Scsi_Host         *instance = cmd->host;struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;Scsi_Cmnd                *tmp;cli();DEB_QUEUE(printk(SEPARATOR_LINE));DEB_QUEUE(printk("scsi%d: AM53C974_queue_command called\n", instance->host_no));DEB_QUEUE(printk("cmd=%02x target=%02x lun=%02x bufflen=%d use_sg = %02x\n", 	   cmd->cmnd[0], cmd->target, cmd->lun, cmd->request_bufflen, cmd->use_sg));/* We use the host_scribble field as a pointer to the next command in a queue */cmd->host_scribble = NULL;cmd->scsi_done = done;cmd->result = 0;cmd->device->disconnect = 0;/* Insert the cmd into the issue queue. Note that REQUEST SENSE  * commands are added to the head of the queue since any command will * clear the contingent allegiance condition that exists and the  * sense data is only guaranteed to be valid while the condition exists. */if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {   LIST(cmd, hostdata->issue_queue);   cmd->host_scribble = (unsigned char *)hostdata->issue_queue;   hostdata->issue_queue = cmd; }  else {   for (tmp = (Scsi_Cmnd *)hostdata->issue_queue; tmp->host_scribble; 	tmp = (Scsi_Cmnd *)tmp->host_scribble);   LIST(cmd, tmp);   tmp->host_scribble = (unsigned char *)cmd; }DEB_QUEUE(printk("scsi%d : command added to %s of queue\n", instance->host_no,	  (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));/* Run the coroutine if it isn't already running. */run_main();return 0;}/************************************************************************** * Function : AM53C974_main (void)  * * Purpose : AM53C974_main is a coroutine that runs as long as more work can  *	be done on the AM53C974 host adapters in a system.  Both  *	AM53C974_queue_command() and AM53C974_intr() will try to start it  *	in case it is not running. *  * NOTE : AM53C974_main exits with interrupts *disabled*, the caller should  *  reenable them.  This prevents reentrancy and kernel stack overflow. **************************************************************************/  static void AM53C974_main(void){AM53C974_local_declare(); Scsi_Cmnd                *tmp, *prev;struct Scsi_Host         *instance;struct AM53C974_hostdata *hostdata;int                      done;/* We run (with interrupts disabled) until we're sure that none of  * the host adapters have anything that can be done, at which point  * we set main_running to 0 and exit. */do {   cli(); /* Freeze request queues */   done = 1;   for (instance = first_instance; instance && instance->hostt == the_template;        instance = instance->next) {       hostdata = (struct AM53C974_hostdata *)instance->hostdata;       AM53C974_setio(instance);       /* start to select target if we are not connected and not in the           selection process */       if (!hostdata->connected && !hostdata->sel_cmd) {          /* Search through the issue_queue for a command destined for a target              that is not busy. */          for (tmp = (Scsi_Cmnd *)hostdata->issue_queue, prev = NULL; tmp;                prev = tmp, tmp = (Scsi_Cmnd *)tmp->host_scribble) {	      /*  When we find one, remove it from the issue queue. */	      if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {		 if (prev) {		    REMOVE(prev, (Scsi_Cmnd *)(prev->host_scribble), tmp,                           (Scsi_Cmnd *)(tmp->host_scribble));		    prev->host_scribble = tmp->host_scribble; }                    else {		    REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble);		    hostdata->issue_queue = (Scsi_Cmnd *)tmp->host_scribble; }		 tmp->host_scribble = NULL;                 /* go into selection mode, disable reselection and wait for                    SO interrupt which will continue with the selection process */                 hostdata->selecting = 1;                 hostdata->sel_cmd = tmp;                 AM53C974_write_8(CMDREG, CMDREG_DSR);                  break;                 		 } /* if target/lun is not busy */	      } /* for */          } /* if (!hostdata->connected) */         else {		          DEB(printk("main: connected; cmd = 0x%lx, sel_cmd = 0x%lx\n",                 (long)hostdata->connected, (long)hostdata->sel_cmd));	  }       } /* for instance */   } while (!done);main_running = 0;}/************************************************************************* Function : AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) **                                                                       *

⌨️ 快捷键说明

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