^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * iohelper.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * helper for define functions to access ISDN hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * supported are memory mapped IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * indirect port IO (one port for address, one for data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author Karsten Keil <keil@isdn4linux.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #ifndef _IOHELPER_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define _IOHELPER_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) typedef u8 (read_reg_func)(void *hwp, u8 offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) typedef void (write_reg_func)(void *hwp, u8 offset, u8 value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) typedef void (fifo_func)(void *hwp, u8 offset, u8 *datap, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct _ioport {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u32 port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) u32 ale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define IOFUNC_IO(name, hws, ap) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static u8 Read##name##_IO(void *p, u8 off) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return inb(hw->ap.port + off); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static void Write##name##_IO(void *p, u8 off, u8 val) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) outb(val, hw->ap.port + off); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static void ReadFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) insb(hw->ap.port + off, dp, size); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void WriteFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) outsb(hw->ap.port + off, dp, size); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define IOFUNC_IND(name, hws, ap) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static u8 Read##name##_IND(void *p, u8 off) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) outb(off, hw->ap.ale); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return inb(hw->ap.port); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static void Write##name##_IND(void *p, u8 off, u8 val) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) outb(off, hw->ap.ale); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) outb(val, hw->ap.port); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void ReadFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) outb(off, hw->ap.ale); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) insb(hw->ap.port, dp, size); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void WriteFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) outb(off, hw->ap.ale); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) outsb(hw->ap.port, dp, size); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define IOFUNC_MEMIO(name, hws, typ, adr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static u8 Read##name##_MIO(void *p, u8 off) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return readb(((typ *)hw->adr) + off); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void Write##name##_MIO(void *p, u8 off, u8 val) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) writeb(val, ((typ *)hw->adr) + off); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void ReadFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) while (size--) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *dp++ = readb(((typ *)hw->adr) + off); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void WriteFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct hws *hw = p; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) while (size--) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) writeb(*dp++, ((typ *)hw->adr) + off); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define ASSIGN_FUNC(typ, name, dest) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dest.read_reg = &Read##name##_##typ; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dest.write_reg = &Write##name##_##typ; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dest.read_fifo = &ReadFiFo##name##_##typ; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dest.write_fifo = &WriteFiFo##name##_##typ; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define ASSIGN_FUNC_IPAC(typ, target) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ASSIGN_FUNC(typ, ISAC, target.isac); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ASSIGN_FUNC(typ, IPAC, target); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #endif