0001
0002
0003 #include <linux/io.h>
0004 #include "ipmi_si.h"
0005
0006 static unsigned char port_inb(const struct si_sm_io *io, unsigned int offset)
0007 {
0008 unsigned int addr = io->addr_data;
0009
0010 return inb(addr + (offset * io->regspacing));
0011 }
0012
0013 static void port_outb(const struct si_sm_io *io, unsigned int offset,
0014 unsigned char b)
0015 {
0016 unsigned int addr = io->addr_data;
0017
0018 outb(b, addr + (offset * io->regspacing));
0019 }
0020
0021 static unsigned char port_inw(const struct si_sm_io *io, unsigned int offset)
0022 {
0023 unsigned int addr = io->addr_data;
0024
0025 return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
0026 }
0027
0028 static void port_outw(const struct si_sm_io *io, unsigned int offset,
0029 unsigned char b)
0030 {
0031 unsigned int addr = io->addr_data;
0032
0033 outw(b << io->regshift, addr + (offset * io->regspacing));
0034 }
0035
0036 static unsigned char port_inl(const struct si_sm_io *io, unsigned int offset)
0037 {
0038 unsigned int addr = io->addr_data;
0039
0040 return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
0041 }
0042
0043 static void port_outl(const struct si_sm_io *io, unsigned int offset,
0044 unsigned char b)
0045 {
0046 unsigned int addr = io->addr_data;
0047
0048 outl(b << io->regshift, addr+(offset * io->regspacing));
0049 }
0050
0051 static void port_cleanup(struct si_sm_io *io)
0052 {
0053 unsigned int addr = io->addr_data;
0054 int idx;
0055
0056 if (addr) {
0057 for (idx = 0; idx < io->io_size; idx++)
0058 release_region(addr + idx * io->regspacing,
0059 io->regsize);
0060 }
0061 }
0062
0063 int ipmi_si_port_setup(struct si_sm_io *io)
0064 {
0065 unsigned int addr = io->addr_data;
0066 int idx;
0067
0068 if (!addr)
0069 return -ENODEV;
0070
0071
0072
0073
0074
0075 switch (io->regsize) {
0076 case 1:
0077 io->inputb = port_inb;
0078 io->outputb = port_outb;
0079 break;
0080 case 2:
0081 io->inputb = port_inw;
0082 io->outputb = port_outw;
0083 break;
0084 case 4:
0085 io->inputb = port_inl;
0086 io->outputb = port_outl;
0087 break;
0088 default:
0089 dev_warn(io->dev, "Invalid register size: %d\n",
0090 io->regsize);
0091 return -EINVAL;
0092 }
0093
0094
0095
0096
0097
0098
0099
0100 for (idx = 0; idx < io->io_size; idx++) {
0101 if (request_region(addr + idx * io->regspacing,
0102 io->regsize, SI_DEVICE_NAME) == NULL) {
0103
0104 while (idx--)
0105 release_region(addr + idx * io->regspacing,
0106 io->regsize);
0107 return -EIO;
0108 }
0109 }
0110
0111 io->io_cleanup = port_cleanup;
0112
0113 return 0;
0114 }