📄 sym53c8xx.c
字号:
{ FreePages(m); --mp->nump;}static m_pool_s mp0 = {0, ___mp0_getp, ___mp0_freep};#endif /* SCSI_NCR_DYNAMIC_DMA_MAPPING */static void *m_calloc(int size, char *name){ u_long flags; void *m; NCR_LOCK_DRIVER(flags); m = __m_calloc(&mp0, size, name); NCR_UNLOCK_DRIVER(flags); return m;}static void m_free(void *ptr, int size, char *name){ u_long flags; NCR_LOCK_DRIVER(flags); __m_free(&mp0, ptr, size, name); NCR_UNLOCK_DRIVER(flags);}/* * DMAable pools. */#ifndef SCSI_NCR_DYNAMIC_DMA_MAPPING/* Without pci bus iommu support, all the memory is assumed DMAable */#define __m_calloc_dma(b, s, n) m_calloc(s, n)#define __m_free_dma(b, p, s, n) m_free(p, s, n)#define __vtobus(b, p) virt_to_bus(p)#else/* * With pci bus iommu support, we maintain one pool per pcidev and a * hashed reverse table for virtual to bus physical address translations. */static m_addr_t ___dma_getp(m_pool_s *mp){ m_addr_t vp; m_vtob_s *vbp; vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB"); if (vbp) { dma_addr_t daddr; vp = (m_addr_t) pci_alloc_consistent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER, &daddr); if (vp) { int hc = VTOB_HASH_CODE(vp); vbp->vaddr = vp; vbp->baddr = daddr; vbp->next = mp->vtob[hc]; mp->vtob[hc] = vbp; ++mp->nump; return vp; } else __m_free(&mp0, vbp, sizeof(*vbp), "VTOB"); } return 0;}static void ___dma_freep(m_pool_s *mp, m_addr_t m){ m_vtob_s **vbpp, *vbp; int hc = VTOB_HASH_CODE(m); vbpp = &mp->vtob[hc]; while (*vbpp && (*vbpp)->vaddr != m) vbpp = &(*vbpp)->next; if (*vbpp) { vbp = *vbpp; *vbpp = (*vbpp)->next; pci_free_consistent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER, (void *)vbp->vaddr, (dma_addr_t)vbp->baddr); __m_free(&mp0, vbp, sizeof(*vbp), "VTOB"); --mp->nump; }}static inline m_pool_s *___get_dma_pool(m_bush_t bush){ m_pool_s *mp; for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next); return mp;}static m_pool_s *___cre_dma_pool(m_bush_t bush){ m_pool_s *mp; mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL"); if (mp) { bzero(mp, sizeof(*mp)); mp->bush = bush; mp->getp = ___dma_getp; mp->freep = ___dma_freep; mp->next = mp0.next; mp0.next = mp; } return mp;}static void ___del_dma_pool(m_pool_s *p){ struct m_pool **pp = &mp0.next; while (*pp && *pp != p) pp = &(*pp)->next; if (*pp) { *pp = (*pp)->next; __m_free(&mp0, p, sizeof(*p), "MPOOL"); }}static void *__m_calloc_dma(m_bush_t bush, int size, char *name){ u_long flags; struct m_pool *mp; void *m = 0; NCR_LOCK_DRIVER(flags); mp = ___get_dma_pool(bush); if (!mp) mp = ___cre_dma_pool(bush); if (mp) m = __m_calloc(mp, size, name); if (mp && !mp->nump) ___del_dma_pool(mp); NCR_UNLOCK_DRIVER(flags); return m;}static void __m_free_dma(m_bush_t bush, void *m, int size, char *name){ u_long flags; struct m_pool *mp; NCR_LOCK_DRIVER(flags); mp = ___get_dma_pool(bush); if (mp) __m_free(mp, m, size, name); if (mp && !mp->nump) ___del_dma_pool(mp); NCR_UNLOCK_DRIVER(flags);}static m_addr_t __vtobus(m_bush_t bush, void *m){ u_long flags; m_pool_s *mp; int hc = VTOB_HASH_CODE(m); m_vtob_s *vp = 0; m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK; NCR_LOCK_DRIVER(flags); mp = ___get_dma_pool(bush); if (mp) { vp = mp->vtob[hc]; while (vp && (m_addr_t) vp->vaddr != a) vp = vp->next; } NCR_UNLOCK_DRIVER(flags); return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;}#endif /* SCSI_NCR_DYNAMIC_DMA_MAPPING */#define _m_calloc_dma(np, s, n) __m_calloc_dma(np->pdev, s, n)#define _m_free_dma(np, p, s, n) __m_free_dma(np->pdev, p, s, n)#define m_calloc_dma(s, n) _m_calloc_dma(np, s, n)#define m_free_dma(p, s, n) _m_free_dma(np, p, s, n)#define _vtobus(np, p) __vtobus(np->pdev, p)#define vtobus(p) _vtobus(np, p)/* * Deal with DMA mapping/unmapping. */#ifndef SCSI_NCR_DYNAMIC_DMA_MAPPING/* Linux versions prior to pci bus iommu kernel interface */#define __unmap_scsi_data(pdev, cmd) do {; } while (0)#define __map_scsi_single_data(pdev, cmd) (__vtobus(pdev,(cmd)->request_buffer))#define __map_scsi_sg_data(pdev, cmd) ((cmd)->use_sg)#define __sync_scsi_data(pdev, cmd) do {; } while (0)#define scsi_sg_dma_address(sc) vtobus((sc)->address)#define scsi_sg_dma_len(sc) ((sc)->length)#else/* Linux version with pci bus iommu kernel interface *//* To keep track of the dma mapping (sg/single) that has been set */#define __data_mapped SCp.phase#define __data_mapping SCp.have_data_instatic void __unmap_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd){ int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); switch(cmd->__data_mapped) { case 2: pci_unmap_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); break; case 1: pci_unmap_single(pdev, cmd->__data_mapping, cmd->request_bufflen, dma_dir); break; } cmd->__data_mapped = 0;}static u_long __map_scsi_single_data(pcidev_t pdev, Scsi_Cmnd *cmd){ dma_addr_t mapping; int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); if (cmd->request_bufflen == 0) return 0; mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, dma_dir); cmd->__data_mapped = 1; cmd->__data_mapping = mapping; return mapping;}static int __map_scsi_sg_data(pcidev_t pdev, Scsi_Cmnd *cmd){ int use_sg; int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); if (cmd->use_sg == 0) return 0; use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); cmd->__data_mapped = 2; cmd->__data_mapping = use_sg; return use_sg;}static void __sync_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd){ int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); switch(cmd->__data_mapped) { case 2: pci_dma_sync_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); break; case 1: pci_dma_sync_single(pdev, cmd->__data_mapping, cmd->request_bufflen, dma_dir); break; }}#define scsi_sg_dma_address(sc) sg_dma_address(sc)#define scsi_sg_dma_len(sc) sg_dma_len(sc)#endif /* SCSI_NCR_DYNAMIC_DMA_MAPPING */#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->pdev, cmd)#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->pdev, cmd)#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->pdev, cmd)#define sync_scsi_data(np, cmd) __sync_scsi_data(np->pdev, cmd)/* * Print out some buffer. */static void ncr_print_hex(u_char *p, int n){ while (n-- > 0) printk (" %x", *p++);}static void ncr_printl_hex(char *label, u_char *p, int n){ printk("%s", label); ncr_print_hex(p, n); printk (".\n");}/*** Transfer direction**** Until some linux kernel version near 2.3.40, low-level scsi ** drivers were not told about data transfer direction.** We check the existence of this feature that has been expected ** for a _long_ time by all SCSI driver developers by just ** testing against the definition of SCSI_DATA_UNKNOWN. Indeed ** this is a hack, but testing against a kernel version would ** have been a shame. ;-)*/#ifdef SCSI_DATA_UNKNOWN#define scsi_data_direction(cmd) (cmd->sc_data_direction)#else#define SCSI_DATA_UNKNOWN 0#define SCSI_DATA_WRITE 1#define SCSI_DATA_READ 2#define SCSI_DATA_NONE 3static __inline__ int scsi_data_direction(Scsi_Cmnd *cmd){ int direction; switch((int) cmd->cmnd[0]) { case 0x08: /* READ(6) 08 */ case 0x28: /* READ(10) 28 */ case 0xA8: /* READ(12) A8 */ direction = SCSI_DATA_READ; break; case 0x0A: /* WRITE(6) 0A */ case 0x2A: /* WRITE(10) 2A */ case 0xAA: /* WRITE(12) AA */ direction = SCSI_DATA_WRITE; break; default: direction = SCSI_DATA_UNKNOWN; break; } return direction;}#endif /* SCSI_DATA_UNKNOWN *//*** Head of list of NCR boards**** For kernel version < 1.3.70, host is retrieved by its irq level.** For later kernels, the internal host control block address ** (struct ncb) is used as device id parameter of the irq stuff.*/static struct Scsi_Host *first_host = NULL;/*** /proc directory entry and proc_info function*/#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)static struct proc_dir_entry proc_scsi_sym53c8xx = { PROC_SCSI_SYM53C8XX, 9, NAME53C8XX, S_IFDIR | S_IRUGO | S_IXUGO, 2};#endif#ifdef SCSI_NCR_PROC_INFO_SUPPORTstatic int sym53c8xx_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int func);#endif/*** Driver setup.**** This structure is initialized from linux config options.** It can be overridden at boot-up by the boot command line.*/static struct ncr_driver_setup driver_setup = SCSI_NCR_DRIVER_SETUP;#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORTstatic struct ncr_driver_setup driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;# ifdef MODULEchar *sym53c8xx = 0; /* command line passed by insmod */# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)MODULE_PARM(sym53c8xx, "s");# endif# endif#endif/*** Other Linux definitions*/#define SetScsiResult(cmd, h_sts, s_sts) \ cmd->result = (((h_sts) << 16) + ((s_sts) & 0x7f))/* We may have to remind our amnesiac SCSI layer of the reason of the abort */#if 0#define SetScsiAbortResult(cmd) \ SetScsiResult( \ cmd, \ (cmd)->abort_reason == DID_TIME_OUT ? DID_TIME_OUT : DID_ABORT, \ 0xff)#else#define SetScsiAbortResult(cmd) SetScsiResult(cmd, DID_ABORT, 0xff)#endifstatic void sym53c8xx_select_queue_depths( struct Scsi_Host *host, struct scsi_device *devlist);static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);static void sym53c8xx_timeout(unsigned long np);#define initverbose (driver_setup.verbose)#define bootverbose (np->verbose)#ifdef SCSI_NCR_NVRAM_SUPPORTstatic u_char Tekram_sync[16] __initdata = {25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10};#endif /* SCSI_NCR_NVRAM_SUPPORT *//*** Structures used by sym53c8xx_detect/sym53c8xx_pci_init to ** transmit device configuration to the ncr_attach() function.*/typedef struct { int bus; u_char device_fn; u_long base; u_long base_2; u_long io_port; int irq;/* port and reg fields to use INB, OUTB macros */ u_long base_io; volatile struct ncr_reg *reg;} ncr_slot;typedef struct { int type;#define SCSI_NCR_SYMBIOS_NVRAM (1)#define SCSI_NCR_TEKRAM_NVRAM (2)#ifdef SCSI_NCR_NVRAM_SUPPORT union { Symbios_nvram Symbios; Tekram_nvram Tekram; } data;#endif} ncr_nvram;/*** Structure used by sym53c8xx_detect/sym53c8xx_pci_init** to save data on each detected board for ncr_attach().*/typedef struct { pcidev_t pdev; ncr_slot slot; ncr_chip chip; ncr_nvram *nvram; u_char host_id;#ifdef SCSI_NCR_PQS_PDS_SUPPORT u_char pqs_pds;#endif int attach_done;} ncr_device;/*==========================================================**** assert ()****==========================================================**** modified copy from 386bsd:/usr/include/sys/assert.h****----------------------------------------------------------*/#define assert(expression) { \ if (!(expression)) { \ (void)panic( \ "assertion \"%s\" failed: file \"%s\", line %d\n", \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -