lba_pci.c

来自「linux 内核源代码」· C语言 代码 · 共 1,593 行 · 第 1/4 页

C
1,593
字号
/*****  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 */#include <linux/pci.h>#include <linux/ioport.h>#include <linux/slab.h>#include <asm/byteorder.h>#include <asm/pdc.h>#include <asm/pdcpat.h>#include <asm/page.h>#include <asm/system.h>#include <asm/ropes.h>#include <asm/hardware.h>	/* for register_parisc_driver() stuff */#include <asm/parisc-device.h>#include <asm/io.h>		/* read/write stuff */#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"/* non-postable I/O port space, densely packed */#define LBA_PORT_BASE	(PCI_F_EXTEND | 0xfee00000UL)static void __iomem *astro_iop_base __read_mostly;static u32 lba_t32;/* lba flags */#define LBA_FLAG_SKIP_PROBE	0x10#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_IOC	8#define LBA_NUM(x)    ((((unsigned long) x) >> 13) & (ROPES_PER_IOC-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]/%lx\n", r,		(long)r->start, (long)r->end, 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**	-- prevent any DMA from occurring**	-- 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 int lba_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 ((bus < first_bus) ||	    (bus > last_sub_bus) ||	    ((bus - first_bus) >= LBA_MAX_NUM_BUSES)) {		return 0;	}	return 1;}#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.					\    */									\	/* 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);	\    /*									\     * 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);			\	/*								\	 * 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 = ~0U;	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 */	LBA_CFG_SETUP(d, tok);	LBA_CFG_PROBE(d, tok);	LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);	if (!error) {		void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;		LBA_CFG_ADDR_SETUP(d, tok | reg);		switch (size) {		case 1: data = (u32) READ_REG8(data_reg + (reg & 3)); break;		case 2: data = (u32) READ_REG16(data_reg+ (reg & 2)); break;		case 4: data = READ_REG32(data_reg); break;		}	}	LBA_CFG_RESTORE(d, d->hba.base_addr);	return(data);}static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data){	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;	u32 tok = LBA_CFG_TOK(local_bus, devfn);	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;	if ((pos > 255) || (devfn > 255))		return -EINVAL;/* FIXME: B2K/C3600 workaround is always use old method... */	/* if (!LBA_SKIP_PROBE(d)) */ {		/* original - Generate config cycle on broken elroy		  with risk we will miss PCI bus errors. */		*data = lba_rd_cfg(d, tok, pos, size);		DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data);		return 0;	}	if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) {		DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __FUNCTION__, tok, pos);		/* either don't want to look or know device isn't present. */		*data = ~0U;		return(0);	}	/* Basic Algorithm	** Should only get here on fully working LBA rev.	** This is how simple the code should have been.	*/	LBA_CFG_ADDR_SETUP(d, tok | pos);	switch(size) {	case 1: *data = READ_REG8 (data_reg + (pos & 3)); break;	case 2: *data = READ_REG16(data_reg + (pos & 2)); break;	case 4: *data = READ_REG32(data_reg); break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?