📄 lba_pci.c
字号:
/*** PCI Lower Bus Adapter (LBA) manager**** (c) Copyright 1999,2000 Grant Grundler** (c) Copyright 1999,2000 Hewlett-Packard Company**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.****** This module primarily provides access to PCI bus (config/IOport** spaces) on platforms with an SBA/LBA chipset. A/B/C/J/L/N-class** with 4 digit model numbers - eg C3000 (and A400...sigh).**** LBA driver isn't as simple as the Dino driver because:** (a) this chip has substantial bug fixes between revisions** (Only one Dino bug has a software workaround :^( )** (b) has more options which we don't (yet) support (DMA hints, OLARD)** (c) IRQ support lives in the I/O SAPIC driver (not with PCI driver)** (d) play nicely with both PAT and "Legacy" PA-RISC firmware (PDC).** (dino only deals with "Legacy" PDC)**** LBA driver passes the I/O SAPIC HPA to the I/O SAPIC driver.** (I/O SAPIC is integratd in the LBA chip).**** FIXME: Add support to SBA and LBA drivers for DMA hint sets** FIXME: Add support for PCI card hot-plug (OLARD).*/#include <linux/delay.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/spinlock.h>#include <linux/init.h> /* for __init and __devinit *//* #define PCI_DEBUG enable ASSERT */#include <linux/pci.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <asm/byteorder.h>#include <asm/irq.h> /* for struct irq_region support */#include <asm/pdc.h>#include <asm/page.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/hardware.h> /* for register_parisc_driver() stuff */#include <asm/iosapic.h> /* for iosapic_register() */#include <asm/io.h> /* read/write stuff */#ifndef TRUE#define TRUE (1 == 1)#define FALSE (1 == 0)#endif#undef DEBUG_LBA /* general stuff */#undef DEBUG_LBA_PORT /* debug I/O Port access */#undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */#undef DEBUG_LBA_PAT /* debug PCI Resource Mgt code - PDC PAT only */#undef FBB_SUPPORT /* Fast Back-Back xfers - NOT READY YET */#ifdef DEBUG_LBA#define DBG(x...) printk(x)#else#define DBG(x...)#endif#ifdef DEBUG_LBA_PORT#define DBG_PORT(x...) printk(x)#else#define DBG_PORT(x...)#endif#ifdef DEBUG_LBA_CFG#define DBG_CFG(x...) printk(x)#else#define DBG_CFG(x...)#endif#ifdef DEBUG_LBA_PAT#define DBG_PAT(x...) printk(x)#else#define DBG_PAT(x...)#endif/*** Config accessor functions only pass in the 8-bit bus number and not** the 8-bit "PCI Segment" number. Each LBA will be assigned a PCI bus** number based on what firmware wrote into the scratch register.**** The "secondary" bus number is set to this before calling** pci_register_ops(). If any PPB's are present, the scan will** discover them and update the "secondary" and "subordinate"** fields in the pci_bus structure.**** Changes in the configuration *may* result in a different** bus number for each LBA depending on what firmware does.*/#define MODULE_NAME "lba"#define LBA_FUNC_ID 0x0000 /* function id */#define LBA_FCLASS 0x0008 /* function class, bist, header, rev... */#define LBA_CAPABLE 0x0030 /* capabilities register */#define LBA_PCI_CFG_ADDR 0x0040 /* poke CFG address here */#define LBA_PCI_CFG_DATA 0x0048 /* read or write data here */#define LBA_PMC_MTLT 0x0050 /* Firmware sets this - read only. */#define LBA_FW_SCRATCH 0x0058 /* Firmware writes the PCI bus number here. */#define LBA_ERROR_ADDR 0x0070 /* On error, address gets logged here */#define LBA_ARB_MASK 0x0080 /* bit 0 enable arbitration. PAT/PDC enables */#define LBA_ARB_PRI 0x0088 /* firmware sets this. */#define LBA_ARB_MODE 0x0090 /* firmware sets this. */#define LBA_ARB_MTLT 0x0098 /* firmware sets this. */#define LBA_MOD_ID 0x0100 /* Module ID. PDC_PAT_CELL reports 4 */#define LBA_STAT_CTL 0x0108 /* Status & Control */#define LBA_BUS_RESET 0x01 /* Deassert PCI Bus Reset Signal */#define CLEAR_ERRLOG 0x10 /* "Clear Error Log" cmd */#define CLEAR_ERRLOG_ENABLE 0x20 /* "Clear Error Log" Enable */#define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */#define LBA_LMMIO_BASE 0x0200 /* < 4GB I/O address range */#define LBA_LMMIO_MASK 0x0208#define LBA_GMMIO_BASE 0x0210 /* > 4GB I/O address range */#define LBA_GMMIO_MASK 0x0218#define LBA_WLMMIO_BASE 0x0220 /* All < 4GB ranges under the same *SBA* */#define LBA_WLMMIO_MASK 0x0228#define LBA_WGMMIO_BASE 0x0230 /* All > 4GB ranges under the same *SBA* */#define LBA_WGMMIO_MASK 0x0238#define LBA_IOS_BASE 0x0240 /* I/O port space for this LBA */#define LBA_IOS_MASK 0x0248#define LBA_ELMMIO_BASE 0x0250 /* Extra LMMIO range */#define LBA_ELMMIO_MASK 0x0258#define LBA_EIOS_BASE 0x0260 /* Extra I/O port space */#define LBA_EIOS_MASK 0x0268#define LBA_DMA_CTL 0x0278 /* firmware sets this */#define LBA_IBASE 0x0300 /* SBA DMA support */#define LBA_IMASK 0x0308/* FIXME: ignore DMA Hint stuff until we can measure performance */#define LBA_HINT_CFG 0x0310#define LBA_HINT_BASE 0x0380 /* 14 registers at every 8 bytes. *//* ERROR regs are needed for config cycle kluges */#define LBA_ERROR_CONFIG 0x0680#define LBA_SMART_MODE 0x20#define LBA_ERROR_STATUS 0x0688#define LBA_ROPE_CTL 0x06A0#define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic *//* non-postable I/O port space, densely packed */#ifdef __LP64__#define LBA_ASTRO_PORT_BASE (0xfffffffffee00000UL)#else#define LBA_ASTRO_PORT_BASE (0xfee00000UL)#endif/*** lba_device: Per instance Elroy data structure*/struct lba_device { struct pci_hba_data hba; spinlock_t lba_lock; void *iosapic_obj;#ifdef __LP64__ unsigned long lmmio_base; /* PA_VIEW - fixup MEM addresses */ unsigned long gmmio_base; /* PA_VIEW - Not used (yet) */ unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */#endif int flags; /* state/functionality enabled */ int hw_rev; /* HW revision of chip */};static u32 lba_t32;/*** lba "flags"*/#define LBA_FLAG_NO_DMA_DURING_CFG 0x01#define LBA_FLAG_SKIP_PROBE 0x10/* Tape Release 4 == hw_rev 5 */#define LBA_TR4PLUS(d) ((d)->hw_rev > 0x4)#define LBA_DMA_DURING_CFG_DISABLED(d) ((d)->flags & LBA_FLAG_NO_DMA_DURING_CFG)#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE)/* Looks nice and keeps the compiler happy */#define LBA_DEV(d) ((struct lba_device *) (d))/*** Only allow 8 subsidiary busses per LBA** Problem is the PCI bus numbering is globally shared.*/#define LBA_MAX_NUM_BUSES 8/************************************ * LBA register read and write support * * BE WARNED: register writes are posted. * (ie follow writes which must reach HW with a read) */#define READ_U8(addr) __raw_readb(addr)#define READ_U16(addr) __raw_readw(addr)#define READ_U32(addr) __raw_readl(addr)#define WRITE_U8(value, addr) __raw_writeb(value, addr)#define WRITE_U16(value, addr) __raw_writew(value, addr)#define WRITE_U32(value, addr) __raw_writel(value, addr)#define READ_REG8(addr) readb(addr)#define READ_REG16(addr) readw(addr)#define READ_REG32(addr) readl(addr)#define READ_REG64(addr) readq(addr)#define WRITE_REG8(value, addr) writeb(value, addr)#define WRITE_REG16(value, addr) writew(value, addr)#define WRITE_REG32(value, addr) writel(value, addr)#define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8))#define LBA_CFG_BUS(tok) ((u8) ((tok)>>16))#define LBA_CFG_DEV(tok) ((u8) ((tok)>>11) & 0x1f)#define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7)/*** Extract LBA (Rope) number from HPA** REVISIT: 16 ropes for Stretch/Ike?*/#define ROPES_PER_SBA 8#define LBA_NUM(x) ((((unsigned long) x) >> 13) & (ROPES_PER_SBA-1))static voidlba_dump_res(struct resource *r, int d){ int i; if (NULL == r) return; printk(KERN_DEBUG "(%p)", r->parent); for (i = d; i ; --i) printk(" "); printk(KERN_DEBUG "%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags); lba_dump_res(r->child, d+2); lba_dump_res(r->sibling, d);}/*** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex** workaround for cfg cycles:** -- preserve LBA state** -- LBA_FLAG_NO_DMA_DURING_CFG workaround** -- turn on smart mode** -- probe with config writes before doing config reads** -- check ERROR_STATUS** -- clear ERROR_STATUS** -- restore LBA state**** The workaround is only used for device discovery.*/static intlba_device_present( u8 bus, u8 dfn, struct lba_device *d){ u8 first_bus = d->hba.hba_bus->secondary; u8 last_sub_bus = d->hba.hba_bus->subordinate;#if 0/* FIXME - see below in this function */ u8 dev = PCI_SLOT(dfn); u8 func = PCI_FUNC(dfn);#endif ASSERT(bus >= first_bus); ASSERT(bus <= last_sub_bus); ASSERT((bus - first_bus) < LBA_MAX_NUM_BUSES); if ((bus < first_bus) || (bus > last_sub_bus) || ((bus - first_bus) >= LBA_MAX_NUM_BUSES)) { /* devices that fall into any of these cases won't get claimed */ return(FALSE); }#if 0/*** FIXME: Need to implement code to fill the devices bitmap based** on contents of the local pci_bus tree "data base".** pci_register_ops() walks the bus for us and builds the tree.** For now, always do the config cycle.*/ bus -= first_bus; return (((d->devices[bus][dev]) >> func) & 0x1);#else return TRUE;#endif}#define LBA_CFG_SETUP(d, tok) { \ /* Save contents of error config register. */ \ error_config = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG); \\ /* Save contents of status control register. */ \ status_control = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); \\ /* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA \ ** arbitration for full bus walks. \ */ \ if (LBA_DMA_DURING_CFG_DISABLED(d)) { \ /* Save contents of arb mask register. */ \ arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK); \\ /* \ * Turn off all device arbitration bits (i.e. everything \ * except arbitration enable bit). \ */ \ WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK); \ } \\ /* \ * Set the smart mode bit so that master aborts don't cause \ * LBA to go into PCI fatal mode (required). \ */ \ WRITE_REG32(error_config | LBA_SMART_MODE, d->hba.base_addr + LBA_ERROR_CONFIG); \}#define LBA_CFG_PROBE(d, tok) { \ /* \ * Setup Vendor ID write and read back the address register \ * to make sure that LBA is the bus master. \ */ \ WRITE_REG32(tok | PCI_VENDOR_ID, (d)->hba.base_addr + LBA_PCI_CFG_ADDR);\ /* \ * Read address register to ensure that LBA is the bus master, \ * which implies that DMA traffic has stopped when DMA arb is off. \ */ \ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ /* \ * Generate a cfg write cycle (will have no affect on \ * Vendor ID register since read-only). \ */ \ WRITE_REG32(~0, (d)->hba.base_addr + LBA_PCI_CFG_DATA); \ /* \ * Make sure write has completed before proceeding further, \ * i.e. before setting clear enable. \ */ \ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \}/* * HPREVISIT: * -- Can't tell if config cycle got the error. * * OV bit is broken until rev 4.0, so can't use OV bit and * LBA_ERROR_LOG_ADDR to tell if error belongs to config cycle. * * As of rev 4.0, no longer need the error check. * * -- Even if we could tell, we still want to return -1 * for **ANY** error (not just master abort). * * -- Only clear non-fatal errors (we don't want to bring * LBA out of pci-fatal mode). * * Actually, there is still a race in which * we could be clearing a fatal error. We will * live with this during our initial bus walk * until rev 4.0 (no driver activity during * initial bus walk). The initial bus walk * has race conditions concerning the use of * smart mode as well. */#define LBA_MASTER_ABORT_ERROR 0xc#define LBA_FATAL_ERROR 0x10#define LBA_CFG_MASTER_ABORT_CHECK(d, base, tok, error) { \ u32 error_status = 0; \ /* \ * Set clear enable (CE) bit. Unset by HW when new \ * errors are logged -- LBA HW ERS section 14.3.3). \ */ \ WRITE_REG32(status_control | CLEAR_ERRLOG_ENABLE, base + LBA_STAT_CTL); \ error_status = READ_REG32(base + LBA_ERROR_STATUS); \ if ((error_status & 0x1f) != 0) { \ /* \ * Fail the config read request. \ */ \ error = 1; \ if ((error_status & LBA_FATAL_ERROR) == 0) { \ /* \ * Clear error status (if fatal bit not set) by setting \ * clear error log bit (CL). \ */ \ WRITE_REG32(status_control | CLEAR_ERRLOG, base + LBA_STAT_CTL); \ } \ } \}#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR)#define LBA_CFG_ADDR_SETUP(d, addr) { \ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ /* \ * HPREVISIT: \ * -- Potentially could skip this once DMA bug fixed. \ * \ * Read address register to ensure that LBA is the bus master, \ * which implies that DMA traffic has stopped when DMA arb is off. \ */ \ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \}#define LBA_CFG_RESTORE(d, base) { \ /* \ * Restore status control register (turn off clear enable). \ */ \ WRITE_REG32(status_control, base + LBA_STAT_CTL); \ /* \ * Restore error config register (turn off smart mode). \ */ \ WRITE_REG32(error_config, base + LBA_ERROR_CONFIG); \ if (LBA_DMA_DURING_CFG_DISABLED(d)) { \ /* \ * Restore arb mask register (reenables DMA arbitration). \ */ \ WRITE_REG32(arb_mask, base + LBA_ARB_MASK); \ } \}static unsigned intlba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size){ u32 data = ~0; int error = 0; u32 arb_mask = 0; /* used by LBA_CFG_SETUP/RESTORE */ u32 error_config = 0; /* used by LBA_CFG_SETUP/RESTORE */ u32 status_control = 0; /* used by LBA_CFG_SETUP/RESTORE */ ASSERT((size == sizeof(u8)) || (size == sizeof(u16)) || (size == sizeof(u32))); if ((size != sizeof(u8)) && (size != sizeof(u16)) && (size != sizeof(u32))) { return(data); } LBA_CFG_SETUP(d, tok); LBA_CFG_PROBE(d, tok); LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error); if (!error) { LBA_CFG_ADDR_SETUP(d, tok | reg); switch (size) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -