cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aic94xx_reg.c (10156B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Aic94xx SAS/SATA driver register access.
      4 *
      5 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
      6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
      7 */
      8
      9#include <linux/pci.h>
     10#include "aic94xx_reg.h"
     11#include "aic94xx.h"
     12
     13/* Writing to device address space.
     14 * Offset comes before value to remind that the operation of
     15 * this function is *offs = val.
     16 */
     17static void asd_write_byte(struct asd_ha_struct *asd_ha,
     18			   unsigned long offs, u8 val)
     19{
     20	if (unlikely(asd_ha->iospace))
     21		outb(val,
     22		     (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
     23	else
     24		writeb(val, asd_ha->io_handle[0].addr + offs);
     25	wmb();
     26}
     27
     28static void asd_write_word(struct asd_ha_struct *asd_ha,
     29			   unsigned long offs, u16 val)
     30{
     31	if (unlikely(asd_ha->iospace))
     32		outw(val,
     33		     (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
     34	else
     35		writew(val, asd_ha->io_handle[0].addr + offs);
     36	wmb();
     37}
     38
     39static void asd_write_dword(struct asd_ha_struct *asd_ha,
     40			    unsigned long offs, u32 val)
     41{
     42	if (unlikely(asd_ha->iospace))
     43		outl(val,
     44		     (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
     45	else
     46		writel(val, asd_ha->io_handle[0].addr + offs);
     47	wmb();
     48}
     49
     50/* Reading from device address space.
     51 */
     52static u8 asd_read_byte(struct asd_ha_struct *asd_ha, unsigned long offs)
     53{
     54	u8 val;
     55	if (unlikely(asd_ha->iospace))
     56		val = inb((unsigned long) asd_ha->io_handle[0].addr
     57			  + (offs & 0xFF));
     58	else
     59		val = readb(asd_ha->io_handle[0].addr + offs);
     60	rmb();
     61	return val;
     62}
     63
     64static u16 asd_read_word(struct asd_ha_struct *asd_ha,
     65			 unsigned long offs)
     66{
     67	u16 val;
     68	if (unlikely(asd_ha->iospace))
     69		val = inw((unsigned long)asd_ha->io_handle[0].addr
     70			  + (offs & 0xFF));
     71	else
     72		val = readw(asd_ha->io_handle[0].addr + offs);
     73	rmb();
     74	return val;
     75}
     76
     77static u32 asd_read_dword(struct asd_ha_struct *asd_ha,
     78			  unsigned long offs)
     79{
     80	u32 val;
     81	if (unlikely(asd_ha->iospace))
     82		val = inl((unsigned long) asd_ha->io_handle[0].addr
     83			  + (offs & 0xFF));
     84	else
     85		val = readl(asd_ha->io_handle[0].addr + offs);
     86	rmb();
     87	return val;
     88}
     89
     90static inline u32 asd_mem_offs_swa(void)
     91{
     92	return 0;
     93}
     94
     95static inline u32 asd_mem_offs_swc(void)
     96{
     97	return asd_mem_offs_swa() + MBAR0_SWA_SIZE;
     98}
     99
    100static inline u32 asd_mem_offs_swb(void)
    101{
    102	return asd_mem_offs_swc() + MBAR0_SWC_SIZE + 0x20;
    103}
    104
    105/* We know that the register wanted is in the range
    106 * of the sliding window.
    107 */
    108#define ASD_READ_SW(ww, type, ord)					\
    109static type asd_read_##ww##_##ord(struct asd_ha_struct *asd_ha,		\
    110				   u32 reg)				\
    111{									\
    112	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];	\
    113	u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
    114	return asd_read_##ord(asd_ha, (unsigned long)map_offs);	\
    115}
    116
    117#define ASD_WRITE_SW(ww, type, ord)					\
    118static void asd_write_##ww##_##ord(struct asd_ha_struct *asd_ha,	\
    119				    u32 reg, type val)			\
    120{									\
    121	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];	\
    122	u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
    123	asd_write_##ord(asd_ha, (unsigned long)map_offs, val);		\
    124}
    125
    126ASD_READ_SW(swa, u8,  byte);
    127ASD_READ_SW(swa, u16, word);
    128ASD_READ_SW(swa, u32, dword);
    129
    130ASD_READ_SW(swb, u8,  byte);
    131ASD_READ_SW(swb, u16, word);
    132ASD_READ_SW(swb, u32, dword);
    133
    134ASD_READ_SW(swc, u8,  byte);
    135ASD_READ_SW(swc, u16, word);
    136ASD_READ_SW(swc, u32, dword);
    137
    138ASD_WRITE_SW(swa, u8,  byte);
    139ASD_WRITE_SW(swa, u16, word);
    140ASD_WRITE_SW(swa, u32, dword);
    141
    142ASD_WRITE_SW(swb, u8,  byte);
    143ASD_WRITE_SW(swb, u16, word);
    144ASD_WRITE_SW(swb, u32, dword);
    145
    146ASD_WRITE_SW(swc, u8,  byte);
    147ASD_WRITE_SW(swc, u16, word);
    148ASD_WRITE_SW(swc, u32, dword);
    149
    150/*
    151 * A word about sliding windows:
    152 * MBAR0 is divided into sliding windows A, C and B, in that order.
    153 * SWA starts at offset 0 of MBAR0, up to 0x57, with size 0x58 bytes.
    154 * SWC starts at offset 0x58 of MBAR0, up to 0x60, with size 0x8 bytes.
    155 * From 0x60 to 0x7F, we have a copy of PCI config space 0x60-0x7F.
    156 * SWB starts at offset 0x80 of MBAR0 and extends to the end of MBAR0.
    157 * See asd_init_sw() in aic94xx_hwi.c
    158 *
    159 * We map the most common registers we'd access of the internal 4GB
    160 * host adapter memory space.  If a register/internal memory location
    161 * is wanted which is not mapped, we slide SWB, by paging it,
    162 * see asd_move_swb() in aic94xx_reg.c.
    163 */
    164
    165/**
    166 * asd_move_swb -- move sliding window B
    167 * @asd_ha: pointer to host adapter structure
    168 * @reg: register desired to be within range of the new window
    169 */
    170static void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
    171{
    172	u32 base = reg & ~(MBAR0_SWB_SIZE-1);
    173	pci_write_config_dword(asd_ha->pcidev, PCI_CONF_MBAR0_SWB, base);
    174	asd_ha->io_handle[0].swb_base = base;
    175}
    176
    177static void __asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val)
    178{
    179	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0];
    180	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);
    181	if (io_handle->swa_base <= reg
    182	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)
    183		asd_write_swa_byte (asd_ha, reg,val);
    184	else if (io_handle->swb_base <= reg
    185		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)
    186		asd_write_swb_byte (asd_ha, reg, val);
    187	else if (io_handle->swc_base <= reg
    188		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)
    189		asd_write_swc_byte (asd_ha, reg, val);
    190	else {
    191		/* Ok, we have to move SWB */
    192		asd_move_swb(asd_ha, reg);
    193		asd_write_swb_byte (asd_ha, reg, val);
    194	}
    195}
    196
    197#define ASD_WRITE_REG(type, ord)                                  \
    198void asd_write_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg, type val)\
    199{                                                                 \
    200	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \
    201	unsigned long flags;                                      \
    202	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);         \
    203	spin_lock_irqsave(&asd_ha->iolock, flags);                \
    204	if (io_handle->swa_base <= reg                            \
    205	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)        \
    206		asd_write_swa_##ord (asd_ha, reg,val);            \
    207	else if (io_handle->swb_base <= reg                       \
    208		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)   \
    209		asd_write_swb_##ord (asd_ha, reg, val);           \
    210	else if (io_handle->swc_base <= reg                       \
    211		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)   \
    212		asd_write_swc_##ord (asd_ha, reg, val);           \
    213	else {                                                    \
    214		/* Ok, we have to move SWB */                     \
    215		asd_move_swb(asd_ha, reg);                        \
    216		asd_write_swb_##ord (asd_ha, reg, val);           \
    217	}                                                         \
    218	spin_unlock_irqrestore(&asd_ha->iolock, flags);           \
    219}
    220
    221ASD_WRITE_REG(u8, byte);
    222ASD_WRITE_REG(u16,word);
    223ASD_WRITE_REG(u32,dword);
    224
    225static u8 __asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg)
    226{
    227	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0];
    228	u8 val;
    229	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);
    230	if (io_handle->swa_base <= reg
    231	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)
    232		val = asd_read_swa_byte (asd_ha, reg);
    233	else if (io_handle->swb_base <= reg
    234		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)
    235		val = asd_read_swb_byte (asd_ha, reg);
    236	else if (io_handle->swc_base <= reg
    237		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)
    238		val = asd_read_swc_byte (asd_ha, reg);
    239	else {
    240		/* Ok, we have to move SWB */
    241		asd_move_swb(asd_ha, reg);
    242		val = asd_read_swb_byte (asd_ha, reg);
    243	}
    244	return val;
    245}
    246
    247#define ASD_READ_REG(type, ord)                                   \
    248type asd_read_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg)   \
    249{                                                                 \
    250	struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \
    251	type val;                                                 \
    252	unsigned long flags;                                      \
    253	BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);         \
    254	spin_lock_irqsave(&asd_ha->iolock, flags);                \
    255	if (io_handle->swa_base <= reg                            \
    256	    && reg < io_handle->swa_base + MBAR0_SWA_SIZE)        \
    257		val = asd_read_swa_##ord (asd_ha, reg);           \
    258	else if (io_handle->swb_base <= reg                       \
    259		 && reg < io_handle->swb_base + MBAR0_SWB_SIZE)   \
    260		val = asd_read_swb_##ord (asd_ha, reg);           \
    261	else if (io_handle->swc_base <= reg                       \
    262		 && reg < io_handle->swc_base + MBAR0_SWC_SIZE)   \
    263		val = asd_read_swc_##ord (asd_ha, reg);           \
    264	else {                                                    \
    265		/* Ok, we have to move SWB */                     \
    266		asd_move_swb(asd_ha, reg);                        \
    267		val = asd_read_swb_##ord (asd_ha, reg);           \
    268	}                                                         \
    269	spin_unlock_irqrestore(&asd_ha->iolock, flags);           \
    270	return val;                                               \
    271}
    272
    273ASD_READ_REG(u8, byte);
    274ASD_READ_REG(u16,word);
    275ASD_READ_REG(u32,dword);
    276
    277/**
    278 * asd_read_reg_string -- read a string of bytes from io space memory
    279 * @asd_ha: pointer to host adapter structure
    280 * @dst: pointer to a destination buffer where data will be written to
    281 * @offs: start offset (register) to read from
    282 * @count: number of bytes to read
    283 */
    284void asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst,
    285			 u32 offs, int count)
    286{
    287	u8 *p = dst;
    288	unsigned long flags;
    289
    290	spin_lock_irqsave(&asd_ha->iolock, flags);
    291	for ( ; count > 0; count--, offs++, p++)
    292		*p = __asd_read_reg_byte(asd_ha, offs);
    293	spin_unlock_irqrestore(&asd_ha->iolock, flags);
    294}
    295
    296/**
    297 * asd_write_reg_string -- write a string of bytes to io space memory
    298 * @asd_ha: pointer to host adapter structure
    299 * @src: pointer to source buffer where data will be read from
    300 * @offs: start offset (register) to write to
    301 * @count: number of bytes to write
    302 */
    303void asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src,
    304			  u32 offs, int count)
    305{
    306	u8 *p = src;
    307	unsigned long flags;
    308
    309	spin_lock_irqsave(&asd_ha->iolock, flags);
    310	for ( ; count > 0; count--, offs++, p++)
    311		__asd_write_reg_byte(asd_ha, offs, *p);
    312	spin_unlock_irqrestore(&asd_ha->iolock, flags);
    313}