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

📄 ultrastor.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 3 页
字号:
	in_byte = inb(U14F_PRODUCT_ID(config.port_address));	if (in_byte != US14F_PRODUCT_ID_0) {#if (ULTRASTOR_DEBUG & UD_DETECT)# ifdef PORT_OVERRIDE	    printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);# else	    printk("US14F: detect: no adapter at port %03X\n", config.port_address);# endif#endif#ifdef PORT_OVERRIDE	    return FALSE;#else	    continue;#endif	}	in_byte = inb(U14F_PRODUCT_ID(config.port_address) + 1);	/* Only upper nibble is significant for Product ID 1 */	if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {#if (ULTRASTOR_DEBUG & UD_DETECT)# ifdef PORT_OVERRIDE	    printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);# else	    printk("US14F: detect: no adapter at port %03X\n", config.port_address);# endif#endif#ifdef PORT_OVERRIDE	    return FALSE;#else	    continue;#endif	}	version_byte = in_byte;#ifndef PORT_OVERRIDE	break;    }    if (i == ARRAY_SIZE(ultrastor_ports_14f)) {# if (ULTRASTOR_DEBUG & UD_DETECT)	printk("US14F: detect: no port address found!\n");# endif	return FALSE;    }#endif#if (ULTRASTOR_DEBUG & UD_DETECT)    printk("US14F: detect: adapter found at port address %03X\n",	   config.port_address);#endif    /* Set local doorbell mask to disallow bus reset unless       ultrastor_bus_reset is true.  */    outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(config.port_address));    /* All above tests passed, must be the right thing.  Get some useful       info. */    snarf_region(config.port_address, 0x0c); /* Register the I/O space that we use */    *(char *)&config_1 = inb(CONFIG(config.port_address + 0));    *(char *)&config_2 = inb(CONFIG(config.port_address + 1));    config.bios_segment = bios_segment_table[config_1.bios_segment];    config.doorbell_address = config.port_address;    config.ogm_address = config.port_address + 0x8;    config.icm_address = config.port_address + 0xC;    config.interrupt = interrupt_table_14f[config_1.interrupt];    config.ha_scsi_id = config_2.ha_scsi_id;    config.heads = mapping_table[config_2.mapping_mode].heads;    config.sectors = mapping_table[config_2.mapping_mode].sectors;    config.bios_drive_number = config_2.bios_drive_number;    config.subversion = (version_byte & 0x0F);    if (config.subversion == U34F)	config.dma_channel = 0;    else	config.dma_channel = dma_channel_table_14f[config_1.dma_channel];    if (!config.bios_segment) {#if (ULTRASTOR_DEBUG & UD_DETECT)	printk("US14F: detect: not detected.\n");#endif	return FALSE;    }    /* Final consistancy check, verify previous info. */    if (config.subversion != U34F)	if (!config.dma_channel || !(config_2.tfr_port & 0x2)) {#if (ULTRASTOR_DEBUG & UD_DETECT)	    printk("US14F: detect: consistancy check failed\n");#endif	    return FALSE;	}    /* If we were TRULY paranoid, we could issue a host adapter inquiry       command here and verify the data returned.  But frankly, I'm       exhausted! */    /* Finally!  Now I'm satisfied... */#if (ULTRASTOR_DEBUG & UD_DETECT)    printk("US14F: detect: detect succeeded\n"	   "  Port address: %03X\n"	   "  BIOS segment: %05X\n"	   "  Interrupt: %u\n"	   "  DMA channel: %u\n"	   "  H/A SCSI ID: %u\n"	   "  Subversion: %u\n",	   config.port_address, config.bios_segment, config.interrupt,	   config.dma_channel, config.ha_scsi_id, config.subversion);#endif    config.host_number = hostnum;    scsi_hosts[hostnum].this_id = config.ha_scsi_id;    scsi_hosts[hostnum].unchecked_isa_dma = (config.subversion != U34F);#if ULTRASTOR_MAX_CMDS > 1    config.mscp_free = ~0;#endif    if (request_irq(config.interrupt, ultrastor_interrupt)) {	printk("Unable to allocate IRQ%u for UltraStor controller.\n",	       config.interrupt);	return FALSE;    }    if (config.dma_channel && request_dma(config.dma_channel)) {	printk("Unable to allocate DMA channel %u for UltraStor controller.\n",	       config.dma_channel);	free_irq(config.interrupt);	return FALSE;    }    scsi_hosts[hostnum].sg_tablesize = ULTRASTOR_14F_MAX_SG;    printk("UltraStor driver version" VERSION ".  Using %d SG lists.\n",	   ULTRASTOR_14F_MAX_SG);    return TRUE;}static int ultrastor_24f_detect(int hostnum){  register int i;#if (ULTRASTOR_DEBUG & UD_DETECT)  printk("US24F: detect");#endif  /* probe each EISA slot at slot address C80 */  for (i = 1; i < 15; i++)    {      unsigned char config_1, config_2;      unsigned short addr = (i << 12) | ULTRASTOR_24F_PORT;      if (inb(addr) != US24F_PRODUCT_ID_0 &&	  inb(addr+1) != US24F_PRODUCT_ID_1 &&	  inb(addr+2) != US24F_PRODUCT_ID_2)	continue;      config.revision = inb(addr+3);      config.slot = i;      if (! (inb(addr+4) & 1))	{#if (ULTRASTOR_DEBUG & UD_DETECT)	  printk("U24F: found disabled card in slot %u\n", i);#endif	  continue;	}#if (ULTRASTOR_DEBUG & UD_DETECT)      printk("U24F: found card in slot %u\n", i);#endif      config_1 = inb(addr + 5);      config.bios_segment = bios_segment_table[config_1 & 7];      switch(config_1 >> 4)	{	case 1:	  config.interrupt = 15;	  break;	case 2:	  config.interrupt = 14;	  break;	case 4:	  config.interrupt = 11;	  break;	case 8:	  config.interrupt = 10;	  break;	default:	  printk("U24F: invalid IRQ\n");	  return FALSE;	}      if (request_irq(config.interrupt, ultrastor_interrupt))	{	  printk("Unable to allocate IRQ%u for UltraStor controller.\n",		 config.interrupt);	  return FALSE;	}      /* BIOS addr set */      /* base port set */      config.port_address = addr;      config.doorbell_address = addr + 12;      config.ogm_address = addr + 0x17;      config.icm_address = addr + 0x1C;      config_2 = inb(addr + 7);      config.ha_scsi_id = config_2 & 7;      config.heads = mapping_table[(config_2 >> 3) & 3].heads;      config.sectors = mapping_table[(config_2 >> 3) & 3].sectors;#if (ULTRASTOR_DEBUG & UD_DETECT)      printk("US24F: detect: detect succeeded\n"	     "  Port address: %03X\n"	     "  BIOS segment: %05X\n"	     "  Interrupt: %u\n"	     "  H/A SCSI ID: %u\n",	     config.port_address, config.bios_segment,	     config.interrupt, config.ha_scsi_id);#endif      config.host_number = hostnum;      scsi_hosts[hostnum].this_id = config.ha_scsi_id;      scsi_hosts[hostnum].unchecked_isa_dma = 0;      scsi_hosts[hostnum].sg_tablesize = ULTRASTOR_14F_MAX_SG;#if ULTRASTOR_MAX_CMDS > 1      config.mscp_free = ~0;#endif      /* Mark ICM and OGM free */      outb(0, addr + 0x16);      outb(0, addr + 0x1B);      /* Set local doorbell mask to disallow bus reset unless	 ultrastor_bus_reset is true.  */      outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(addr+12));      outb(0x02, SYS_DOORBELL_MASK(addr+12));      printk("UltraStor driver version " VERSION ".  Using %d SG lists.\n",	     ULTRASTOR_14F_MAX_SG);      return TRUE;    }  return FALSE;}int ultrastor_detect(int hostnum){  return ultrastor_14f_detect(hostnum) || ultrastor_24f_detect(hostnum);}const char *ultrastor_info(void){    static char buf[64];    if (config.slot)      sprintf(buf, "UltraStor 24F SCSI @ Slot %u IRQ%u\n",	      config.slot, config.interrupt);    else if (config.subversion)      sprintf(buf, "UltraStor 34F SCSI @ Port %03X BIOS %05X IRQ%u\n",	      config.port_address, (int)config.bios_segment,	      config.interrupt);    else      sprintf(buf, "UltraStor 14F SCSI @ Port %03X BIOS %05X IRQ%u DMA%u\n",	      config.port_address, (int)config.bios_segment,	      config.interrupt, config.dma_channel);    return buf;}static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt){	struct scatterlist *sl;	long transfer_length = 0;	int i, max;	sl = (struct scatterlist *) SCpnt->request_buffer;	max = SCpnt->use_sg;	for (i = 0; i < max; i++) {		mscp->sglist[i].address = (unsigned int)sl[i].address;		mscp->sglist[i].num_bytes = sl[i].length;		transfer_length += sl[i].length;	}	mscp->number_of_sg_list = max;	mscp->transfer_data = (unsigned int)mscp->sglist;	/* ??? May not be necessary.  Docs are unclear as to whether transfer	   length field is ignored or whether it should be set to the total	   number of bytes of the transfer.  */	mscp->transfer_data_length = transfer_length;}int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){    register struct mscp *my_mscp;#if ULTRASTOR_MAX_CMDS > 1    int mscp_index;#endif    unsigned int status;    int flags;    /* Next test is for debugging; "can't happen" */    if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)	panic("ultrastor_queuecommand: no free MSCP\n");    mscp_index = find_and_clear_bit_16(&config.mscp_free);    /* Has the command been aborted?  */    if (xchgb(0xff, &config.aborted[mscp_index]) != 0)      {	status = DID_ABORT << 16;	goto aborted;      }    my_mscp = &config.mscp[mscp_index];#if 1    /* This way is faster.  */    *(unsigned char *)my_mscp = OP_SCSI | (DTD_SCSI << 3);#else    my_mscp->opcode = OP_SCSI;    my_mscp->xdir = DTD_SCSI;    my_mscp->dcn = FALSE;#endif    /* Tape drives don't work properly if the cache is used.  The SCSI       READ command for a tape doesn't have a block offset, and the adapter       incorrectly assumes that all reads from the tape read the same       blocks.  Results will depend on read buffer size and other disk       activity.        ???  Which other device types should never use the cache?   */    my_mscp->ca = scsi_devices[SCpnt->index].type != TYPE_TAPE;    my_mscp->target_id = SCpnt->target;    my_mscp->ch_no = 0;    my_mscp->lun = SCpnt->lun;    if (SCpnt->use_sg) {	/* Set scatter/gather flag in SCSI command packet */	my_mscp->sg = TRUE;	build_sg_list(my_mscp, SCpnt);    } else {	/* Unset scatter/gather flag in SCSI command packet */	my_mscp->sg = FALSE;	my_mscp->transfer_data = (unsigned int)SCpnt->request_buffer;	my_mscp->transfer_data_length = SCpnt->request_bufflen;    }    my_mscp->command_link = 0;		/*???*/    my_mscp->scsi_command_link_id = 0;	/*???*/    my_mscp->length_of_sense_byte = sizeof SCpnt->sense_buffer;    my_mscp->length_of_scsi_cdbs = COMMAND_SIZE(*(unsigned char *)SCpnt->cmnd);    memcpy(my_mscp->scsi_cdbs, SCpnt->cmnd, my_mscp->length_of_scsi_cdbs);    my_mscp->adapter_status = 0;    my_mscp->target_status = 0;    my_mscp->sense_data = (unsigned int)&SCpnt->sense_buffer;    my_mscp->done = done;    my_mscp->SCint = SCpnt;    SCpnt->host_scribble = (unsigned char *)my_mscp;    /* Find free OGM slot.  On 24F, look for OGM status byte == 0.       On 14F and 34F, wait for local interrupt pending flag to clear.  */  retry:    if (config.slot)	while (inb(config.ogm_address - 1) != 0 &&	       config.aborted[mscp_index] == 0xff);    /* else??? */    while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & 	    (config.slot ? 2 : 1)) 	   && config.aborted[mscp_index] == 0xff);    /* To avoid race conditions, make the code to write to the adapter       atomic.  This simplifies the abort code.  */    save_flags(flags);    cli();    if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) &	(config.slot ? 2 : 1))      {      restore_flags(flags);      goto retry;      }    status = xchgb(0, &config.aborted[mscp_index]);    if (status != 0xff) {	restore_flags(flags);#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT)

⌨️ 快捷键说明

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