root/drivers/scsi/aic94xx/aic94xx_reg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. asd_write_byte
  2. asd_write_word
  3. asd_write_dword
  4. asd_read_byte
  5. asd_read_word
  6. asd_read_dword
  7. asd_mem_offs_swa
  8. asd_mem_offs_swc
  9. asd_mem_offs_swb
  10. asd_move_swb
  11. __asd_write_reg_byte
  12. __asd_read_reg_byte
  13. asd_read_reg_string
  14. asd_write_reg_string

   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  */
  17 static 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 
  28 static 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 
  39 static 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  */
  52 static 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 
  64 static 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 
  77 static 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 
  90 static inline u32 asd_mem_offs_swa(void)
  91 {
  92         return 0;
  93 }
  94 
  95 static inline u32 asd_mem_offs_swc(void)
  96 {
  97         return asd_mem_offs_swa() + MBAR0_SWA_SIZE;
  98 }
  99 
 100 static 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)                                      \
 109 static 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)                                     \
 118 static 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 
 126 ASD_READ_SW(swa, u8,  byte);
 127 ASD_READ_SW(swa, u16, word);
 128 ASD_READ_SW(swa, u32, dword);
 129 
 130 ASD_READ_SW(swb, u8,  byte);
 131 ASD_READ_SW(swb, u16, word);
 132 ASD_READ_SW(swb, u32, dword);
 133 
 134 ASD_READ_SW(swc, u8,  byte);
 135 ASD_READ_SW(swc, u16, word);
 136 ASD_READ_SW(swc, u32, dword);
 137 
 138 ASD_WRITE_SW(swa, u8,  byte);
 139 ASD_WRITE_SW(swa, u16, word);
 140 ASD_WRITE_SW(swa, u32, dword);
 141 
 142 ASD_WRITE_SW(swb, u8,  byte);
 143 ASD_WRITE_SW(swb, u16, word);
 144 ASD_WRITE_SW(swb, u32, dword);
 145 
 146 ASD_WRITE_SW(swc, u8,  byte);
 147 ASD_WRITE_SW(swc, u16, word);
 148 ASD_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  */
 170 static 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 
 177 static 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)                                  \
 198 void 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 
 221 ASD_WRITE_REG(u8, byte);
 222 ASD_WRITE_REG(u16,word);
 223 ASD_WRITE_REG(u32,dword);
 224 
 225 static 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)                                   \
 248 type 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 
 273 ASD_READ_REG(u8, byte);
 274 ASD_READ_REG(u16,word);
 275 ASD_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  */
 284 void 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  */
 303 void 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 }

/* [<][>][^][v][top][bottom][index][help] */