12908d778ab3e244900c310974e1fc1c69066e450James Bottomley/*
22908d778ab3e244900c310974e1fc1c69066e450James Bottomley * Aic94xx SAS/SATA driver register access.
32908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
42908d778ab3e244900c310974e1fc1c69066e450James Bottomley * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
52908d778ab3e244900c310974e1fc1c69066e450James Bottomley * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
62908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
72908d778ab3e244900c310974e1fc1c69066e450James Bottomley * This file is licensed under GPLv2.
82908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
92908d778ab3e244900c310974e1fc1c69066e450James Bottomley * This file is part of the aic94xx driver.
102908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
112908d778ab3e244900c310974e1fc1c69066e450James Bottomley * The aic94xx driver is free software; you can redistribute it and/or
122908d778ab3e244900c310974e1fc1c69066e450James Bottomley * modify it under the terms of the GNU General Public License as
132908d778ab3e244900c310974e1fc1c69066e450James Bottomley * published by the Free Software Foundation; version 2 of the
142908d778ab3e244900c310974e1fc1c69066e450James Bottomley * License.
152908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
162908d778ab3e244900c310974e1fc1c69066e450James Bottomley * The aic94xx driver is distributed in the hope that it will be useful,
172908d778ab3e244900c310974e1fc1c69066e450James Bottomley * but WITHOUT ANY WARRANTY; without even the implied warranty of
182908d778ab3e244900c310974e1fc1c69066e450James Bottomley * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
192908d778ab3e244900c310974e1fc1c69066e450James Bottomley * General Public License for more details.
202908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
212908d778ab3e244900c310974e1fc1c69066e450James Bottomley * You should have received a copy of the GNU General Public License
222908d778ab3e244900c310974e1fc1c69066e450James Bottomley * along with the aic94xx driver; if not, write to the Free Software
232908d778ab3e244900c310974e1fc1c69066e450James Bottomley * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
242908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
252908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
262908d778ab3e244900c310974e1fc1c69066e450James Bottomley
272908d778ab3e244900c310974e1fc1c69066e450James Bottomley#include <linux/pci.h>
282908d778ab3e244900c310974e1fc1c69066e450James Bottomley#include "aic94xx_reg.h"
292908d778ab3e244900c310974e1fc1c69066e450James Bottomley#include "aic94xx.h"
302908d778ab3e244900c310974e1fc1c69066e450James Bottomley
312908d778ab3e244900c310974e1fc1c69066e450James Bottomley/* Writing to device address space.
322908d778ab3e244900c310974e1fc1c69066e450James Bottomley * Offset comes before value to remind that the operation of
332908d778ab3e244900c310974e1fc1c69066e450James Bottomley * this function is *offs = val.
342908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
3581e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic void asd_write_byte(struct asd_ha_struct *asd_ha,
3681e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk			   unsigned long offs, u8 val)
372908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
382908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (unlikely(asd_ha->iospace))
392908d778ab3e244900c310974e1fc1c69066e450James Bottomley		outb(val,
402908d778ab3e244900c310974e1fc1c69066e450James Bottomley		     (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
412908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else
422908d778ab3e244900c310974e1fc1c69066e450James Bottomley		writeb(val, asd_ha->io_handle[0].addr + offs);
432908d778ab3e244900c310974e1fc1c69066e450James Bottomley	wmb();
442908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
452908d778ab3e244900c310974e1fc1c69066e450James Bottomley
4681e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic void asd_write_word(struct asd_ha_struct *asd_ha,
4781e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk			   unsigned long offs, u16 val)
482908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
492908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (unlikely(asd_ha->iospace))
502908d778ab3e244900c310974e1fc1c69066e450James Bottomley		outw(val,
512908d778ab3e244900c310974e1fc1c69066e450James Bottomley		     (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
522908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else
532908d778ab3e244900c310974e1fc1c69066e450James Bottomley		writew(val, asd_ha->io_handle[0].addr + offs);
542908d778ab3e244900c310974e1fc1c69066e450James Bottomley	wmb();
552908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
562908d778ab3e244900c310974e1fc1c69066e450James Bottomley
5781e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic void asd_write_dword(struct asd_ha_struct *asd_ha,
5881e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk			    unsigned long offs, u32 val)
592908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
602908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (unlikely(asd_ha->iospace))
612908d778ab3e244900c310974e1fc1c69066e450James Bottomley		outl(val,
622908d778ab3e244900c310974e1fc1c69066e450James Bottomley		     (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
632908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else
642908d778ab3e244900c310974e1fc1c69066e450James Bottomley		writel(val, asd_ha->io_handle[0].addr + offs);
652908d778ab3e244900c310974e1fc1c69066e450James Bottomley	wmb();
662908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
672908d778ab3e244900c310974e1fc1c69066e450James Bottomley
682908d778ab3e244900c310974e1fc1c69066e450James Bottomley/* Reading from device address space.
692908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
7081e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic u8 asd_read_byte(struct asd_ha_struct *asd_ha, unsigned long offs)
712908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
722908d778ab3e244900c310974e1fc1c69066e450James Bottomley	u8 val;
732908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (unlikely(asd_ha->iospace))
742908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = inb((unsigned long) asd_ha->io_handle[0].addr
752908d778ab3e244900c310974e1fc1c69066e450James Bottomley			  + (offs & 0xFF));
762908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else
772908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = readb(asd_ha->io_handle[0].addr + offs);
782908d778ab3e244900c310974e1fc1c69066e450James Bottomley	rmb();
792908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return val;
802908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
812908d778ab3e244900c310974e1fc1c69066e450James Bottomley
8281e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic u16 asd_read_word(struct asd_ha_struct *asd_ha,
8381e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk			 unsigned long offs)
842908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
852908d778ab3e244900c310974e1fc1c69066e450James Bottomley	u16 val;
862908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (unlikely(asd_ha->iospace))
872908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = inw((unsigned long)asd_ha->io_handle[0].addr
882908d778ab3e244900c310974e1fc1c69066e450James Bottomley			  + (offs & 0xFF));
892908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else
902908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = readw(asd_ha->io_handle[0].addr + offs);
912908d778ab3e244900c310974e1fc1c69066e450James Bottomley	rmb();
922908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return val;
932908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
942908d778ab3e244900c310974e1fc1c69066e450James Bottomley
9581e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic u32 asd_read_dword(struct asd_ha_struct *asd_ha,
9681e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk			  unsigned long offs)
972908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
982908d778ab3e244900c310974e1fc1c69066e450James Bottomley	u32 val;
992908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (unlikely(asd_ha->iospace))
1002908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = inl((unsigned long) asd_ha->io_handle[0].addr
1012908d778ab3e244900c310974e1fc1c69066e450James Bottomley			  + (offs & 0xFF));
1022908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else
1032908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = readl(asd_ha->io_handle[0].addr + offs);
1042908d778ab3e244900c310974e1fc1c69066e450James Bottomley	rmb();
1052908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return val;
1062908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
1072908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1082908d778ab3e244900c310974e1fc1c69066e450James Bottomleystatic inline u32 asd_mem_offs_swa(void)
1092908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
1102908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return 0;
1112908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
1122908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1132908d778ab3e244900c310974e1fc1c69066e450James Bottomleystatic inline u32 asd_mem_offs_swc(void)
1142908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
1152908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return asd_mem_offs_swa() + MBAR0_SWA_SIZE;
1162908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
1172908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1182908d778ab3e244900c310974e1fc1c69066e450James Bottomleystatic inline u32 asd_mem_offs_swb(void)
1192908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
1202908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return asd_mem_offs_swc() + MBAR0_SWC_SIZE + 0x20;
1212908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
1222908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1232908d778ab3e244900c310974e1fc1c69066e450James Bottomley/* We know that the register wanted is in the range
1242908d778ab3e244900c310974e1fc1c69066e450James Bottomley * of the sliding window.
1252908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
12681e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk#define ASD_READ_SW(ww, type, ord)					\
12781e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic type asd_read_##ww##_##ord(struct asd_ha_struct *asd_ha,		\
12881e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk				   u32 reg)				\
12981e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk{									\
13081e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];	\
13181e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk	u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
13281e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk	return asd_read_##ord(asd_ha, (unsigned long)map_offs);	\
1332908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
1342908d778ab3e244900c310974e1fc1c69066e450James Bottomley
13581e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk#define ASD_WRITE_SW(ww, type, ord)					\
13681e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic void asd_write_##ww##_##ord(struct asd_ha_struct *asd_ha,	\
13781e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk				    u32 reg, type val)			\
13881e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk{									\
13981e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];	\
14081e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk	u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
14181e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunk	asd_write_##ord(asd_ha, (unsigned long)map_offs, val);		\
1422908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
1432908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1442908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swa, u8,  byte);
1452908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swa, u16, word);
1462908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swa, u32, dword);
1472908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1482908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swb, u8,  byte);
1492908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swb, u16, word);
1502908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swb, u32, dword);
1512908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1522908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swc, u8,  byte);
1532908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swc, u16, word);
1542908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_SW(swc, u32, dword);
1552908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1562908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swa, u8,  byte);
1572908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swa, u16, word);
1582908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swa, u32, dword);
1592908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1602908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swb, u8,  byte);
1612908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swb, u16, word);
1622908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swb, u32, dword);
1632908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1642908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swc, u8,  byte);
1652908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swc, u16, word);
1662908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_SW(swc, u32, dword);
1672908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1682908d778ab3e244900c310974e1fc1c69066e450James Bottomley/*
1692908d778ab3e244900c310974e1fc1c69066e450James Bottomley * A word about sliding windows:
1702908d778ab3e244900c310974e1fc1c69066e450James Bottomley * MBAR0 is divided into sliding windows A, C and B, in that order.
1712908d778ab3e244900c310974e1fc1c69066e450James Bottomley * SWA starts at offset 0 of MBAR0, up to 0x57, with size 0x58 bytes.
1722908d778ab3e244900c310974e1fc1c69066e450James Bottomley * SWC starts at offset 0x58 of MBAR0, up to 0x60, with size 0x8 bytes.
1732908d778ab3e244900c310974e1fc1c69066e450James Bottomley * From 0x60 to 0x7F, we have a copy of PCI config space 0x60-0x7F.
1742908d778ab3e244900c310974e1fc1c69066e450James Bottomley * SWB starts at offset 0x80 of MBAR0 and extends to the end of MBAR0.
1752908d778ab3e244900c310974e1fc1c69066e450James Bottomley * See asd_init_sw() in aic94xx_hwi.c
1762908d778ab3e244900c310974e1fc1c69066e450James Bottomley *
1772908d778ab3e244900c310974e1fc1c69066e450James Bottomley * We map the most common registers we'd access of the internal 4GB
1782908d778ab3e244900c310974e1fc1c69066e450James Bottomley * host adapter memory space.  If a register/internal memory location
1792908d778ab3e244900c310974e1fc1c69066e450James Bottomley * is wanted which is not mapped, we slide SWB, by paging it,
1802908d778ab3e244900c310974e1fc1c69066e450James Bottomley * see asd_move_swb() in aic94xx_reg.c.
1812908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
1822908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1832908d778ab3e244900c310974e1fc1c69066e450James Bottomley/**
1842908d778ab3e244900c310974e1fc1c69066e450James Bottomley * asd_move_swb -- move sliding window B
1852908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @asd_ha: pointer to host adapter structure
1862908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @reg: register desired to be within range of the new window
1872908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
18881e56ded878aeb8730f18c1d0a70d5face788be3Adrian Bunkstatic void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
1892908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
1902908d778ab3e244900c310974e1fc1c69066e450James Bottomley	u32 base = reg & ~(MBAR0_SWB_SIZE-1);
1912908d778ab3e244900c310974e1fc1c69066e450James Bottomley	pci_write_config_dword(asd_ha->pcidev, PCI_CONF_MBAR0_SWB, base);
1922908d778ab3e244900c310974e1fc1c69066e450James Bottomley	asd_ha->io_handle[0].swb_base = base;
1932908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
1942908d778ab3e244900c310974e1fc1c69066e450James Bottomley
1952908d778ab3e244900c310974e1fc1c69066e450James Bottomleystatic void __asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val)
1962908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
1972908d778ab3e244900c310974e1fc1c69066e450James Bottomley	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0];
1982908d778ab3e244900c310974e1fc1c69066e450James Bottomley	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);
1992908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (io_handle->swa_base <= reg
2002908d778ab3e244900c310974e1fc1c69066e450James Bottomley	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)
2012908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swa_byte (asd_ha, reg,val);
2022908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swb_base <= reg
2032908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)
2042908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swb_byte (asd_ha, reg, val);
2052908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swc_base <= reg
2062908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)
2072908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swc_byte (asd_ha, reg, val);
2082908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else {
2092908d778ab3e244900c310974e1fc1c69066e450James Bottomley		/* Ok, we have to move SWB */
2102908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_move_swb(asd_ha, reg);
2112908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swb_byte (asd_ha, reg, val);
2122908d778ab3e244900c310974e1fc1c69066e450James Bottomley	}
2132908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
2142908d778ab3e244900c310974e1fc1c69066e450James Bottomley
2152908d778ab3e244900c310974e1fc1c69066e450James Bottomley#define ASD_WRITE_REG(type, ord)                                  \
2162908d778ab3e244900c310974e1fc1c69066e450James Bottomleyvoid asd_write_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg, type val)\
2172908d778ab3e244900c310974e1fc1c69066e450James Bottomley{                                                                 \
2182908d778ab3e244900c310974e1fc1c69066e450James Bottomley	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \
2192908d778ab3e244900c310974e1fc1c69066e450James Bottomley	unsigned long flags;                                      \
2202908d778ab3e244900c310974e1fc1c69066e450James Bottomley	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);         \
2212908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_lock_irqsave(&asd_ha->iolock, flags);                \
2222908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (io_handle->swa_base <= reg                            \
2232908d778ab3e244900c310974e1fc1c69066e450James Bottomley	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)        \
2242908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swa_##ord (asd_ha, reg,val);            \
2252908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swb_base <= reg                       \
2262908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)   \
2272908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swb_##ord (asd_ha, reg, val);           \
2282908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swc_base <= reg                       \
2292908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)   \
2302908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swc_##ord (asd_ha, reg, val);           \
2312908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else {                                                    \
2322908d778ab3e244900c310974e1fc1c69066e450James Bottomley		/* Ok, we have to move SWB */                     \
2332908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_move_swb(asd_ha, reg);                        \
2342908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_write_swb_##ord (asd_ha, reg, val);           \
2352908d778ab3e244900c310974e1fc1c69066e450James Bottomley	}                                                         \
2362908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_unlock_irqrestore(&asd_ha->iolock, flags);           \
2372908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
2382908d778ab3e244900c310974e1fc1c69066e450James Bottomley
2392908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_REG(u8, byte);
2402908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_REG(u16,word);
2412908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_WRITE_REG(u32,dword);
2422908d778ab3e244900c310974e1fc1c69066e450James Bottomley
2432908d778ab3e244900c310974e1fc1c69066e450James Bottomleystatic u8 __asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg)
2442908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
2452908d778ab3e244900c310974e1fc1c69066e450James Bottomley	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0];
2462908d778ab3e244900c310974e1fc1c69066e450James Bottomley	u8 val;
2472908d778ab3e244900c310974e1fc1c69066e450James Bottomley	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);
2482908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (io_handle->swa_base <= reg
2492908d778ab3e244900c310974e1fc1c69066e450James Bottomley	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)
2502908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swa_byte (asd_ha, reg);
2512908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swb_base <= reg
2522908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)
2532908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swb_byte (asd_ha, reg);
2542908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swc_base <= reg
2552908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)
2562908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swc_byte (asd_ha, reg);
2572908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else {
2582908d778ab3e244900c310974e1fc1c69066e450James Bottomley		/* Ok, we have to move SWB */
2592908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_move_swb(asd_ha, reg);
2602908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swb_byte (asd_ha, reg);
2612908d778ab3e244900c310974e1fc1c69066e450James Bottomley	}
2622908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return val;
2632908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
2642908d778ab3e244900c310974e1fc1c69066e450James Bottomley
2652908d778ab3e244900c310974e1fc1c69066e450James Bottomley#define ASD_READ_REG(type, ord)                                   \
2662908d778ab3e244900c310974e1fc1c69066e450James Bottomleytype asd_read_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg)   \
2672908d778ab3e244900c310974e1fc1c69066e450James Bottomley{                                                                 \
2682908d778ab3e244900c310974e1fc1c69066e450James Bottomley	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \
2692908d778ab3e244900c310974e1fc1c69066e450James Bottomley	type val;                                                 \
2702908d778ab3e244900c310974e1fc1c69066e450James Bottomley	unsigned long flags;                                      \
2712908d778ab3e244900c310974e1fc1c69066e450James Bottomley	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);         \
2722908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_lock_irqsave(&asd_ha->iolock, flags);                \
2732908d778ab3e244900c310974e1fc1c69066e450James Bottomley	if (io_handle->swa_base <= reg                            \
2742908d778ab3e244900c310974e1fc1c69066e450James Bottomley	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)        \
2752908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swa_##ord (asd_ha, reg);           \
2762908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swb_base <= reg                       \
2772908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)   \
2782908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swb_##ord (asd_ha, reg);           \
2792908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else if (io_handle->swc_base <= reg                       \
2802908d778ab3e244900c310974e1fc1c69066e450James Bottomley		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)   \
2812908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swc_##ord (asd_ha, reg);           \
2822908d778ab3e244900c310974e1fc1c69066e450James Bottomley	else {                                                    \
2832908d778ab3e244900c310974e1fc1c69066e450James Bottomley		/* Ok, we have to move SWB */                     \
2842908d778ab3e244900c310974e1fc1c69066e450James Bottomley		asd_move_swb(asd_ha, reg);                        \
2852908d778ab3e244900c310974e1fc1c69066e450James Bottomley		val = asd_read_swb_##ord (asd_ha, reg);           \
2862908d778ab3e244900c310974e1fc1c69066e450James Bottomley	}                                                         \
2872908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_unlock_irqrestore(&asd_ha->iolock, flags);           \
2882908d778ab3e244900c310974e1fc1c69066e450James Bottomley	return val;                                               \
2892908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
2902908d778ab3e244900c310974e1fc1c69066e450James Bottomley
2912908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_REG(u8, byte);
2922908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_REG(u16,word);
2932908d778ab3e244900c310974e1fc1c69066e450James BottomleyASD_READ_REG(u32,dword);
2942908d778ab3e244900c310974e1fc1c69066e450James Bottomley
2952908d778ab3e244900c310974e1fc1c69066e450James Bottomley/**
2962908d778ab3e244900c310974e1fc1c69066e450James Bottomley * asd_read_reg_string -- read a string of bytes from io space memory
2972908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @asd_ha: pointer to host adapter structure
2982908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @dst: pointer to a destination buffer where data will be written to
2992908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @offs: start offset (register) to read from
3002908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @count: number of bytes to read
3012908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
3022908d778ab3e244900c310974e1fc1c69066e450James Bottomleyvoid asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst,
3032908d778ab3e244900c310974e1fc1c69066e450James Bottomley			 u32 offs, int count)
3042908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
3052908d778ab3e244900c310974e1fc1c69066e450James Bottomley	u8 *p = dst;
3062908d778ab3e244900c310974e1fc1c69066e450James Bottomley	unsigned long flags;
3072908d778ab3e244900c310974e1fc1c69066e450James Bottomley
3082908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_lock_irqsave(&asd_ha->iolock, flags);
3092908d778ab3e244900c310974e1fc1c69066e450James Bottomley	for ( ; count > 0; count--, offs++, p++)
3102908d778ab3e244900c310974e1fc1c69066e450James Bottomley		*p = __asd_read_reg_byte(asd_ha, offs);
3112908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_unlock_irqrestore(&asd_ha->iolock, flags);
3122908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
3132908d778ab3e244900c310974e1fc1c69066e450James Bottomley
3142908d778ab3e244900c310974e1fc1c69066e450James Bottomley/**
3152908d778ab3e244900c310974e1fc1c69066e450James Bottomley * asd_write_reg_string -- write a string of bytes to io space memory
3162908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @asd_ha: pointer to host adapter structure
3172908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @src: pointer to source buffer where data will be read from
3182908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @offs: start offset (register) to write to
3192908d778ab3e244900c310974e1fc1c69066e450James Bottomley * @count: number of bytes to write
3202908d778ab3e244900c310974e1fc1c69066e450James Bottomley */
3212908d778ab3e244900c310974e1fc1c69066e450James Bottomleyvoid asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src,
3222908d778ab3e244900c310974e1fc1c69066e450James Bottomley			  u32 offs, int count)
3232908d778ab3e244900c310974e1fc1c69066e450James Bottomley{
3242908d778ab3e244900c310974e1fc1c69066e450James Bottomley	u8 *p = src;
3252908d778ab3e244900c310974e1fc1c69066e450James Bottomley	unsigned long flags;
3262908d778ab3e244900c310974e1fc1c69066e450James Bottomley
3272908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_lock_irqsave(&asd_ha->iolock, flags);
3282908d778ab3e244900c310974e1fc1c69066e450James Bottomley	for ( ; count > 0; count--, offs++, p++)
3292908d778ab3e244900c310974e1fc1c69066e450James Bottomley		__asd_write_reg_byte(asd_ha, offs, *p);
3302908d778ab3e244900c310974e1fc1c69066e450James Bottomley	spin_unlock_irqrestore(&asd_ha->iolock, flags);
3312908d778ab3e244900c310974e1fc1c69066e450James Bottomley}
332