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

📄 sym53c416.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    printk("sym53c416: Warning: PIO Interrupt Error\n");    current_command->SCp.phase = idle;    current_command->result = DID_ERROR << 16;    spin_lock_irqsave(&io_request_lock, flags);    current_command->scsi_done(current_command);    spin_unlock_irqrestore(&io_request_lock, flags);    return;    }  if(int_reg & DIS)           /* Disconnect */    {    if(current_command->SCp.phase != message_in)      current_command->result = DID_NO_CONNECT << 16;    else      current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16);    current_command->SCp.phase = idle;    spin_lock_irqsave(&io_request_lock, flags);    current_command->scsi_done(current_command);    spin_unlock_irqrestore(&io_request_lock, flags);    return;    }  /* Now we handle SCSI phases         */  switch(status_reg & PHBITS)       /* Filter SCSI phase out of status reg */    {    case PHASE_DATA_OUT:      {      if(int_reg & BS)        {        current_command->SCp.phase = data_out;        outb(FLUSH_FIFO, base + COMMAND_REG);        sym53c416_set_transfer_counter(base, current_command->request_bufflen);        outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);        if(!current_command->use_sg)          tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);        else          {          sgcount = current_command->use_sg;          sglist = current_command->request_buffer;          while(sgcount--)            {            tot_trans += sym53c416_write(base, sglist->address, sglist->length);            sglist++;            }          }        if(tot_trans < current_command->underflow)          printk("sym53c416: Warning: underflow, wrote %d bytes, request for %d bytes\n", tot_trans, current_command->underflow);        }      break;      }    case PHASE_DATA_IN:      {      if(int_reg & BS)        {        current_command->SCp.phase = data_in;        outb(FLUSH_FIFO, base + COMMAND_REG);        sym53c416_set_transfer_counter(base, current_command->request_bufflen);        outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);        if(!current_command->use_sg)          tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);        else          {          sgcount = current_command->use_sg;          sglist = current_command->request_buffer;          while(sgcount--)            {            tot_trans += sym53c416_read(base, sglist->address, sglist->length);            sglist++;            }          }        if(tot_trans < current_command->underflow)          printk("sym53c416: Warning: underflow, read %d bytes, request for %d bytes\n", tot_trans, current_command->underflow);        }      break;      }    case PHASE_COMMAND:      {      current_command->SCp.phase = command_ph;      printk("sym53c416: Warning: Unknown interrupt in command phase\n");      break;      }    case PHASE_STATUS:      {      current_command->SCp.phase = status_ph;      outb(FLUSH_FIFO, base + COMMAND_REG);      outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG);      break;      }    case PHASE_RESERVED_1:    case PHASE_RESERVED_2:      {      printk("sym53c416: Warning: Reserved phase\n");      break;      }    case PHASE_MESSAGE_OUT:      {      current_command->SCp.phase = message_out;      outb(SET_ATN, base + COMMAND_REG);      outb(MSG_ACCEPTED, base + COMMAND_REG);      break;      }    case PHASE_MESSAGE_IN:      {      current_command->SCp.phase = message_in;      current_command->SCp.Status = inb(base + SCSI_FIFO);      current_command->SCp.Message = inb(base + SCSI_FIFO);      if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT)        outb(SET_ATN, base + COMMAND_REG);      outb(MSG_ACCEPTED, base + COMMAND_REG);      break;      }    }  }static void sym53c416_init(int base, int scsi_id)  {  outb(RESET_CHIP, base + COMMAND_REG);  outb(NOOP, base + COMMAND_REG);  outb(0x99, base + TOM); /* Time out of 250 ms */  outb(0x05, base + STP);  outb(0x00, base + SYNC_OFFSET);  outb(EPC | scsi_id, base + CONF_REG_1);  outb(FE | SCSI2 | TBPA, base + CONF_REG_2);  outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3);  outb(0x83 | EAN, base + CONF_REG_4);  outb(IE | WSE0, base + CONF_REG_5);  outb(0, base + FEATURE_EN);  }static int sym53c416_probeirq(int base, int scsi_id)  {  int irq, irqs, i;  /* Clear interrupt register */  inb(base + INT_REG);  /* Start probing for irq's */  irqs = probe_irq_on();  /* Reinit chip */  sym53c416_init(base, scsi_id);  /* Cause interrupt */  outb(NOOP, base + COMMAND_REG);  outb(ILLEGAL, base + COMMAND_REG);  outb(0x07, base + DEST_BUS_ID);  outb(0x00, base + DEST_BUS_ID);  /* Wait for interrupt to occur */  i = jiffies + 20;  while(i > jiffies && !(inb(base + STATUS_REG) & SCI))    barrier();  if(i <= jiffies) /* timed out */    return 0;  /* Get occurred irq */  irq = probe_irq_off(irqs);  sym53c416_init(base, scsi_id);  return irq;  }/* Setup: sym53c416=base,irq */void sym53c416_setup(char *str, int *ints)  {  int i;  if(host_index >= MAXHOSTS)    {    printk("sym53c416.c: Too many hosts defined\n");    }  else    {    if(ints[0] < 1 || ints[0] > 2)      {      printk("sym53c416.c: Wrong number of parameters:\n");      printk("sym53c416.c: usage: sym53c416=<base>[,<irq>]\n");      }    else      {      for(i = 0; i < host_index && i >= 0; i++)        if(hosts[i].base == ints[1])          i = -2;      if(i >= 0)        {        hosts[host_index].base = ints[1];        hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0;        host_index++;        }      }    }  }static int sym53c416_test(int base)  {  outb(RESET_CHIP, base + COMMAND_REG);  outb(NOOP, base + COMMAND_REG);  if(inb(base + COMMAND_REG) != NOOP)    return 0;  if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF)    return 0;  if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY)    return 0;  return 1;  }void sym53c416_probe(void)  {  int *base = probeaddrs;  int ints[2];  ints[0] = 1;  for(; *base; base++)    if(!check_region(*base, IO_RANGE) && sym53c416_test(*base))      {      ints[1] = *base;      sym53c416_setup(NULL, ints);      }  }int sym53c416_detect(Scsi_Host_Template *tpnt)  {  unsigned long flags;  struct Scsi_Host * shpnt = NULL;  int i;  int count;#ifdef MODULE  int ints[3];  ints[0] = 2;  if(sym53c416_base)    {    ints[1] = sym53c416_base;    ints[2] = sym53c416_irq;    sym53c416_setup(NULL, ints);    }  if(sym53c416_base_1)    {    ints[1] = sym53c416_base_1;    ints[2] = sym53c416_irq_1;    sym53c416_setup(NULL, ints);    }  if(sym53c416_base_2)    {    ints[1] = sym53c416_base_2;    ints[2] = sym53c416_irq_2;    sym53c416_setup(NULL, ints);    }  if(sym53c416_base_3)    {    ints[1] = sym53c416_base_3;    ints[2] = sym53c416_irq_3;    sym53c416_setup(NULL, ints);    }#endif  printk("sym53c416.c: %s\n", VERSION_STRING);  sym53c416_probe();  /* Now we register and set up each host adapter found... */  for(count = 0, i = 0; i < host_index; i++)    if(!sym53c416_test(hosts[i].base))      printk("No sym53c416 found at address 0x%03x\n", hosts[i].base);    else      {      if(hosts[i].irq == 0)        /* We don't have an irq yet, so we should probe for one */        if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0)          printk("irq autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base);      if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE))        {        shpnt = scsi_register(tpnt, 0);        if(shpnt==NULL)        	continue;        save_flags(flags);        cli();        /* Request for specified IRQ */        if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, NULL))          {          restore_flags(flags);          printk("Unable to assign IRQ %d\n", hosts[i].irq);          scsi_unregister(shpnt);          }        else          {          /* Inform the kernel of our IO range */          request_region(hosts[i].base, IO_RANGE, ID);          shpnt->unique_id = hosts[i].base;          shpnt->io_port = hosts[i].base;          shpnt->n_io_port = IO_RANGE;          shpnt->irq = hosts[i].irq;          shpnt->this_id = hosts[i].scsi_id;          sym53c416_init(hosts[i].base, hosts[i].scsi_id);          count++;          restore_flags(flags);          }        }      }  return count;  }const char *sym53c416_info(struct Scsi_Host *SChost)  {  int i;  int base = SChost->io_port;  int irq = SChost->irq;  int scsi_id = 0;  int rev = inb(base + TC_HIGH);  for(i = 0; i < host_index; i++)    if(hosts[i].base == base)      scsi_id = hosts[i].scsi_id;  sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow");  return info;  }int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))  {  int base;  unsigned long flags = 0;  int i;  /* Store base register as we can have more than one controller in the system */  base = SCpnt->host->io_port;  current_command = SCpnt;                  /* set current command                */  current_command->scsi_done = done;        /* set ptr to done function           */  current_command->SCp.phase = command_ph;  /* currect phase is the command phase */  current_command->SCp.Status = 0;  current_command->SCp.Message = 0;  save_flags(flags);  cli();  outb(SCpnt->target, base + DEST_BUS_ID); /* Set scsi id target        */  outb(FLUSH_FIFO, base + COMMAND_REG);    /* Flush SCSI and PIO FIFO's */  /* Write SCSI command into the SCSI fifo */  for(i = 0; i < SCpnt->cmd_len; i++)    outb(SCpnt->cmnd[i], base + SCSI_FIFO);  /* Start selection sequence */  outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG);  /* Now an interrupt will be generated which we will catch in out interrupt routine */  restore_flags(flags);  return 0;  }static void internal_done(Scsi_Cmnd *SCpnt)  {  SCpnt->SCp.Status++;  }int sym53c416_command(Scsi_Cmnd *SCpnt)  {  sym53c416_queuecommand(SCpnt, internal_done);  SCpnt->SCp.Status = 0;  while(!SCpnt->SCp.Status)    barrier();  return SCpnt->result;  }int sym53c416_abort(Scsi_Cmnd *SCpnt)  {  printk("sym53c416_abort\n");  /* We don't know how to abort for the moment */  return SCSI_ABORT_SNOOZE;  }int sym53c416_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)  {  int base;  int scsi_id = -1;  int i;  printk("sym53c416_reset\n");  base = SCpnt->host->io_port;  /* search scsi_id */  for(i = 0; i < host_index && scsi_id != -1; i++)    if(hosts[i].base == base)      scsi_id = hosts[i].scsi_id;  outb(RESET_CHIP, base + COMMAND_REG);  outb(NOOP | PIO_MODE, base + COMMAND_REG);  outb(RESET_SCSI_BUS, base + COMMAND_REG);  sym53c416_init(base, scsi_id);  return SCSI_RESET_PENDING;  }int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip)  {  int size;  size = disk->capacity;  ip[0] = 64;                         /* heads                        */  ip[1] = 32;                         /* sectors                      */  if((ip[2] = size >> 11) > 1024)     /* cylinders, test for big disk */    {    ip[0] = 255;                      /* heads                        */    ip[1] = 63;                       /* sectors                      */    ip[2] = size / (255 * 63);        /* cylinders                    */    }  return 0;  }/* Loadable module support */#ifdef MODULEMODULE_AUTHOR("Lieven Willems");MODULE_PARM(sym53c416, "1-2i");MODULE_PARM(sym53c416_1, "1-2i");MODULE_PARM(sym53c416_2, "1-2i");MODULE_PARM(sym53c416_3, "1-2i");#endifstatic Scsi_Host_Template driver_template = SYM53C416;#include "scsi_module.c"

⌨️ 快捷键说明

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