📄 53c78xx.c
字号:
/* * Function : static int normal_init(Scsi_Host_Template *tpnt, int board, * int chip, u32 base, int io_port, int irq, int dma, int pcivalid, * unsigned char pci_bus, unsigned char pci_device_fn, * long long options); * * Purpose : initializes a NCR53c7,8x0 based on base addresses, * IRQ, and DMA channel. * * Useful where a new NCR chip is backwards compatible with * a supported chip, but the DEVICE ID has changed so it * doesn't show up when the autoprobe does a pcibios_find_device. * * Inputs : tpnt - Template for this SCSI adapter, board - board level * product, chip - 810, 820, or 825, bus - PCI bus, device_fn - * device and function encoding as used by PCI BIOS calls. * * Returns : 0 on success, -1 on failure. * */static int normal_init (Scsi_Host_Template *tpnt, int board, int chip, u32 base, int io_port, int irq, int dma, int pci_valid, unsigned char pci_bus, unsigned char pci_device_fn, long long options) { struct Scsi_Host *instance; struct NCR53c7x0_hostdata *hostdata; char chip_str[80]; int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0, schedule_size = 0, ok = 0; void *tmp; options |= perm_options; switch (chip) { case 825: case 820: case 815: case 810: schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */; script_len = NCR53c8xx_script_len; dsa_len = NCR53c8xx_dsa_len; options |= OPTION_INTFLY; sprintf (chip_str, "NCR53c%d", chip); break; default: printk("scsi-ncr53c7,8xx : unsupported SCSI chip %d\n", chip); return -1; } printk("scsi-ncr53c7,8xx : %s at memory 0x%x, io 0x%x, irq %d", chip_str, (unsigned) base, io_port, irq); if (dma == DMA_NONE) printk("\n"); else printk(", dma %d\n", dma); if ((chip / 100 == 8) && !pci_valid) printk ("scsi-ncr53c7,8xx : for better reliability and performance, please use the\n" " PCI override instead.\n" " Syntax : ncr53c8{10,15,20,25}=pci,<bus>,<device>,<function>\n" " <bus> and <device> are usually 0.\n"); if (options & OPTION_DEBUG_PROBE_ONLY) { printk ("scsi-ncr53c7,8xx : probe only enabled, aborting initialization\n"); return -1; } max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len + /* Size of dynamic part of command structure : */ 2 * /* Worst case : we don't know if we need DATA IN or DATA out */ ( 2 * /* Current instructions per scatter/gather segment */ tpnt->sg_tablesize + 3 /* Current startup / termination required per phase */ ) * 8 /* Each instruction is eight bytes */; /* Allocate fixed part of hostdata, dynamic part to hold appropriate SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure. We need a NCR53c7x0_cmd structure for scan_scsis() when we are not loaded as a module, and when we're loaded as a module, we can't use a non-dynamically allocated structure because modules are vmalloc()'d, which can allow structures to cross page boundaries and breaks our physical/virtual address assumptions for DMA. So, we stick it past the end of our hostdata structure. ASSUMPTION : Regardless of how many simultaneous SCSI commands we allow, the probe code only executes a _single_ instruction at a time, so we only need one here, and don't need to allocate NCR53c7x0_cmd structures for each target until we are no longer in scan_scsis and kmalloc() has become functional (memory_init() happens after all device driver initialization). */ size = sizeof(struct NCR53c7x0_hostdata) + script_len + /* Note that alignment will be guaranteed, since we put the command allocated at probe time after the fixed-up SCSI script, which consists of 32 bit words, aligned on a 32 bit boundary. But on a 64bit machine we need 8 byte alignment for hostdata->free, so we add in another 4 bytes to take care of potential misalignment */ (sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size; instance = scsi_register (tpnt, size); if (!instance) return -1; /* FIXME : if we ever support an ISA NCR53c7xx based board, we need to check if the chip is running in a 16 bit mode, and if so unregister it if it is past the 16M (0x1000000) mark */ hostdata = (struct NCR53c7x0_hostdata *) instance->hostdata; hostdata->size = size; hostdata->script_count = script_len / sizeof(u32); hostdata = (struct NCR53c7x0_hostdata *) instance->hostdata; hostdata->board = board; hostdata->chip = chip; if ((hostdata->pci_valid = pci_valid)) { hostdata->pci_bus = pci_bus; hostdata->pci_device_fn = pci_device_fn; } /* * Being memory mapped is more desirable, since * * - Memory accesses may be faster. * * - The destination and source address spaces are the same for * all instructions, meaning we don't have to twiddle dmode or * any other registers. * * So, we try for memory mapped, and if we don't get it, * we go for port mapped, and that failing we tell the user * it can't work. */ if (base) { instance->base = (unsigned char *) (unsigned long) base; /* Check for forced I/O mapping */ if (!(options & OPTION_IO_MAPPED)) { options |= OPTION_MEMORY_MAPPED; ok = 1; } } else { options &= ~OPTION_MEMORY_MAPPED; } if (io_port) { instance->io_port = io_port; options |= OPTION_IO_MAPPED; ok = 1; } else { options &= ~OPTION_IO_MAPPED; } if (!ok) { printk ("scsi%d : not initializing, no I/O or memory mapping known \n", instance->host_no); scsi_unregister (instance); return -1; } instance->irq = irq; instance->dma_channel = dma; hostdata->options = options; hostdata->dsa_len = dsa_len; hostdata->max_cmd_size = max_cmd_size; hostdata->num_cmds = 1; /* Initialize single command */ tmp = (hostdata->script + hostdata->script_count); hostdata->free = ROUNDUP(tmp, void *); hostdata->free->real = tmp; hostdata->free->size = max_cmd_size; hostdata->free->free = NULL; hostdata->free->next = NULL; hostdata->extra_allocate = 0; /* Allocate command start code space */ hostdata->schedule = (chip == 700 || chip == 70066) ? NULL : (u32 *) ((char *)hostdata->free + max_cmd_size);/* * For diagnostic purposes, we don't really care how fast things blaze. * For profiling, we want to access the 800ns resolution system clock, * using a 'C' call on the host processor. * * Therefore, there's no need for the NCR chip to directly manipulate * this data, and we should put it wherever is most convenient for * Linux. */ if (track_events) hostdata->events = (struct NCR53c7x0_event *) (track_events ? vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL); else hostdata->events = NULL; if (hostdata->events) { memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) * track_events); hostdata->event_size = track_events; hostdata->event_index = 0; } else hostdata->event_size = 0; return NCR53c7x0_init(instance);}/* * Function : static int ncr_pci_init(Scsi_Host_Template *tpnt, int board, * int chip, int bus, int device_fn, long long options) * * Purpose : initializes a NCR53c800 family based on the PCI * bus, device, and function location of it. Allows * reprogramming of latency timer and determining addresses * and whether bus mastering, etc. are OK. * * Useful where a new NCR chip is backwards compatible with * a supported chip, but the DEVICE ID has changed so it * doesn't show up when the autoprobe does a pcibios_find_device. * * Inputs : tpnt - Template for this SCSI adapter, board - board level * product, chip - 810, 820, or 825, bus - PCI bus, device_fn - * device and function encoding as used by PCI BIOS calls. * * Returns : 0 on success, -1 on failure. * */static int ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, unsigned char bus, unsigned char device_fn, long long options) { unsigned short vendor_id, device_id, command;#ifdef LINUX_1_2 unsigned long#else unsigned int #endif base, io_port; unsigned char irq, revision; int error, expected_chip; int expected_id = -1, max_revision = -1, min_revision = -1; int i; printk("scsi-ncr53c7,8xx : at PCI bus %d, device %d, function %d\n", bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); if (!pcibios_present()) { printk("scsi-ncr53c7,8xx : not initializing due to lack of PCI BIOS,\n" " try using memory, port, irq override instead.\n"); return -1; } if ((error = pcibios_read_config_word (bus, device_fn, PCI_VENDOR_ID, &vendor_id)) || (error = pcibios_read_config_word (bus, device_fn, PCI_DEVICE_ID, &device_id)) || (error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, &command)) || (error = pcibios_read_config_dword (bus, device_fn, PCI_BASE_ADDRESS_0, &io_port)) || (error = pcibios_read_config_dword (bus, device_fn, PCI_BASE_ADDRESS_1, &base)) || (error = pcibios_read_config_byte (bus, device_fn, PCI_CLASS_REVISION, &revision)) || (error = pcibios_read_config_byte (bus, device_fn, PCI_INTERRUPT_LINE, &irq))) { printk ("scsi-ncr53c7,8xx : error %s not initializing due to error reading configuration space\n" " perhaps you specified an incorrect PCI bus, device, or function.\n" , pcibios_strerror(error)); return -1; } /* If any one ever clones the NCR chips, this will have to change */ if (vendor_id != PCI_VENDOR_ID_NCR) { printk ("scsi-ncr53c7,8xx : not initializing, 0x%04x is not NCR vendor ID\n", (int) vendor_id); return -1; } /* * Bit 0 is the address space indicator and must be one for I/O * space mappings, bit 1 is reserved, discard them after checking * that they have the correct value of 1. */ if (command & PCI_COMMAND_IO) { if ((io_port & 3) != 1) { printk ("scsi-ncr53c7,8xx : disabling I/O mapping since base address 0 (0x%x)\n" " bits 0..1 indicate a non-IO mapping\n", (unsigned) io_port); io_port = 0; } else io_port &= PCI_BASE_ADDRESS_IO_MASK; } else { io_port = 0; } if (command & PCI_COMMAND_MEMORY) { if ((base & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { printk("scsi-ncr53c7,8xx : disabling memory mapping since base address 1\n" " contains a non-memory mapping\n"); base = 0; } else base &= PCI_BASE_ADDRESS_MEM_MASK; } else { base = 0; } if (!io_port && !base) { printk ("scsi-ncr53c7,8xx : not initializing, both I/O and memory mappings disabled\n"); return -1; } if (!(command & PCI_COMMAND_MASTER)) { printk ("scsi-ncr53c7,8xx : not initializing, BUS MASTERING was disabled\n"); return -1; } for (i = 0; i < NPCI_CHIP_IDS; ++i) { if (device_id == pci_chip_ids[i].pci_device_id) { max_revision = pci_chip_ids[i].max_revision; min_revision = pci_chip_ids[i].min_revision; expected_chip = pci_chip_ids[i].chip; } if (chip == pci_chip_ids[i].chip) expected_id = pci_chip_ids[i].pci_device_id; } if (chip && device_id != expected_id) printk ("scsi-ncr53c7,8xx : warning : device id of 0x%04x doesn't\n" " match expected 0x%04x\n", (unsigned int) device_id, (unsigned int) expected_id ); if (max_revision != -1 && revision > max_revision) printk ("scsi-ncr53c7,8xx : warning : revision of %d is greater than %d.\n", (int) revision, max_revision); else if (min_revision != -1 && revision < min_revision) printk ("scsi-ncr53c7,8xx : warning : revision of %d is less than %d.\n", (int) revision, min_revision); if (io_port && check_region (io_port, 128)) { printk ("scsi-ncr53c7,8xx : IO region 0x%x to 0x%x is in use\n", (unsigned) io_port, (unsigned) io_port + 127); return -1; } return normal_init (tpnt, board, chip, (int) base, io_port, (int) irq, DMA_NONE, 1, bus, device_fn, options);}/* * Function : int NCR53c7xx_detect(Scsi_Host_Template *tpnt) * * Purpose : detects and initializes NCR53c7,8x0 SCSI chips * that were autoprobed, overridden on the LILO command line, * or specified at compile time. * * Inputs : tpnt - template for this SCSI adapter * * Returns : number of host adapters detected * */int NCR53c7xx_detect(Scsi_Host_Template *tpnt) { int i; int current_override; int count; /* Number of boards detected */ unsigned char pci_bus, pci_device_fn; static short pci_index=0; /* Device index to PCI BIOS calls */#ifndef LINUX_1_2 tpnt->proc_dir = &proc_scsi_ncr53c7xx;#endif for (current_override = count = 0; current_override < OVERRIDE_LIMIT; ++current_override) { if (overrides[current_override].pci ? !ncr_pci_init (tpnt, overrides[current_override].board,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -