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

📄 aha152x.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
  struct Scsi_Host *shpnt = SCpnt->host;  unsigned long flags;  Scsi_Cmnd *ptr, *prev, *next;  aha152x_reset_ports(shpnt);  /* Reset, if bus hangs */  if(TESTLO(SSTAT1, BUSFREE)) {    CLRBITS(DMACNTRL0, INTEN);#if defined(DEBUG_RESET)    if(HOSTDATA(shpnt)->debug & debug_reset) {      printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");      show_queues(shpnt);    }#endif    ptr=CURRENT_SC;    if(ptr && !ptr->device->soft_reset) {      ptr->host_scribble = NULL;      ptr->result = DID_RESET << 16;      ptr->scsi_done(CURRENT_SC);      CURRENT_SC=NULL;    }    save_flags(flags);    cli();    prev=NULL; ptr=DISCONNECTED_SC;    while(ptr) {      if(!ptr->device->soft_reset) {        if(prev)          prev->host_scribble = ptr->host_scribble;        else          DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;        next = (Scsi_Cmnd *) ptr->host_scribble;        ptr->host_scribble = NULL;        ptr->result        = DID_RESET << 16;        ptr->scsi_done(ptr);          ptr = next;       } else {        prev=ptr;        ptr = (Scsi_Cmnd *) ptr->host_scribble;      }    }    restore_flags(flags);#if defined(DEBUG_RESET)    if(HOSTDATA(shpnt)->debug & debug_reset) {      printk("commands on targets w/ soft-resets:\n");      show_queues(shpnt);    }#endif    /* RESET OUT */    SETPORT(SCSISEQ, SCSIRSTO);    do_pause(30);    SETPORT(SCSISEQ, 0);    do_pause(DELAY);    SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);    SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);    SETPORT(DMACNTRL0, INTEN);  }  return SCSI_RESET_SUCCESS;}/* * Return the "logical geometry" */int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array){  struct Scsi_Host *shpnt=disk->device->host;#if defined(DEBUG_BIOSPARAM)  if(HOSTDATA(shpnt)->debug & debug_biosparam)    printk("aha152x_biosparam: dev=%s, size=%d, ",           kdevname(dev), disk->capacity);#endif   /* try default translation */  info_array[0]=64;  info_array[1]=32;  info_array[2]=disk->capacity / (64 * 32);  /* for disks >1GB do some guessing */  if(info_array[2]>=1024) {    int info[3];    /* try to figure out the geometry from the partition table */    if(scsicam_bios_param(disk, dev, info)<0 ||       !((info[0]==64 && info[1]==32) || (info[0]==255 && info[1]==63))) {      if(EXT_TRANS) {        printk("aha152x: unable to verify geometry for disk with >1GB.\n"               "         using extended translation.\n");        info_array[0] = 255;        info_array[1] = 63;        info_array[2] = disk->capacity / (255 * 63);      } else {        printk("aha152x: unable to verify geometry for disk with >1GB.\n"               "         Using default translation. Please verify yourself.\n"               "         Perhaps you need to enable extended translation in the driver.\n"               "         See /usr/src/linux/drivers/scsi/aha152x.c for details.\n");      }    } else {      info_array[0]=info[0];      info_array[1]=info[1];      info_array[2]=info[2];            if(info[0]==255 && !EXT_TRANS) {        printk("aha152x: current partition table is using extended translation.\n"               "         using it also, although it's not explicty enabled.\n");      }    }  }#if defined(DEBUG_BIOSPARAM)  if(HOSTDATA(shpnt)->debug & debug_biosparam) {    printk("bios geometry: head=%d, sec=%d, cyl=%d\n",           info_array[0], info_array[1], info_array[2]);    printk("WARNING: check, if the bios geometry is correct.\n");  }#endif  return 0;}/* *  Internal done function */void aha152x_done(struct Scsi_Host *shpnt, int error){  unsigned long flags;  Scsi_Cmnd *done_SC;#if defined(DEBUG_DONE)  if(HOSTDATA(shpnt)->debug & debug_done) {    printk("\naha152x: done(), ");    disp_ports(shpnt);  }#endif  if(CURRENT_SC) {#if defined(DEBUG_DONE)    if(HOSTDATA(shpnt)->debug & debug_done)      printk("done(%x), ", error);#endif    save_flags(flags);    cli();    done_SC = CURRENT_SC;    CURRENT_SC = NULL;    /* turn led off, when no commands are in the driver */    HOSTDATA(shpnt)->commands--;    if(!HOSTDATA(shpnt)->commands)      SETPORT(PORTA, 0);                                  /* turn led off */#if defined(DEBUG_QUEUES)    if(HOSTDATA(shpnt)->debug & debug_queues)       printk("ok (%d), ", HOSTDATA(shpnt)->commands);#endif    restore_flags(flags);    SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);    SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);#if 0/* Why poll for the BUS FREE phase, when we have setup the interrupt!? */#if defined(DEBUG_PHASES)    if(HOSTDATA(shpnt)->debug & debug_phases)      printk("BUS FREE loop, ");#endif    while(TESTLO(SSTAT1, BUSFREE))      barrier();#if defined(DEBUG_PHASES)    if(HOSTDATA(shpnt)->debug & debug_phases)      printk("BUS FREE\n");#endif#endif    done_SC->result = error;    if(done_SC->scsi_done) {#if defined(DEBUG_DONE)      if(HOSTDATA(shpnt)->debug & debug_done)        printk("calling scsi_done, ");#endif      done_SC->scsi_done(done_SC);#if defined(DEBUG_DONE)      if(HOSTDATA(shpnt)->debug & debug_done)        printk("done returned, ");#endif    } else       panic("aha152x: current_SC->scsi_done() == NULL");  } else    aha152x_panic(shpnt, "done() called outside of command");}/* * Interrupts handler (main routine of the driver) */void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs){  struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];  unsigned int flags;  int done=0, phase;#if defined(DEBUG_RACE)  enter_driver("intr");#else#if defined(DEBUG_INTR)  if(HOSTDATA(shpnt)->debug & debug_intr)    printk("\naha152x: intr(), ");#endif#endif  if(!shpnt)    panic("aha152x: catched interrupt for unknown controller.\n");  /* no more interrupts from the controller, while we're busy.     INTEN has to be restored, when we're ready to leave     intr(). To avoid race conditions, we have to return     immediately afterwards. */  CLRBITS(DMACNTRL0, INTEN);  sti();  /* Yes, sti() really needs to be here */  /* disconnected target is trying to reconnect.     Only possible, if we have disconnected nexuses and     nothing is occupying the bus.  */  if(TESTHI(SSTAT0, SELDI) &&      DISCONNECTED_SC &&      (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection)) ) {    int identify_msg, target, i;    /* Avoid conflicts when a target reconnects       while we are trying to connect to another. */    if(CURRENT_SC) {#if defined(DEBUG_QUEUES)      if(HOSTDATA(shpnt)->debug & debug_queues)        printk("i+, ");#endif      save_flags(flags);      cli();      append_SC(&ISSUE_SC, CURRENT_SC);      CURRENT_SC=NULL;      restore_flags(flags);    }    /* disable sequences */    SETPORT(SCSISEQ, 0);    SETPORT(SSTAT0, CLRSELDI);    SETPORT(SSTAT1, CLRBUSFREE);#if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES)    if(HOSTDATA(shpnt)->debug & (debug_queues|debug_phases))      printk("reselected, ");#endif    i = GETPORT(SELID) & ~(1 << shpnt->this_id);    target=0;    if(i==0)      aha152x_panic(shpnt, "reconnecting target unknown");    for(; (i & 1)==0; target++, i>>=1)      ;#if defined(DEBUG_QUEUES)    if(HOSTDATA(shpnt)->debug & debug_queues)      printk("SELID=%02x, target=%d, ", GETPORT(SELID), target);#endif    SETPORT(SCSIID, (shpnt->this_id << OID_) | target);    SETPORT(SCSISEQ, ENRESELI);    if(TESTLO(SSTAT0, SELDI))      aha152x_panic(shpnt, "RESELI failed");    SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target]&0x7f);    SETPORT(SCSISIG, P_MSGI);    /* Get identify message */    if((i=getphase(shpnt))!=P_MSGI) {      printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);      aha152x_panic(shpnt, "unknown lun");    }    SETPORT(SCSISEQ, 0);    SETPORT(SXFRCTL0, CH1);    identify_msg = GETPORT(SCSIBUS);    if(!(identify_msg & IDENTIFY_BASE)) {      printk("target=%d, inbound message (%02x) != IDENTIFY\n",             target, identify_msg);      aha152x_panic(shpnt, "unknown lun");    }#if defined(DEBUG_QUEUES)    if(HOSTDATA(shpnt)->debug & debug_queues)      printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f);#endif    save_flags(flags);    cli();#if defined(DEBUG_QUEUES)    if(HOSTDATA(shpnt)->debug & debug_queues)      printk("d-, ");#endif    CURRENT_SC = remove_SC(&DISCONNECTED_SC, target, identify_msg & 0x3f);    if(!CURRENT_SC) {      printk("lun=%d, ", identify_msg & 0x3f);      aha152x_panic(shpnt, "no disconnected command for that lun");    }    CURRENT_SC->SCp.phase &= ~disconnected;    restore_flags(flags);    make_acklow(shpnt);    if(getphase(shpnt)!=P_MSGI) {      SETPORT(SIMODE0, 0);      SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);#if defined(DEBUG_RACE)      leave_driver("(reselected) intr");#endif      SETBITS(DMACNTRL0, INTEN);      return;    }  }    /* Check, if we aren't busy with a command */  if(!CURRENT_SC) {    /* bus is free to issue a queued command */    if(TESTHI(SSTAT1, BUSFREE) && ISSUE_SC) {      save_flags(flags);      cli();#if defined(DEBUG_QUEUES)      if(HOSTDATA(shpnt)->debug & debug_queues)        printk("i-, ");#endif      CURRENT_SC = remove_first_SC(&ISSUE_SC);      restore_flags(flags);#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))        printk("issuing command, ");#endif      CURRENT_SC->SCp.phase = in_selection;#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))        printk("selecting %d, ", CURRENT_SC->target); #endif      SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);      /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */      SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK|ENSTIMER) : ENSTIMER);      /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */      SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));      SETPORT(SIMODE1, ENSELTIMO);      /* Enable SELECTION OUT sequence */      SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);            } else {      /* No command we are busy with and no new to issue */      printk("aha152x: ignoring spurious interrupt, nothing to do\n");      if(TESTHI(DMACNTRL0, SWINT)) {        printk("aha152x: SWINT is set!  Why?\n");        CLRBITS(DMACNTRL0, SWINT);      }      show_queues(shpnt);    }#if defined(DEBUG_RACE)    leave_driver("(selecting) intr");#endif    SETBITS(DMACNTRL0, INTEN);          return;  }  /* the bus is busy with something */#if defined(DEBUG_INTR)  if(HOSTDATA(shpnt)->debug & debug_intr)    disp_ports(shpnt);#endif  /* we are waiting for the result of a selection attempt */  if(CURRENT_SC->SCp.phase & in_selection) {    if(TESTLO(SSTAT1, SELTO)) {      /* no timeout */      if(TESTHI(SSTAT0, SELDO)) {        /* clear BUS FREE interrupt */        SETPORT(SSTAT1, CLRBUSFREE);        /* Disable SELECTION OUT sequence */        CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);        /* Disable SELECTION OUT DONE interrupt */        CLRBITS(SIMODE0, ENSELDO);        CLRBITS(SIMODE1, ENSELTIMO);        if(TESTLO(SSTAT0, SELDO)) {          printk("aha152x: passing bus free condition\n");#if defined(DEBUG_RACE)          leave_driver("(passing bus free) intr");#endif          SETBITS(DMACNTRL0, INTEN);          if(CURRENT_SC->SCp.phase & aborted) {            HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;            HOSTDATA(shpnt)->abortion_complete++;          }          aha152x_done(shpnt, DID_NO_CONNECT << 16);          return;        }#if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)        if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))          printk("SELDO (SELID=%x), ", GETPORT(SELID));#endif        /* selection was done */        SETPORT(SSTAT0, CLRSELDO);#if defined(DEBUG_ABORT)        if((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted))          printk("(ABORT) target selected, ");#endif        CURRENT_SC->SCp.phase &= ~in_selection;        CURRENT_SC->SCp.phase |= in_other;        ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun));        if(!(SYNCRATE&0x80) && HOSTDATA(shpnt)->synchronous) {          ADDMSG(EXTENDED_MESSAGE);          ADDMSG(3);          ADDMSG(EXTENDED_SDTR);

⌨️ 快捷键说明

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