📄 sym_glue.c
字号:
switch(uc->cmd) { case UC_SETSYNC: case UC_SETTAGS: case UC_SETWIDE: case UC_SETFLAG: case UC_RESETDEV: case UC_CLEARDEV: SKIP_SPACES(1); if ((arg_len = is_keyword(ptr, len, "all")) != 0) { ptr += arg_len; len -= arg_len; uc->target = ~0; } else { GET_INT_ARG(target); uc->target = (1<<target);#ifdef DEBUG_PROC_INFOprintk("sym_user_command: target=%ld\n", target);#endif } break; } switch(uc->cmd) { case UC_SETVERBOSE: case UC_SETSYNC: case UC_SETTAGS: case UC_SETWIDE: SKIP_SPACES(1); GET_INT_ARG(uc->data);#ifdef DEBUG_PROC_INFOprintk("sym_user_command: data=%ld\n", uc->data);#endif break;#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT case UC_SETDEBUG: while (len > 0) { SKIP_SPACES(1); if ((arg_len = is_keyword(ptr, len, "alloc"))) uc->data |= DEBUG_ALLOC; else if ((arg_len = is_keyword(ptr, len, "phase"))) uc->data |= DEBUG_PHASE; else if ((arg_len = is_keyword(ptr, len, "queue"))) uc->data |= DEBUG_QUEUE; else if ((arg_len = is_keyword(ptr, len, "result"))) uc->data |= DEBUG_RESULT; else if ((arg_len = is_keyword(ptr, len, "scatter"))) uc->data |= DEBUG_SCATTER; else if ((arg_len = is_keyword(ptr, len, "script"))) uc->data |= DEBUG_SCRIPT; else if ((arg_len = is_keyword(ptr, len, "tiny"))) uc->data |= DEBUG_TINY; else if ((arg_len = is_keyword(ptr, len, "timing"))) uc->data |= DEBUG_TIMING; else if ((arg_len = is_keyword(ptr, len, "nego"))) uc->data |= DEBUG_NEGO; else if ((arg_len = is_keyword(ptr, len, "tags"))) uc->data |= DEBUG_TAGS; else if ((arg_len = is_keyword(ptr, len, "pointer"))) uc->data |= DEBUG_POINTER; else return -EINVAL; ptr += arg_len; len -= arg_len; }#ifdef DEBUG_PROC_INFOprintk("sym_user_command: data=%ld\n", uc->data);#endif break;#endif /* SYM_LINUX_DEBUG_CONTROL_SUPPORT */ case UC_SETFLAG: while (len > 0) { SKIP_SPACES(1); if ((arg_len = is_keyword(ptr, len, "no_disc"))) uc->data &= ~SYM_DISC_ENABLED; else return -EINVAL; ptr += arg_len; len -= arg_len; } break; default: break; } if (len) return -EINVAL; else { long flags; SYM_LOCK_HCB(np, flags); sym_exec_user_command (np, uc); SYM_UNLOCK_HCB(np, flags); } return length;}#endif /* SYM_LINUX_USER_COMMAND_SUPPORT */#ifdef SYM_LINUX_USER_INFO_SUPPORT/* * Informations through the proc file system. */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;}/* * Copy formatted information into the input buffer. */static int sym_host_info(hcb_p np, char *ptr, off_t offset, int len){ struct info_str info; info.buffer = ptr; info.length = len; info.offset = offset; info.pos = 0; copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, " "revision id 0x%x\n", np->s.chip_name, np->device_id, np->revision_id); copy_info(&info, "On PCI bus %d, device %d, function %d, "#ifdef __sparc__ "IRQ %s\n",#else "IRQ %d\n",#endif np->s.bus, (np->s.device_fn & 0xf8) >> 3, np->s.device_fn & 7,#ifdef __sparc__ __irq_itoa(np->s.irq));#else (int) np->s.irq);#endif copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n", (int) (np->minsync_dt ? np->minsync_dt : np->minsync), np->maxwide ? "Wide" : "Narrow", np->minsync_dt ? ", DT capable" : ""); copy_info(&info, "Max. started commands %d, " "max. commands per LUN %d\n", SYM_CONF_MAX_START, SYM_CONF_MAX_TAG); return info.pos > info.offset? info.pos - info.offset : 0;}#endif /* SYM_LINUX_USER_INFO_SUPPORT *//* * Entry point of the scsi proc fs of the driver. * - func = 0 means read (returns adapter infos) * - func = 1 means write (not yet merget from sym53c8xx) */static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int func){ struct Scsi_Host *host; struct host_data *host_data; hcb_p np = 0; int retv; for (host = first_host; host; host = host->next) { if (host->hostt != first_host->hostt) continue; if (host->host_no == hostno) { host_data = (struct host_data *) host->hostdata; np = host_data->ncb; break; } } if (!np) return -EINVAL; if (func) {#ifdef SYM_LINUX_USER_COMMAND_SUPPORT retv = sym_user_command(np, buffer, length);#else retv = -EINVAL;#endif } else { if (start) *start = buffer;#ifdef SYM_LINUX_USER_INFO_SUPPORT retv = sym_host_info(np, buffer, offset, length);#else retv = -EINVAL;#endif } return retv;}#endif /* SYM_LINUX_PROC_INFO_SUPPORT *//* * Free controller resources. */static void sym_free_resources(hcb_p np){ /* * Free O/S specific resources. */ if (np->s.irq) free_irq(np->s.irq, np); if (np->s.io_port) release_region(np->s.io_port, np->s.io_ws);#ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING if (np->s.mmio_va) pci_unmap_mem(np->s.mmio_va, np->s.io_ws); if (np->s.ram_va) pci_unmap_mem(np->s.ram_va, np->ram_ws);#endif /* * Free O/S independant resources. */ sym_hcb_free(np); sym_mfree_dma(np, sizeof(*np), "HCB");}/* * Ask/tell the system about DMA addressing. */#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPINGstatic int sym_setup_bus_dma_mask(hcb_p np){#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,3) if (!pci_dma_supported(np->s.device, 0xffffffffUL)) goto out_err32;#else#if SYM_CONF_DMA_ADDRESSING_MODE == 0 if (pci_set_dma_mask(np->s.device, 0xffffffffUL)) goto out_err32;#else#if SYM_CONF_DMA_ADDRESSING_MODE == 1#define PciDmaMask 0xffffffffff#elif SYM_CONF_DMA_ADDRESSING_MODE == 2#define PciDmaMask 0xffffffffffffffff#endif if (np->features & FE_DAC) { if (!pci_set_dma_mask(np->s.device, PciDmaMask)) { np->use_dac = 1; printf_info("%s: using 64 bit DMA addressing\n", sym_name(np)); } else { if (!pci_set_dma_mask(np->s.device, 0xffffffffUL)) goto out_err32; } }#undef PciDmaMask#endif#endif return 0;out_err32: printf_warning("%s: 32 BIT DMA ADDRESSING NOT SUPPORTED\n", sym_name(np)); return -1;}#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING *//* * Host attach and initialisations. * * Allocate host data and ncb structure. * Request IO region and remap MMIO region. * Do chip initialization. * If all is OK, install interrupt handling and * start the timer daemon. */static int __init sym_attach (Scsi_Host_Template *tpnt, int unit, sym_device *dev){ struct host_data *host_data; hcb_p np = 0; struct Scsi_Host *instance = 0; u_long flags = 0; sym_nvram *nvram = dev->nvram; struct sym_fw *fw; printk(KERN_INFO "sym%d: <%s> rev 0x%x on pci bus %d device %d function %d "#ifdef __sparc__ "irq %s\n",#else "irq %d\n",#endif unit, dev->chip.name, dev->chip.revision_id, dev->s.bus, (dev->s.device_fn & 0xf8) >> 3, dev->s.device_fn & 7,#ifdef __sparc__ __irq_itoa(dev->s.irq));#else dev->s.irq);#endif /* * Get the firmware for this chip. */ fw = sym_find_firmware(&dev->chip); if (!fw) goto attach_failed; /* * Allocate host_data structure */ if (!(instance = scsi_register(tpnt, sizeof(*host_data)))) goto attach_failed; host_data = (struct host_data *) instance->hostdata; /* * Allocate immediately the host control block, * since we are only expecting to succeed. :) * We keep track in the HCB of all the resources that * are to be released on error. */#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING np = __sym_calloc_dma(dev->pdev, sizeof(*np), "HCB"); if (np) { np->s.device = dev->pdev; np->bus_dmat = dev->pdev; /* Result in 1 DMA pool per HBA */ } else goto attach_failed;#else np = sym_calloc_dma(sizeof(*np), "HCB"); if (!np) goto attach_failed;#endif host_data->ncb = np; SYM_INIT_LOCK_HCB(np); /* * Copy some useful infos to the HCB. */ np->hcb_ba = vtobus(np); np->verbose = sym_driver_setup.verbose; np->s.device = dev->pdev; np->s.unit = unit; np->device_id = dev->chip.device_id; np->revision_id = dev->chip.revision_id; np->s.bus = dev->s.bus; np->s.device_fn = dev->s.device_fn; np->features = dev->chip.features; np->clock_divn = dev->chip.nr_divisor; np->maxoffs = dev->chip.offset_max; np->maxburst = dev->chip.burst_max; np->myaddr = dev->host_id; /* * Edit its name. */ strncpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name)-1); sprintf(np->s.inst_name, "sym%d", np->s.unit); /* * Ask/tell the system about DMA addressing. */#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING if (sym_setup_bus_dma_mask(np)) goto attach_failed;#endif /* * Try to map the controller chip to * virtual and physical memory. */ np->mmio_ba = (u32)dev->s.base; np->s.io_ws = (np->features & FE_IO256)? 256 : 128;#ifndef SYM_CONF_IOMAPPED np->s.mmio_va = pci_map_mem(dev->s.base_c, np->s.io_ws); if (!np->s.mmio_va) { printf_err("%s: can't map PCI MMIO region\n", sym_name(np)); goto attach_failed; } else if (sym_verbose > 1) printf_info("%s: using memory mapped IO\n", sym_name(np));#endif /* !defined SYM_CONF_IOMAPPED */ /* * Try to map the controller chip into iospace. */ if (dev->s.io_port) { request_region(dev->s.io_port, np->s.io_ws, NAME53C8XX); np->s.io_port = dev->s.io_port; } /* * Map on-chip RAM if present and supported. */ if (!(np->features & FE_RAM)) dev->s.base_2 = 0; if (dev->s.base_2) { np->ram_ba = (u32)dev->s.base_2; if (np->features & FE_RAM8K) np->ram_ws = 8192; else np->ram_ws = 4096;#ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING np->s.ram_va = pci_map_mem(dev->s.base_2_c, np->ram_ws); if (!np->s.ram_va) { printf_err("%s: can't map PCI MEMORY region\n", sym_name(np)); goto attach_failed; }#endif } /* * Perform O/S independant stuff. */ if (sym_hcb_attach(np, fw, nvram)) goto attach_failed; /* * Install the interrupt handler. * If we synchonize the C code with SCRIPTS on interrupt, * we donnot want to share the INTR line at all. */ if (request_irq(dev->s.irq, sym53c8xx_intr, SA_SHIRQ, NAME53C8XX, np)) { printf_err("%s: request irq %d failure\n", sym_name(np), dev->s.irq); goto attach_failed; } np->s.irq = dev->s.irq; /* * After SCSI devices have been opened, we cannot * reset the bus safely, so we do it here. */ SYM_LOCK_HCB(np, flags); if (sym_reset_scsi_bus(np, 0)) { printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, " "TERMINATION, DEVICE POWER etc.!\n", sym_name(np)); SYM_UNLOCK_HCB(np, flags); goto attach_failed; } /* * Initialize some queue headers. */ sym_que_init(&np->s.wait_cmdq); sym_que_init(&np->s.busy_cmdq); /* * Start the SCRIPTS. */ sym_start_up (np, 1); /* * Start the timer daemon */ init_timer(&np->s.timer); np->s.timer.data = (unsigned long) np; np->s.timer.function = sym53c8xx_timer; np->s.lasttime=0; sym_timer (np); /* * Done. */ if (!first_host) first_host = instance; /* * Fill Linux host instance structure * and return success. */ instance->max_channel = 0; instance->this_id = np->myaddr; instance->max_id = np->maxwide ? 16 : 8; instance->max_lun = SYM_CONF_MAX_LUN;#ifndef SYM_CONF_IOMAPPED#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,29) instance->base = (unsigned long) np->s.mmio_va;#else instance->base = (char *) np->s.mmio_va;#endif#endif instance->irq = np->s.irq; instance->unique_id = np->s.io_port; instance->io_port = np->s.io_port; instance->n_io_port = np->s.io_ws; instance->dma_channel = 0; instance->cmd_per_lun = SYM_CONF_MAX_TAG; instance->can_queue = (SYM_CONF_MAX_START-2); instance->sg_tablesize = SYM_CONF_MAX_SG;#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) instance->max_cmd_len = 16;#endif instance->select_queue_depths = sym53c8xx_select_queue_depths; SYM_UNLOCK_HCB(np, flags); scsi_set_pci_device(instance, dev->pdev); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -