📄 sym53c8xx_comm.h
字号:
#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)/*==========================================================**** SCSI data 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 *//*==========================================================**** 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;#endif#define initverbose (driver_setup.verbose)#define bootverbose (np->verbose)/*==========================================================**** Big/Little endian support.**** If the NCR uses big endian addressing mode over the ** PCI, actual io register addresses for byte and word ** accesses must be changed according to lane routing.** Btw, ncr_offb() and ncr_offw() macros only apply to ** constants and so donnot generate bloated code.**** If the CPU and the NCR use same endian-ness adressing,** no byte reordering is needed for script patching.** Macro cpu_to_scr() is to be used for script patching.** Macro scr_to_cpu() is to be used for getting a DWORD ** from the script.****==========================================================*/#if defined(SCSI_NCR_BIG_ENDIAN)#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3))#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2))#else#define ncr_offb(o) (o)#define ncr_offw(o) (o)#endif#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)#define cpu_to_scr(dw) cpu_to_le32(dw)#define scr_to_cpu(dw) le32_to_cpu(dw)#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)#define cpu_to_scr(dw) cpu_to_be32(dw)#define scr_to_cpu(dw) be32_to_cpu(dw)#else#define cpu_to_scr(dw) (dw)#define scr_to_cpu(dw) (dw)#endif/*==========================================================**** Access to the controller chip.**** If NCR_IOMAPPED is defined, the driver will use ** normal IOs instead of the MEMORY MAPPED IO method ** recommended by PCI specifications.** If all PCI bridges, host brigdes and architectures ** would have been correctly designed for PCI, this ** option would be useless.**** If the CPU and the NCR use same endian-ness adressing,** no byte reordering is needed for accessing chip io ** registers. Functions suffixed by '_raw' are assumed ** to access the chip over the PCI without doing byte ** reordering. Functions suffixed by '_l2b' are ** assumed to perform little-endian to big-endian byte ** reordering, those suffixed by '_b2l' blah, blah,** blah, ...****==========================================================*/#if defined(NCR_IOMAPPED)/*** IO mapped only input / ouput*/#define INB_OFF(o) inb (np->base_io + ncr_offb(o))#define OUTB_OFF(o, val) outb ((val), np->base_io + ncr_offb(o))#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)#define INW_OFF(o) inw_l2b (np->base_io + ncr_offw(o))#define INL_OFF(o) inl_l2b (np->base_io + (o))#define OUTW_OFF(o, val) outw_b2l ((val), np->base_io + ncr_offw(o))#define OUTL_OFF(o, val) outl_b2l ((val), np->base_io + (o))#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)#define INW_OFF(o) inw_b2l (np->base_io + ncr_offw(o))#define INL_OFF(o) inl_b2l (np->base_io + (o))#define OUTW_OFF(o, val) outw_l2b ((val), np->base_io + ncr_offw(o))#define OUTL_OFF(o, val) outl_l2b ((val), np->base_io + (o))#else#define INW_OFF(o) inw_raw (np->base_io + ncr_offw(o))#define INL_OFF(o) inl_raw (np->base_io + (o))#define OUTW_OFF(o, val) outw_raw ((val), np->base_io + ncr_offw(o))#define OUTL_OFF(o, val) outl_raw ((val), np->base_io + (o))#endif /* ENDIANs */#else /* defined NCR_IOMAPPED *//*** MEMORY mapped IO input / output*/#define INB_OFF(o) readb((char *)np->reg + ncr_offb(o))#define OUTB_OFF(o, val) writeb((val), (char *)np->reg + ncr_offb(o))#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)#define INW_OFF(o) readw_l2b((char *)np->reg + ncr_offw(o))#define INL_OFF(o) readl_l2b((char *)np->reg + (o))#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->reg + ncr_offw(o))#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->reg + (o))#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)#define INW_OFF(o) readw_b2l((char *)np->reg + ncr_offw(o))#define INL_OFF(o) readl_b2l((char *)np->reg + (o))#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->reg + ncr_offw(o))#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->reg + (o))#else#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o))#define INL_OFF(o) readl_raw((char *)np->reg + (o))#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o))#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o))#endif#endif /* defined NCR_IOMAPPED */#define INB(r) INB_OFF (offsetof(struct ncr_reg,r))#define INW(r) INW_OFF (offsetof(struct ncr_reg,r))#define INL(r) INL_OFF (offsetof(struct ncr_reg,r))#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val))#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val))#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val))/*** Set bit field ON, OFF */#define OUTONB(r, m) OUTB(r, INB(r) | (m))#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))#define OUTONW(r, m) OUTW(r, INW(r) | (m))#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))#define OUTONL(r, m) OUTL(r, INL(r) | (m))#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))/*==========================================================**** Structures used by the detection routine to transmit ** device configuration to the 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;/*==========================================================**** Structure used to store the NVRAM content.****==========================================================*/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 detection routine to save data on ** each detected board for 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;static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device);/*==========================================================**** NVRAM detection and reading.** ** Currently supported:** - 24C16 EEPROM with both Symbios and Tekram layout.** - 93C46 EEPROM with Tekram layout.****==========================================================*/#ifdef SCSI_NCR_NVRAM_SUPPORT/* * 24C16 EEPROM reading. * * GPOI0 - data in/data out * GPIO1 - clock * Symbios NVRAM wiring now also used by Tekram. */#define SET_BIT 0#define CLR_BIT 1#define SET_CLK 2#define CLR_CLK 3/* * Set/clear data/clock bit in GPIO0 */static void __initS24C16_set_bit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode){ UDELAY (5); switch (bit_mode){ case SET_BIT: *gpreg |= write_bit; break; case CLR_BIT: *gpreg &= 0xfe; break; case SET_CLK: *gpreg |= 0x02; break; case CLR_CLK: *gpreg &= 0xfd; break; } OUTB (nc_gpreg, *gpreg); UDELAY (5);}/* * Send START condition to NVRAM to wake it up. */static void __init S24C16_start(ncr_slot *np, u_char *gpreg){ S24C16_set_bit(np, 1, gpreg, SET_BIT); S24C16_set_bit(np, 0, gpreg, SET_CLK); S24C16_set_bit(np, 0, gpreg, CLR_BIT); S24C16_set_bit(np, 0, gpreg, CLR_CLK);}/* * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!! */static void __init S24C16_stop(ncr_slot *np, u_char *gpreg){ S24C16_set_bit(np, 0, gpreg, SET_CLK); S24C16_set_bit(np, 1, gpreg, SET_BIT);}/* * Read or write a bit to the NVRAM, * read if GPIO0 input else write if GPIO0 output */static void __init S24C16_do_bit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg){ S24C16_set_bit(np, write_bit, gpreg, SET_BIT); S24C16_set_bit(np, 0, gpreg, SET_CLK); if (read_bit) *read_bit = INB (nc_gpreg); S24C16_set_bit(np, 0, gpreg, CLR_CLK); S24C16_set_bit(np, 0, gpreg, CLR_BIT);}/* * Output an ACK to the NVRAM after reading, * change GPIO0 to output and when done back to an input */static void __initS24C16_write_ack(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl){ OUTB (nc_gpcntl, *gpcntl & 0xfe); S24C16_do_bit(np, 0, write_bit, gpreg); OUTB (nc_gpcntl, *gpcntl);}/* * Input an ACK from NVRAM after writing, * change GPIO0 to input and when done back to an output */static void __init S24C16_read_ack(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl){ OUTB (nc_gpcntl, *gpcntl | 0x01); S24C16_do_bit(np, read_bit, 1, gpreg); OUTB (nc_gpcntl, *gpcntl);}/* * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK, * GPIO0 must already be set as an output */static void __init S24C16_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl){ int x; for (x = 0; x < 8; x++) S24C16_do_bit(np, 0, (write_data >> (7 - x)) & 0x01, gpreg); S24C16_read_ack(np, ack_data, gpreg, gpcntl);}/* * READ a byte from the NVRAM and then send an ACK to say we have got it, * GPIO0 must already be set as an input */static void __init S24C16_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl){ int x; u_char read_bit; *read_data = 0; for (x = 0; x < 8; x++) { S24C16_do_bit(np, &read_bit, 1, gpreg); *read_data |= ((read_bit & 0x01) << (7 - x)); } S24C16_write_ack(np, ack_data, gpreg, gpcntl);}/* * Read 'len' bytes starting at 'offset'. */static int __init sym_read_S24C16_nvram (ncr_slot *np, int offset, u_char *data, int len){ u_char gpcntl, gpreg; u_char old_gpcntl, old_gpreg; u_char ack_data; int retv = 1; int x; /* save current state of GPCNTL and GPREG */ old_gpreg = INB (nc_gpreg); old_gpcntl = INB (nc_gpcntl); gpcntl = old_gpcntl & 0xfc; /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ OUTB (nc_gpreg, old_gpreg); OUTB (nc_gpcntl, gpcntl); /* this is to set NVRAM into a known state with GPIO0/1 both low */ gpreg = old_gpreg; S24C16_set_bit(np, 0, &gpreg, CLR_CLK); S24C16_set_bit(np, 0, &gpreg, CLR_BIT); /* now set NVRAM inactive with GPIO0/1 both high */ S24C16_stop(np, &gpreg); /* activate NVRAM */ S24C16_start(np, &gpreg); /* write device code and random address MSB */ S24C16_write_byte(np, &ack_data, 0xa0 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); if (ack_data & 0x01) goto out; /* write random address LSB */ S24C16_write_byte(np, &ack_data, offset & 0xff, &gpreg, &gpcntl); if (ack_data & 0x01) goto out; /* regenerate START state to set up for reading */ S24C16_start(np, &gpreg); /* rewrite device code and address MSB with read bit set (lsb = 0x01) */ S24C16_write_byte(np, &ack_data, 0xa1 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); if (ack_data & 0x01) goto out; /* now set up GPIO0 for inputting data */ gpcntl |= 0x01; OUTB (nc_gpcntl, gpcntl); /* input all requested data - only part of total NVRAM */ for (x = 0; x < len; x++) S24C16_read_byte(np, &data[x], (x == (len-1)), &gpreg, &gpcntl); /* finally put NVRAM back in inactive mode */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -