📄 esp.c
字号:
bursts = (DMA_BURST32 - 1); esp->bursts = bursts;}static void __init esp_get_revision(struct esp *esp){ u8 tmp; esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7)); esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY); sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); tmp = sbus_readb(esp->eregs + ESP_CFG2); tmp &= ~ESP_CONFIG2_MAGIC; if (tmp != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) { /* If what we write to cfg2 does not come back, cfg2 * is not implemented, therefore this must be a plain * esp100. */ esp->erev = esp100; printk("NCR53C90(esp100)\n"); } else { esp->config2 = 0; esp->prev_cfg3 = esp->config3[0] = 5; sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); sbus_writeb(0, esp->eregs + ESP_CFG3); sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); tmp = sbus_readb(esp->eregs + ESP_CFG3); if (tmp != 5) { /* The cfg2 register is implemented, however * cfg3 is not, must be esp100a. */ esp->erev = esp100a; printk("NCR53C90A(esp100a)\n"); } else { int target; for (target = 0; target < 16; target++) esp->config3[target] = 0; esp->prev_cfg3 = 0; sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); /* All of cfg{1,2,3} implemented, must be one of * the fas variants, figure out which one. */ if (esp->raw_cfact > ESP_CCF_F5) { esp->erev = fast; esp->sync_defp = SYNC_DEFP_FAST; printk("NCR53C9XF(espfast)\n"); } else { esp->erev = esp236; printk("NCR53C9x(esp236)\n"); } esp->config2 = 0; sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); } }}static void __init esp_init_swstate(struct esp *esp){ int i; /* Driver spinlock... */ spin_lock_init(&esp->lock); /* Command queues... */ esp->current_SC = NULL; esp->disconnected_SC = NULL; esp->issue_SC = NULL; /* Target and current command state... */ esp->targets_present = 0; esp->resetting_bus = 0; esp->snip = 0; /* Debugging... */ for(i = 0; i < 32; i++) esp->espcmdlog[i] = 0; esp->espcmdent = 0; /* MSG phase state... */ for(i = 0; i < 16; i++) { esp->cur_msgout[i] = 0; esp->cur_msgin[i] = 0; } esp->prevmsgout = esp->prevmsgin = 0; esp->msgout_len = esp->msgin_len = 0; /* Clear the one behind caches to hold unmatchable values. */ esp->prev_soff = esp->prev_stp = esp->prev_cfg3 = 0xff; esp->prev_hme_dmacsr = 0xffffffff;}static int __init detect_one_esp(Scsi_Host_Template *tpnt, struct sbus_dev *esp_dev, struct sbus_dev *espdma, struct sbus_bus *sbus, int id, int hme){ struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp)); struct esp *esp; if (!esp_host) { printk("ESP: Cannot register SCSI host\n"); return -1; } if (hme) esp_host->max_id = 16; esp = (struct esp *) esp_host->hostdata; esp->ehost = esp_host; esp->sdev = esp_dev; esp->esp_id = id; esp->prom_node = esp_dev->prom_node; prom_getstring(esp->prom_node, "name", esp->prom_name, sizeof(esp->prom_name)); esp_chain_add(esp); if (esp_find_dvma(esp, espdma) < 0) goto fail_unlink; if (esp_map_regs(esp, hme) < 0) { printk("ESP registers unmappable"); goto fail_dvma_release; } if (esp_map_cmdarea(esp) < 0) { printk("ESP DVMA transport area unmappable"); goto fail_unmap_regs; } if (esp_register_irq(esp) < 0) goto fail_unmap_cmdarea; esp_get_scsi_id(esp); esp->diff = prom_getbool(esp->prom_node, "differential"); if (esp->diff) printk("Differential "); esp_get_clock_params(esp); esp_get_bursts(esp, espdma); esp_get_revision(esp); esp_init_swstate(esp); esp_bootup_reset(esp); return 0;fail_unmap_cmdarea: sbus_free_consistent(esp->sdev, 16, (void *) esp->esp_command, esp->esp_command_dvma);fail_unmap_regs: sbus_iounmap(esp->eregs, ESP_REG_SIZE);fail_dvma_release: esp->dma->allocated = 0;fail_unlink: esp_chain_del(esp); scsi_unregister(esp_host); return -1;}/* Detecting ESP chips on the machine. This is the simple and easy * version. */#ifdef CONFIG_SUN4#include <asm/sun4paddr.h>int __init esp_detect(Scsi_Host_Template *tpnt){ static struct sbus_dev esp_dev; int esps_in_use = 0; espchain = 0; if (sun4_esp_physaddr) { memset (&esp_dev, 0, sizeof(esp_dev)); esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; esp_dev.irqs[0] = 4; esp_dev.resource[0].start = sun4_esp_physaddr; esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1; esp_dev.resource[0].flags = IORESOURCE_IO; if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0)) esps_in_use++; printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use); esps_running = esps_in_use; } return esps_in_use;}#else /* !CONFIG_SUN4 */int __init esp_detect(Scsi_Host_Template *tpnt){ struct sbus_bus *sbus; struct sbus_dev *esp_dev, *sbdev_iter; int nesps = 0, esps_in_use = 0; espchain = 0; if (!sbus_root) {#ifdef CONFIG_PCI return 0;#else panic("No SBUS in esp_detect()");#endif } for_each_sbus(sbus) { for_each_sbusdev(sbdev_iter, sbus) { struct sbus_dev *espdma = NULL; int hme = 0; /* Is it an esp sbus device? */ esp_dev = sbdev_iter; if (strcmp(esp_dev->prom_name, "esp") && strcmp(esp_dev->prom_name, "SUNW,esp")) { if (!strcmp(esp_dev->prom_name, "SUNW,fas")) { hme = 1; espdma = esp_dev; } else { if (!esp_dev->child || (strcmp(esp_dev->prom_name, "espdma") && strcmp(esp_dev->prom_name, "dma"))) continue; /* nope... */ espdma = esp_dev; esp_dev = esp_dev->child; if (strcmp(esp_dev->prom_name, "esp") && strcmp(esp_dev->prom_name, "SUNW,esp")) continue; /* how can this happen? */ } } if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0) continue; esps_in_use++; } /* for each sbusdev */ } /* for each sbus */ printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use); esps_running = esps_in_use; return esps_in_use;}#endif /* !CONFIG_SUN4 *//* The info function will return whatever useful * information the developer sees fit. If not provided, then * the name field will be used instead. */const char *esp_info(struct Scsi_Host *host){ struct esp *esp; esp = (struct esp *) host->hostdata; switch (esp->erev) { case esp100: return "Sparc ESP100 (NCR53C90)"; case esp100a: return "Sparc ESP100A (NCR53C90A)"; case esp236: return "Sparc ESP236"; case fas236: return "Sparc ESP236-FAST"; case fashme: return "Sparc ESP366-HME"; case fas100a: return "Sparc ESP100A-FAST"; default: return "Bogon ESP revision"; };}/* From Wolfgang Stanglmeier's NCR scsi driver. */struct info_str{ char *buffer; int length; int offset; int pos;};static void copy_mem_info(struct info_str *info, char *data, int len){ if (info->pos + len > info->length) len = info->length - info->pos; if (info->pos + len < info->offset) { info->pos += len; return; } if (info->pos < info->offset) { data += (info->offset - info->pos); len -= (info->offset - info->pos); } if (len > 0) { memcpy(info->buffer + info->pos, data, len); info->pos += len; }}static int copy_info(struct info_str *info, char *fmt, ...){ va_list args; char buf[81]; int len; va_start(args, fmt); len = vsprintf(buf, fmt, args); va_end(args); copy_mem_info(info, buf, len); return len;}static int esp_host_info(struct esp *esp, char *ptr, off_t offset, int len){ struct info_str info; int i; info.buffer = ptr; info.length = len; info.offset = offset; info.pos = 0; copy_info(&info, "Sparc ESP Host Adapter:\n"); copy_info(&info, "\tPROM node\t\t%08x\n", (unsigned int) esp->prom_node); copy_info(&info, "\tPROM name\t\t%s\n", esp->prom_name); copy_info(&info, "\tESP Model\t\t"); switch (esp->erev) { case esp100: copy_info(&info, "ESP100\n"); break; case esp100a: copy_info(&info, "ESP100A\n"); break; case esp236: copy_info(&info, "ESP236\n"); break; case fas236: copy_info(&info, "FAS236\n"); break; case fas100a: copy_info(&info, "FAS100A\n"); break; case fast: copy_info(&info, "FAST\n"); break; case fashme: copy_info(&info, "Happy Meal FAS\n"); break; case espunknown: default: copy_info(&info, "Unknown!\n"); break; }; copy_info(&info, "\tDMA Revision\t\t"); switch (esp->dma->revision) { case dvmarev0: copy_info(&info, "Rev 0\n"); break; case dvmaesc1: copy_info(&info, "ESC Rev 1\n"); break; case dvmarev1: copy_info(&info, "Rev 1\n"); break; case dvmarev2: copy_info(&info, "Rev 2\n"); break; case dvmarev3: copy_info(&info, "Rev 3\n"); break; case dvmarevplus: copy_info(&info, "Rev 1+\n"); break; case dvmahme: copy_info(&info, "Rev HME/FAS\n"); break; default: copy_info(&info, "Unknown!\n"); break; }; copy_info(&info, "\tLive Targets\t\t[ "); for (i = 0; i < 15; i++) { if (esp->targets_present & (1 << i)) copy_info(&info, "%d ", i); } copy_info(&info, "]\n\n"); /* Now describe the state of each existing target. */ copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\tWide\n"); for (i = 0; i < 15; i++) { if (esp->targets_present & (1 << i)) { Scsi_Device *SDptr = esp->ehost->host_queue; while ((SDptr->host != esp->ehost) && (SDptr->id != i) && (SDptr->next)) SDptr = SDptr->next; copy_info(&info, "%d\t\t", i); copy_info(&info, "%08lx\t", esp->config3[i]); copy_info(&info, "[%02lx,%02lx]\t\t\t", SDptr->sync_max_offset, SDptr->sync_min_period); copy_info(&info, "%s\t\t", SDptr->disconnect ? "yes" : "no"); copy_info(&info, "%s\n", (esp->config3[i] & ESP_CONFIG3_EWIDE) ? "yes" : "no"); } } return info.pos > info.offset? info.pos - info.offset : 0;}/* ESP proc filesystem code. */int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout){ struct esp *esp; if (inout) return -EINVAL; /* not yet */ for_each_esp(esp) { if (esp->ehost->host_no == hostno) break; } if (!esp) return -EINVAL; if (start) *start = buffer; return esp_host_info(esp, buffer, offset, length);}static void esp_get_dmabufs(struct esp *esp, Scsi_Cmnd *sp){ if (sp->use_sg == 0) { sp->SCp.this_residual = sp->request_bufflen; sp->SCp.buffer = (struct scatterlist *) sp->request_buffer; sp->SCp.buffers_residual = 0; if (sp->request_bufflen) { sp->SCp.have_data_in = sbus_map_single(esp->sdev, sp->SCp.buffer, sp->SCp.this_residual, scsi_to_sbus_dma_dir(sp->sc_data_direction)); sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.have_data_in); } else { sp->SCp.ptr = NULL; } } else { sp->SCp.buffer = (struct scatterlist *) sp->buffer; sp->SCp.buffers_residual = sbus_map_sg(esp->sdev, sp->SCp.buffer, sp->use_sg, scsi_to_sbus_dma_dir(sp->sc_data_direction)); sp->SCp.this_residual = sg_dma_len(sp->SCp.buffer); sp->SCp.ptr = (char *) ((unsigned long)sg_dma_address(sp->SCp.buffer)); }}static void esp_release_dmabufs(struct esp *esp, Scsi_Cmnd *sp){ if (sp->use_sg) { sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg, scsi_to_sbus_dma_dir(sp->sc_data_direction)); } else if (sp->request_bufflen) { sbus_unmap_single(esp->sdev, sp->SCp.have_data_in, sp->request_bufflen, scsi_to_sbus_dma_dir(sp->sc_data_direction)); }}static void esp_restore_pointers(struct esp *esp, Scsi_Cmnd *sp){ struct esp_pointers *ep = &esp->data_pointers[sp->target]; sp->SCp.ptr = ep->saved_ptr; sp->SCp.buffer = ep->saved_buffer; sp->SCp.this_residual = ep->saved_this_residual; sp->SCp.buffers_residual = ep->saved_buffers_residual;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -