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

📄 eata_pio.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (success) { /* hmmm... */	DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n"));	DBG(DBG_ABNORM && DBG_DELAY, DELAY(1));	return (SCSI_RESET_SUCCESS);    } else {	DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n"));	DBG(DBG_ABNORM && DBG_DELAY, DELAY(1));	return (SCSI_RESET_PUNT);    }}char * get_pio_board_data(ulong base, uint irq, uint id, ulong cplen, ushort cppadlen){    struct eata_ccb cp;    static char buff[256];    int z;        memset(&cp, 0, sizeof(struct eata_ccb));    memset(buff, 0, sizeof(buff));        cp.DataIn = TRUE;         cp.Interpret = TRUE;   /* Interpret command */        cp.cp_datalen = htonl(254);      cp.cp_dataDMA = htonl(0);        cp.cp_id = id;    cp.cp_lun = 0;        cp.cp_cdb[0] = INQUIRY;    cp.cp_cdb[1] = 0;    cp.cp_cdb[2] = 0;    cp.cp_cdb[3] = 0;    cp.cp_cdb[4] = 254;    cp.cp_cdb[5] = 0;        if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP))         return (NULL);    while (!(inb(base + HA_RSTATUS) & HA_SDRQ));    outsw(base + HA_RDATA, &cp, cplen);    outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);    for (z = 0; z < cppadlen; z++) outw(0, base + HA_RDATA);        while (inb(base + HA_RSTATUS) & HA_SBUSY);    if (inb(base + HA_RSTATUS) & HA_SERROR)	return (NULL);    else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))	return (NULL);    else    {	insw(base+HA_RDATA, &buff, 127);	while (inb(base + HA_RSTATUS)&HA_SDRQ) inw(base + HA_RDATA);	return (buff);    }}int get_pio_conf_PIO(u32 base, struct get_conf *buf){    ulong loop = HZ/2;    int z;    ushort *p;        if(check_region(base, 9))  	return (FALSE);        memset(buf, 0, sizeof(struct get_conf));        while (inb(base + HA_RSTATUS) & HA_SBUSY)	if (--loop == 0) 	    return (FALSE);        DBG(DBG_PIO && DBG_PROBE,	printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base));    eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG);    loop = HZ/2;    for (p = (ushort *) buf; 	 (long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) {	while (!(inb(base + HA_RSTATUS) & HA_SDRQ))	    if (--loop == 0)		return (FALSE);	loop = HZ/2;	*p = inw(base + HA_RDATA);    }    if (!(inb(base + HA_RSTATUS) & HA_SERROR)) {            /* Error ? */	if (htonl(EATA_SIGNATURE) == buf->signature) {	    DBG(DBG_PIO&&DBG_PROBE, printk(KERN_NOTICE "EATA Controller found "                                           "at %#4x EATA Level: %x\n", base, 					   (uint) (buf->version)));	    	    while (inb(base + HA_RSTATUS) & HA_SDRQ) 		inw(base + HA_RDATA);	    if(ALLOW_DMA_BOARDS == FALSE) {		for (z = 0; z < MAXISA; z++)		    if (base == ISAbases[z]) {			buf->IRQ = ISAirqs[z]; 			break;		    }	    }	    return (TRUE);	}     } else {	DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer "			      "for HBA at %x\n", base));    }    return (FALSE);}void print_pio_config(struct get_conf *gc){    printk("Please check values: (read config data)\n");    printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n",	   (uint) ntohl(gc->len), gc->version,	   gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support);    printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n",	   gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2],	   gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND);    printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n",	   gc->IRQ, gc->IRQ_TR, gc->FORCADR, 	   gc->MAX_CHAN, gc->ID_qest);    DBG(DPT_DEBUG, DELAY(14));}static uint print_selftest(uint base){    unchar buffer[512];#ifdef VERBOSE_SETUP    int z;#endif        printk("eata_pio: executing controller self test & setup...\n");    while (inb(base + HA_RSTATUS) & HA_SBUSY);    outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND);    do {	while (inb(base + HA_RSTATUS) & HA_SBUSY)	    /* nothing */ ;	if (inb(base + HA_RSTATUS) & HA_SDRQ)	{	    insw(base + HA_RDATA, &buffer, 256);#ifdef VERBOSE_SETUP	    /* no beeps please... */	    for (z = 0; z < 511 && buffer[z]; z++)		if (buffer[z] != 7) printk("%c", buffer[z]);#endif	}    } while (inb(base+HA_RSTATUS) & (HA_SBUSY|HA_SDRQ));        return (!(inb(base+HA_RSTATUS) & HA_SERROR)); }int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt){    ulong size = 0;    char *buff;    ulong cplen;    ushort cppadlen;    struct Scsi_Host *sh;    hostdata *hd;        DBG(DBG_REGISTER, print_pio_config(gc));        if (gc->DMA_support == TRUE) {	printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n",base);	if(ALLOW_DMA_BOARDS == FALSE)	    return (FALSE);    }        if ((buff = get_pio_board_data((uint)base, gc->IRQ, gc->scsi_id[3], 			       cplen   =(htonl(gc->cplen   )+1)/2, 			       cppadlen=(htons(gc->cppadlen)+1)/2)) == NULL)    {	printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base);	return (FALSE);    }        if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE)    {	printk("HBA at %#lx failed while performing self test & setup.\n", 	       (ulong) base);	return (FALSE);    }        if (!reg_IRQ[gc->IRQ]) {    /* Interrupt already registered ? */	if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, 			 "EATA-PIO", NULL)){	    reg_IRQ[gc->IRQ]++;	    if (!gc->IRQ_TR)		reg_IRQL[gc->IRQ] = TRUE;   /* IRQ is edge triggered */	} else {	    printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ);	    return (FALSE);	}    } else {            /* More than one HBA on this IRQ */	if (reg_IRQL[gc->IRQ] == TRUE) {	    printk("Can't support more than one HBA on this IRQ,\n"		   "  if the IRQ is edge triggered. Sorry.\n");	    return (FALSE);	} else	    reg_IRQ[gc->IRQ]++;    }        request_region(base, 8, "eata_pio");        size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz));        sh = scsi_register(tpnt, size);    hd = SD(sh);                           memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)));    memset(hd->reads, 0, sizeof(ulong) * 26);         strncpy(SD(sh)->vendor, &buff[8], 8);    SD(sh)->vendor[8] = 0;    strncpy(SD(sh)->name, &buff[16], 17);    SD(sh)->name[17] = 0;    SD(sh)->revision[0] = buff[32];    SD(sh)->revision[1] = buff[33];    SD(sh)->revision[2] = buff[34];    SD(sh)->revision[3] = '.';    SD(sh)->revision[4] = buff[35];    SD(sh)->revision[5] = 0;    switch (ntohl(gc->len)) {    case 0x1c:	SD(sh)->EATA_revision = 'a';	break;    case 0x1e:	SD(sh)->EATA_revision = 'b';	break;    case 0x22:	SD(sh)->EATA_revision = 'c';	break;    case 0x24:	SD(sh)->EATA_revision = 'z';		    default:	SD(sh)->EATA_revision = '?';    }    if(ntohl(gc->len) >= 0x22) {	if (gc->is_PCI == TRUE)	    hd->bustype = IS_PCI;	else if (gc->is_EISA == TRUE)	    hd->bustype = IS_EISA;	else	    hd->bustype = IS_ISA;    } else {	if (buff[21] == '4')	    hd->bustype = IS_PCI;	else if (buff[21] == '2')	    hd->bustype = IS_EISA;	else	    hd->bustype = IS_ISA;    }      SD(sh)->cplen=cplen;    SD(sh)->cppadlen=cppadlen;    SD(sh)->hostid=gc->scsi_id[3];    SD(sh)->devflags=1<<gc->scsi_id[3];    SD(sh)->moresupport=gc->MORE_support;    sh->unique_id = base;    sh->base = (char *) base;    sh->io_port = base;    sh->n_io_port = 8;    sh->irq = gc->IRQ;    sh->dma_channel = PIO;    sh->this_id = gc->scsi_id[3];    sh->can_queue = 1;    sh->cmd_per_lun = 1;    sh->sg_tablesize = SG_ALL;        hd->channel = 0;        sh->max_id = 8;    sh->max_lun = 8;    if (gc->SECOND)	hd->primary = FALSE;    else	hd->primary = TRUE;        sh->unchecked_isa_dma = FALSE; /* We can only do PIO */        hd->next = NULL;    /* build a linked list of all HBAs */    hd->prev = last_HBA;    if(hd->prev != NULL)	SD(hd->prev)->next = sh;    last_HBA = sh;    if (first_HBA == NULL)	first_HBA = sh;    registered_HBAs++;    return (1);}void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt){    int i;        for (i = 0; i < MAXISA; i++) {  	if (ISAbases[i]) {  	    if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE){		register_pio_HBA(ISAbases[i], buf, tpnt);	    }	    ISAbases[i] = 0;	}    }    return;}void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt){    u32 base;    int i;#if CHECKPAL    u8 pal1, pal2, pal3;#endif    for (i = 0; i < MAXEISA; i++) {	if (EISAbases[i] == TRUE) { /* Still a possibility ?          */	    base = 0x1c88 + (i * 0x1000);#if CHECKPAL	    pal1 = inb((u16)base - 8);	    pal2 = inb((u16)base - 7);	    pal3 = inb((u16)base - 6);	    if (((pal1 == 0x12) && (pal2 == 0x14)) ||		((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) ||		((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) {		DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: "                                      "%x %x %x \n",				      (int)pal1, (int)pal2, (int)pal3));#endif		if (get_pio_conf_PIO(base, buf) == TRUE) {		    DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf));		    if (buf->IRQ) {			register_pio_HBA(base, buf, tpnt);		    } else			printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA "                               "removed from list\n");		}		/* Nothing found here so we take it from the list */		EISAbases[i] = 0;#if CHECKPAL	    }#endif	}    }    return;}void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt){#ifndef CONFIG_PCI    printk(KERN_ERR "eata_pio: kernel PCI support not enabled. Skipping scan "           "for PCI HBAs.\n");#else        u8 pci_bus, pci_device_fn;    static s16 pci_index = 0;   /* Device index to PCI BIOS calls */    u32 base = 0;    u16 com_adr;    u16 rev_device;    u32 error, i, x;    if (pci_present()) {	for (i = 0; i <= MAXPCI; ++i, ++pci_index) {	    if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, 				    pci_index, &pci_bus, &pci_device_fn))		break;	    DBG(DBG_PROBE && DBG_PCI, 		printk("eata_pio: HBA at bus %d, device %d,"		       " function %d, index %d\n", (s32)pci_bus, 		       (s32)((pci_device_fn & 0xf8) >> 3),		       (s32)(pci_device_fn & 7), pci_index));	    	    if (!(error = pcibios_read_config_word(pci_bus, pci_device_fn, 				       PCI_CLASS_DEVICE, &rev_device))) {		if (rev_device == PCI_CLASS_STORAGE_SCSI) {		    if (!(error = pcibios_read_config_word(pci_bus, 					       pci_device_fn, PCI_COMMAND, 					       (u16 *) & com_adr))) {			if (!((com_adr & PCI_COMMAND_IO) && 			      (com_adr & PCI_COMMAND_MASTER))) {			    printk("HBA has IO or BUSMASTER mode disabled\n");			    continue;			}		    } else			printk("eata_pio: error %x while reading "			       "PCI_COMMAND\n", error);		} else		    printk("DEVICECLASSID %x didn't match\n", rev_device);	    } else {		printk("eata_pio: error %x while reading PCI_CLASS_BASE\n", 		       error);		continue;	    }	    	    if (!(error = pcibios_read_config_dword(pci_bus, pci_device_fn,				       PCI_BASE_ADDRESS_0, (int *) &base))){				/* Check if the address is valid */		if (base & 0x01) {		    base &= 0xfffffffe;		    /* EISA tag there ? */		    if ((inb(base) == 0x12) && (inb(base + 1) == 0x14))			continue;   /* Jep, it's forced, so move on  */		    base += 0x10;   /* Now, THIS is the real address */		    if (base != 0x1f8) {			/* We didn't find it in the primary search */			if (get_pio_conf_PIO(base, buf) == TRUE) {			    if (buf->FORCADR)   /* If the address is forced */				continue;       /* we'll find it later      */			    			    /* OK. We made it till here, so we can go now  			     * and register it. We  only have to check and 			     * eventually remove it from the EISA and ISA list 			     */			    			    register_pio_HBA(base, buf, tpnt);			    			    if (base < 0x1000) {				for (x = 0; x < MAXISA; ++x) {				    if (ISAbases[x] == base) {					ISAbases[x] = 0;					break;				    }				}			    } else if ((base & 0x0fff) == 0x0c88) {				x = (base >> 12) & 0x0f;				EISAbases[x] = 0;			    }			    continue;  /* break; */			}		    }		}	    } else		printk("eata_pio: error %x while reading "		       "PCI_BASE_ADDRESS_0\n", error);	}    } else	printk("eata_pio: No BIOS32 extensions present. This driver release "	       "still depends on it.\n"	       "          Skipping scan for PCI HBAs.\n");#endif /* #ifndef CONFIG_PCI */    return;}int eata_pio_detect(Scsi_Host_Template * tpnt){    struct Scsi_Host *HBA_ptr;    struct get_conf gc;    int i;        DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG,	printk("Using lots of delays to let you read the debugging output\n"));        tpnt->proc_dir = &proc_scsi_eata_pio;    find_pio_PCI(&gc, tpnt);    find_pio_EISA(&gc, tpnt);    find_pio_ISA(&gc, tpnt);        for (i = 0; i <= MAXIRQ; i++)	if (reg_IRQ[i])	    request_irq(i, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL);        HBA_ptr = first_HBA;      if (registered_HBAs != 0) {	printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n"	       "(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n"	       "            Alfred Arnold,   a.arnold@kfa-juelich.de\n"	       "This release only supports DASD devices (harddisks)\n",	       VER_MAJOR, VER_MINOR, VER_SUB);		printk("Registered HBAs:\n");	printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:"               " QS: SG: CPL:\n");	for (i = 1; i <= registered_HBAs; i++) {	    printk("scsi%-2d: %.10s v%s 2.0%c  %s %#.4x   %2d   %d   %d   %c"                   "  %2d  %2d  %2d\n", 		   HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,		   SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')?		   "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",		   (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel,                    HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', 		   HBA_ptr->can_queue, HBA_ptr->sg_tablesize,                    HBA_ptr->cmd_per_lun);	    HBA_ptr = SD(HBA_ptr)->next;	}    }    DBG(DPT_DEBUG,DELAY(12));        return (registered_HBAs);}#ifdef MODULE/* Eventually this will go into an include file, but this will be later */Scsi_Host_Template driver_template = EATA_PIO;#include "scsi_module.c"#endif/* * Overrides for Emacs so that we almost follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only.  This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */

⌨️ 快捷键说明

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