atp870u.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,735 行 · 第 1/4 页
C
2,735 行
tmport += 0x02; outb(dev->id[i].devspu, tmport++); outb(0, tmport++); outb(satn[6], tmport++); outb(satn[7], tmport++); tmport += 0x03; outb(satn[8], tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { continue; } while (inb(tmport) != 0x8e);try_sync: j = 0; tmport = wkport + 0x54; outb(0x06, tmport); tmport += 0x04; outb(0x20, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0) { if ((inb(tmport) & 0x01) != 0) { tmport -= 0x06; if ((m & dev->wide_idu) != 0) { if ((m & dev->ultra_map) != 0) { outb(synuw[j++], tmport); } else { outb(synw[j++], tmport); } } else { if ((m & dev->ultra_map) != 0) { outb(synu[j++], tmport); } else { outb(synn[j++], tmport); } } tmport += 0x06; } } tmport -= 0x08; while ((inb(tmport) & 0x80) == 0x00); j = inb(tmport) & 0x0f; if (j == 0x0f) { goto phase_ins; } if (j == 0x0a) { goto phase_cmds; } if (j == 0x0e) { goto try_sync; } continue;phase_outs: tmport = wkport + 0x58; outb(0x20, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00) { if ((inb(tmport) & 0x01) != 0x00) { tmport -= 0x06; outb(0x00, tmport); tmport += 0x06; } } tmport -= 0x08; j = inb(tmport); if (j == 0x85) { goto tar_dcons; } j &= 0x0f; if (j == 0x0f) { goto phase_ins; } if (j == 0x0a) { goto phase_cmds; } if (j == 0x0e) { goto phase_outs; } continue;phase_ins: tmport = wkport + 0x54; outb(0x06, tmport); tmport += 0x04; outb(0x20, tmport); tmport += 0x07; k = 0;phase_ins1: j = inb(tmport); if ((j & 0x01) != 0x00) { tmport -= 0x06; mbuf[k++] = inb(tmport); tmport += 0x06; goto phase_ins1; } if ((j & 0x80) == 0x00) { goto phase_ins1; } tmport -= 0x08; while ((inb(tmport) & 0x80) == 0x00); j = inb(tmport); if (j == 0x85) { goto tar_dcons; } j &= 0x0f; if (j == 0x0f) { goto phase_ins; } if (j == 0x0a) { goto phase_cmds; } if (j == 0x0e) { goto phase_outs; } continue;phase_cmds: tmport = wkport + 0x50; outb(0x30, tmport);tar_dcons: tmport = wkport + 0x54; outb(0x00, tmport); tmport += 0x04; outb(0x08, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; j = inb(tmport); if (j != 0x16) { continue; } if (mbuf[0] != 0x01) { continue; } if (mbuf[1] != 0x03) { continue; } if (mbuf[4] == 0x00) { continue; } if (mbuf[3] > 0x64) { continue; } if (mbuf[4] > 0x0e) { mbuf[4] = 0x0e; } dev->id[i].devspu = mbuf[4]; if (mbuf[3] < 0x0c) { j = 0xb0; goto set_syn_ok; } if ((mbuf[3] < 0x0d) && (rmb == 0)) { j = 0xa0; goto set_syn_ok; } if (mbuf[3] < 0x1a) { j = 0x20; goto set_syn_ok; } if (mbuf[3] < 0x33) { j = 0x40; goto set_syn_ok; } if (mbuf[3] < 0x4c) { j = 0x50; goto set_syn_ok; } j = 0x60;set_syn_ok: dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j; }}static void atp870u_free_tables(struct Scsi_Host *host){ struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; int k; for (k = 0; k < 16; k++) { if (!atp_dev->id[k].prd_tableu) continue; pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[k].prd_tableu, atp_dev->id[k].prd_phys); atp_dev->id[k].prd_tableu = NULL; }}static int atp870u_init_tables(struct Scsi_Host *host){ struct atp_unit *dev = (struct atp_unit *)&host->hostdata; int k, i; for (i = k = 0; k < 16; k++) { dev->id[k].prd_tableu = pci_alloc_consistent(dev->pdev, 1024, &dev->id[k].prd_phys); if (!dev->id[k].prd_tableu) { atp870u_free_tables(host); return -ENOMEM; } dev->id[k].devspu = 0x20; dev->id[k].devtypeu = 0; dev->id[k].curr_req = NULL; } dev->active_idu = 0; dev->wide_idu = 0; dev->host_idu = 0x07; dev->quhdu = 0; dev->quendu = 0; dev->chip_veru = 0; dev->last_cmd = 0xff; dev->in_snd = 0; dev->in_int = 0; for (k = 0; k < qcnt; k++) { dev->querequ[k] = NULL; } for (k = 0; k < 16; k++) { dev->id[k].curr_req = NULL; dev->sp[k] = 0x04; } return 0;}/* return non-zero on detection */static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent){ unsigned char k, m; unsigned long flags; unsigned int base_io, error, tmport; unsigned char host_id; unsigned short n; struct Scsi_Host *shpnt; struct atp_unit atp_dev, *p; static int count; if (pci_enable_device(dev)) return -EIO; if (pci_set_dma_mask(dev, 0xFFFFFFFFUL)) { printk(KERN_ERR "atp870u: 32bit DMA mask required but not available.\n"); return -EIO; } memset(&atp_dev, 0, sizeof atp_dev); /* * It's probably easier to weed out some revisions like * this than via the PCI device table */ if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) { error = pci_read_config_byte(dev, PCI_CLASS_REVISION, &atp_dev.chip_veru); if (atp_dev.chip_veru < 2) return -EIO; } switch (ent->device) { case 0x8081: case PCI_DEVICE_ID_ARTOP_AEC7612UW: case PCI_DEVICE_ID_ARTOP_AEC7612SUW: atp_dev.chip_veru = 0x04; default: break; } base_io = pci_resource_start(dev, 0); if (ent->device != 0x8081) { error = pci_read_config_byte(dev, 0x49, &host_id); base_io &= 0xfffffff8; printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d " "IO:%x, IRQ:%d.\n", count, base_io, dev->irq); atp_dev.unit = count; atp_dev.ioport = base_io; atp_dev.pciport = base_io + 0x20; atp_dev.deviceid = ent->device; host_id &= 0x07; atp_dev.host_idu = host_id; tmport = base_io + 0x22; atp_dev.scam_on = inb(tmport); tmport += 0x0b; atp_dev.global_map = inb(tmport++); atp_dev.ultra_map = inw(tmport); if (atp_dev.ultra_map == 0) { atp_dev.scam_on = 0x00; atp_dev.global_map = 0x20; atp_dev.ultra_map = 0xffff; } shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); if (!shpnt) return -ENOMEM; p = (struct atp_unit *)&shpnt->hostdata; atp_dev.host = shpnt; atp_dev.pdev = dev; pci_set_drvdata(dev, p); memcpy(p, &atp_dev, sizeof atp_dev); if (atp870u_init_tables(shpnt) < 0) goto unregister; if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) { printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq); goto free_tables; } spin_lock_irqsave(shpnt->host_lock, flags); if (atp_dev.chip_veru > 0x07) { /* check if atp876 chip then enable terminator */ tmport = base_io + 0x3e; outb(0x00, tmport); } tmport = base_io + 0x3a; k = (inb(tmport) & 0xf3) | 0x10; outb(k, tmport); outb((k & 0xdf), tmport); mdelay(32); outb(k, tmport); mdelay(32); tmport = base_io; outb((host_id | 0x08), tmport); tmport += 0x18; outb(0, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0) mdelay(1); tmport -= 0x08; inb(tmport); tmport = base_io + 1; outb(8, tmport++); outb(0x7f, tmport); tmport = base_io + 0x11; outb(0x20, tmport); tscam(shpnt); is870(shpnt, base_io); tmport = base_io + 0x3a; outb((inb(tmport) & 0xef), tmport); tmport++; outb((inb(tmport) | 0x20), tmport); } else { base_io &= 0xfffffff8; host_id = inb(base_io + 0x39); host_id >>= 0x04; printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d" " IO:%x, IRQ:%d.\n", count, base_io, dev->irq); atp_dev.ioport = base_io + 0x40; atp_dev.pciport = base_io + 0x28; atp_dev.deviceid = ent->device; atp_dev.host_idu = host_id; tmport = base_io + 0x22; atp_dev.scam_on = inb(tmport); tmport += 0x13; atp_dev.global_map = inb(tmport); tmport += 0x07; atp_dev.ultra_map = inw(tmport); n = 0x3f09;next_fblk: if (n >= 0x4000) goto flash_ok; m = 0; outw(n, base_io + 0x34); n += 0x0002; if (inb(base_io + 0x30) == 0xff) goto flash_ok; atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[m++] = inb(base_io + 0x33); outw(n, base_io + 0x34); n += 0x0002; atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[m++] = inb(base_io + 0x33); outw(n, base_io + 0x34); n += 0x0002; atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[m++] = inb(base_io + 0x33); outw(n, base_io + 0x34); n += 0x0002; atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[m++] = inb(base_io + 0x33); n += 0x0018; goto next_fblk;flash_ok: outw(0, base_io + 0x34); atp_dev.ultra_map = 0; atp_dev.async = 0; for (k = 0; k < 16; k++) { n = 1; n = n << k; if (atp_dev.sp[k] > 1) { atp_dev.ultra_map |= n; } else { if (atp_dev.sp[k] == 0) atp_dev.async |= n; } } atp_dev.async = ~(atp_dev.async); outb(atp_dev.global_map, base_io + 0x35); shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); if (!shpnt) return -ENOMEM; p = (struct atp_unit *)&shpnt->hostdata; atp_dev.host = shpnt; atp_dev.pdev = dev; pci_set_drvdata(dev, p); memcpy(p, &atp_dev, sizeof atp_dev); if (atp870u_init_tables(shpnt) < 0) { printk(KERN_ERR "Unable to allocate tables for Acard controller\n"); goto unregister; } if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) { printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq); goto free_tables; } spin_lock_irqsave(shpnt->host_lock, flags); tmport = base_io + 0x38; k = inb(tmport) & 0x80; outb(k, tmport); tmport += 0x03; outb(0x20, tmport); mdelay(32); outb(0, tmport); mdelay(32); tmport = base_io + 0x5b; inb(tmport); tmport -= 0x04; inb(tmport); tmport = base_io + 0x40; outb((host_id | 0x08), tmport); tmport += 0x18; outb(0, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0) mdelay(1); tmport -= 0x08; inb(tmport); tmport = base_io + 0x41; outb(8, tmport++); outb(0x7f, tmport); tmport = base_io + 0x51; outb(0x20, tmport); tscam(shpnt); is880(shpnt, base_io); tmport = base_io + 0x38; outb(0xb0, tmport); } if (p->chip_veru == 4) shpnt->max_id = 16; shpnt->this_id = host_id; shpnt->unique_id = base_io; shpnt->io_port = base_io; if (ent->device == 0x8081) { shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */ } else { shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */ } shpnt->irq = dev->irq; spin_unlock_irqrestore(shpnt->host_lock, flags); if (ent->device == 0x8081) { if (!request_region(base_io, 0x60, "atp870u")) goto request_io_fail; } else { if (!request_region(base_io, 0x40, "atp870u")) goto request_io_fail; } count++; if (scsi_add_host(shpnt, &dev->dev)) goto scsi_add_fail; scsi_scan_host(shpnt); return 0; scsi_add_fail: if (ent->device == 0x8081) release_region(base_io, 0x60); else release_region(base_io, 0x40);request_io_fail: free_irq(dev->irq, shpnt);free_tables: atp870u_free_tables(shpnt);unregister: scsi_host_put(shpnt); return -1;}/* The abort command does not leave the device in a clean state where it is available to be used again. Until this gets worked out, we will leave it commented out. */static int atp870u_abort(struct scsi_cmnd * SCpnt){ unsigned char j, k; struct scsi_cmnd *workrequ; unsigned int tmport; struct atp_unit *dev = (struct atp_unit *)&SCpnt->device->host->hostdata; printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd); printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu); tmport = dev->ioport; for (j = 0; j < 0x17; j++) { printk(" r%2x=%2x", j, inb(tmport++)); } tmport += 0x05; printk(" r1c=%2x", inb(tmport)); tmport += 0x03; printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd); tmport = dev->pciport; printk(" r20=%2x", inb(tmport)); tmport += 0x02; printk(" r22=%2x", inb(tmport)); tmport = dev->ioport + 0x3a; printk(" r3a=%2x \n", inb(tmport)); tmport = dev->ioport + 0x3b; printk(" r3b=%2x \n", inb(tmport)); for (j = 0; j < 16; j++) { if (dev->id[j].curr_req != NULL) { workrequ = dev->id[j].curr_req; printk("\n que cdb= "); for (k = 0; k < workrequ->cmd_len; k++) { printk(" %2x ", workrequ->cmnd[k]); } printk(" last_lenu= %lx ", dev->id[j].last_lenu); } } /* Sort of - the thing handles itself */ return SUCCESS;}static const char *atp870u_info(struct Scsi_Host *notused){ static char buffer[128]; strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "); return buffer;}#define BLS buffer + len + sizestatic int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, int inout){ static u8 buff[512]; int size = 0; int len = 0; off_t begin = 0; off_t pos = 0; if (inout) return -ENOSYS; if (offset == 0) { memset(buff, 0, sizeof(buff)); } size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n"); len += size; pos = begin + len; size = 0; size += sprintf(BLS, "\n"); size += sprintf(BLS, "Adapter Configuration:\n"); size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port); size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); len += size; pos = begin + len; *start = buffer + (offset - begin); /* Start of wanted data */ len -= (offset - begin); /* Start slop */ if (len > length) { len = length; /* Ending slop */ } return (len);}static int atp870u_biosparam(struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int *ip){ int heads, sectors, cylinders; heads = 64; sectors = 32; cylinders = (unsigned long)capacity / (heads * sectors); if (cylinders > 1024) { heads = 255; sectors = 63; cylinders = (unsigned long)capacity / (heads * sectors); } ip[0] = heads; ip[1] = sectors; ip[2] = cylinders; return 0;}static void atp870u_remove(struct pci_dev *pdev){ struct atp_unit *atp_dev = pci_get_drvdata(pdev); struct Scsi_Host *pshost = atp_dev->host; scsi_remove_host(pshost); free_irq(pshost->irq, pshost); release_region(pshost->io_port, pshost->n_io_port); atp870u_free_tables(pshost); scsi_host_put(pshost); pci_set_drvdata(pdev, NULL);}MODULE_LICENSE("GPL");static struct scsi_host_template atp870u_template = { .module = THIS_MODULE, .name = "atp870u", .proc_name = "atp870u", .proc_info = atp870u_proc_info, .info = atp870u_info, .queuecommand = atp870u_queuecommand, .eh_abort_handler = atp870u_abort, .bios_param = atp870u_biosparam, .can_queue = qcnt, .this_id = 7, .sg_tablesize = ATP870U_SCATTER, .cmd_per_lun = ATP870U_CMDLUN, .use_clustering = ENABLE_CLUSTERING,};static struct pci_device_id atp870u_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, 0x8081) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060) }, { 0, },};MODULE_DEVICE_TABLE(pci, atp870u_id_table);static struct pci_driver atp870u_driver = { .id_table = atp870u_id_table, .name = "atp870u", .probe = atp870u_probe, .remove = __devexit_p(atp870u_remove),};static int __init atp870u_init(void){ return pci_module_init(&atp870u_driver);}static void __exit atp870u_exit(void){ pci_unregister_driver(&atp870u_driver);}module_init(atp870u_init);module_exit(atp870u_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?