root/drivers/char/ipmi/ipmi_si_port_io.c

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

DEFINITIONS

This source file includes following definitions.
  1. port_inb
  2. port_outb
  3. port_inw
  4. port_outw
  5. port_inl
  6. port_outl
  7. port_cleanup
  8. ipmi_si_port_setup

   1 // SPDX-License-Identifier: GPL-2.0+
   2 
   3 #include <linux/io.h>
   4 #include "ipmi_si.h"
   5 
   6 static unsigned char port_inb(const struct si_sm_io *io, unsigned int offset)
   7 {
   8         unsigned int addr = io->addr_data;
   9 
  10         return inb(addr + (offset * io->regspacing));
  11 }
  12 
  13 static void port_outb(const struct si_sm_io *io, unsigned int offset,
  14                       unsigned char b)
  15 {
  16         unsigned int addr = io->addr_data;
  17 
  18         outb(b, addr + (offset * io->regspacing));
  19 }
  20 
  21 static unsigned char port_inw(const struct si_sm_io *io, unsigned int offset)
  22 {
  23         unsigned int addr = io->addr_data;
  24 
  25         return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
  26 }
  27 
  28 static void port_outw(const struct si_sm_io *io, unsigned int offset,
  29                       unsigned char b)
  30 {
  31         unsigned int addr = io->addr_data;
  32 
  33         outw(b << io->regshift, addr + (offset * io->regspacing));
  34 }
  35 
  36 static unsigned char port_inl(const struct si_sm_io *io, unsigned int offset)
  37 {
  38         unsigned int addr = io->addr_data;
  39 
  40         return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
  41 }
  42 
  43 static void port_outl(const struct si_sm_io *io, unsigned int offset,
  44                       unsigned char b)
  45 {
  46         unsigned int addr = io->addr_data;
  47 
  48         outl(b << io->regshift, addr+(offset * io->regspacing));
  49 }
  50 
  51 static void port_cleanup(struct si_sm_io *io)
  52 {
  53         unsigned int addr = io->addr_data;
  54         int          idx;
  55 
  56         if (addr) {
  57                 for (idx = 0; idx < io->io_size; idx++)
  58                         release_region(addr + idx * io->regspacing,
  59                                        io->regsize);
  60         }
  61 }
  62 
  63 int ipmi_si_port_setup(struct si_sm_io *io)
  64 {
  65         unsigned int addr = io->addr_data;
  66         int          idx;
  67 
  68         if (!addr)
  69                 return -ENODEV;
  70 
  71         /*
  72          * Figure out the actual inb/inw/inl/etc routine to use based
  73          * upon the register size.
  74          */
  75         switch (io->regsize) {
  76         case 1:
  77                 io->inputb = port_inb;
  78                 io->outputb = port_outb;
  79                 break;
  80         case 2:
  81                 io->inputb = port_inw;
  82                 io->outputb = port_outw;
  83                 break;
  84         case 4:
  85                 io->inputb = port_inl;
  86                 io->outputb = port_outl;
  87                 break;
  88         default:
  89                 dev_warn(io->dev, "Invalid register size: %d\n",
  90                          io->regsize);
  91                 return -EINVAL;
  92         }
  93 
  94         /*
  95          * Some BIOSes reserve disjoint I/O regions in their ACPI
  96          * tables.  This causes problems when trying to register the
  97          * entire I/O region.  Therefore we must register each I/O
  98          * port separately.
  99          */
 100         for (idx = 0; idx < io->io_size; idx++) {
 101                 if (request_region(addr + idx * io->regspacing,
 102                                    io->regsize, SI_DEVICE_NAME) == NULL) {
 103                         /* Undo allocations */
 104                         while (idx--)
 105                                 release_region(addr + idx * io->regspacing,
 106                                                io->regsize);
 107                         return -EIO;
 108                 }
 109         }
 110 
 111         io->io_cleanup = port_cleanup;
 112 
 113         return 0;
 114 }

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