linux/drivers/char/ipmi/ipmi_si_port_io.c
Corey Minyard 243ac21035 ipmi: Add or fix SPDX-License-Identifier in all files
And get rid of the license text that is no longer necessary.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Alistair Popple <alistair@popple.id.au>
Cc: Jeremy Kerr <jk@ozlabs.org>
Cc: Joel Stanley <joel@jms.id.au>
Cc: Rocky Craig <rocky.craig@hp.com>
2018-02-27 07:42:51 -06:00

114 lines
2.5 KiB
C

// SPDX-License-Identifier: GPL-2.0+
#include <linux/io.h>
#include "ipmi_si.h"
static unsigned char port_inb(const struct si_sm_io *io, unsigned int offset)
{
unsigned int addr = io->addr_data;
return inb(addr + (offset * io->regspacing));
}
static void port_outb(const struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
unsigned int addr = io->addr_data;
outb(b, addr + (offset * io->regspacing));
}
static unsigned char port_inw(const struct si_sm_io *io, unsigned int offset)
{
unsigned int addr = io->addr_data;
return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
}
static void port_outw(const struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
unsigned int addr = io->addr_data;
outw(b << io->regshift, addr + (offset * io->regspacing));
}
static unsigned char port_inl(const struct si_sm_io *io, unsigned int offset)
{
unsigned int addr = io->addr_data;
return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
}
static void port_outl(const struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
unsigned int addr = io->addr_data;
outl(b << io->regshift, addr+(offset * io->regspacing));
}
static void port_cleanup(struct si_sm_io *io)
{
unsigned int addr = io->addr_data;
int idx;
if (addr) {
for (idx = 0; idx < io->io_size; idx++)
release_region(addr + idx * io->regspacing,
io->regsize);
}
}
int ipmi_si_port_setup(struct si_sm_io *io)
{
unsigned int addr = io->addr_data;
int idx;
if (!addr)
return -ENODEV;
io->io_cleanup = port_cleanup;
/*
* Figure out the actual inb/inw/inl/etc routine to use based
* upon the register size.
*/
switch (io->regsize) {
case 1:
io->inputb = port_inb;
io->outputb = port_outb;
break;
case 2:
io->inputb = port_inw;
io->outputb = port_outw;
break;
case 4:
io->inputb = port_inl;
io->outputb = port_outl;
break;
default:
dev_warn(io->dev, "Invalid register size: %d\n",
io->regsize);
return -EINVAL;
}
/*
* Some BIOSes reserve disjoint I/O regions in their ACPI
* tables. This causes problems when trying to register the
* entire I/O region. Therefore we must register each I/O
* port separately.
*/
for (idx = 0; idx < io->io_size; idx++) {
if (request_region(addr + idx * io->regspacing,
io->regsize, DEVICE_NAME) == NULL) {
/* Undo allocations */
while (idx--)
release_region(addr + idx * io->regspacing,
io->regsize);
return -EIO;
}
}
return 0;
}