pci_8255.c
来自「CNC 的开放码,EMC2 V2.2.8版」· C语言 代码 · 共 373 行
C
373 行
#include "rtapi.h"#include "rtapi_app.h"#include "hal.h"#include "rtapi_string.h"#define MAX 16int io[MAX] = {0,};int dir[MAX] = {0,};RTAPI_MP_ARRAY_INT(io, MAX, "I/O addresses of 8255s");RTAPI_MP_ARRAY_INT(dir, MAX, "I/O direction of 8255s");static int comp_id;union inv { hal_bit_t *not_; hal_bit_t invert; };struct port { hal_bit_t *a[8]; hal_bit_t *b[8]; hal_bit_t *c[8]; union inv ai[8]; union inv bi[8]; union inv ci[8]; hal_u32_t dir_; hal_u32_t ioaddr;};struct state { struct port ports[3]; hal_bit_t *relay; hal_bit_t relay_invert; hal_u32_t ioaddr;};static void read(struct port *inst, long period);static void write(struct port *inst, long period);static void write_relay(struct state *inst, long period);static void write_all(struct state *inst, long period);static void read_all(struct state *inst, long period);static void extra_cleanup(void);#include <asm/io.h>#define SHIFT 4static inline void WRITE(int value, hal_u32_t base, int offset) { // int *mem = (int*) base; outb(value, base + SHIFT*offset); // mem[offset] = value;}static inline int READ(hal_u32_t base, int offset) { return inb(base + SHIFT*offset); // int *mem = (int*) base; // return mem[offset];}static int export(char *prefix, struct port *inst, int ioaddr, int dir) { char buf[HAL_NAME_LEN + 2]; int r = 0; int i; hal_pin_dir_t direction; int sz = sizeof(struct port); memset(inst, 0, sz); inst->dir_ = dir; inst->ioaddr = ioaddr; if(inst->dir_ & 8) direction = HAL_OUT; else direction = HAL_IN; for(i=0; i<8; i++) { r = hal_pin_bit_newf(direction, &(inst->a[i]), comp_id, "%s.a%d", prefix, i); if(r != 0) return r; if(direction == HAL_OUT) { r = hal_pin_bit_newf(direction, &(inst->ai[i].not_), comp_id, "%s.a%d-not", prefix, i); } else { r = hal_param_bit_newf(HAL_RW, &(inst->ai[i].invert), comp_id, "%s.a%d-invert", prefix, i); } if(r != 0) return r; } if(inst->dir_ & 2) direction = HAL_OUT; else direction = HAL_IN; for(i=0; i<8; i++) { r = hal_pin_bit_newf(direction, &(inst->b[i]), comp_id, "%s.b%d", prefix, i); if(r != 0) return r; if(direction == HAL_OUT) { r = hal_pin_bit_newf(direction, &(inst->bi[i].not_), comp_id, "%s.b%d-not", prefix, i); } else { r = hal_param_bit_newf(HAL_RW, &(inst->bi[i].invert), comp_id, "%s.b%d-invert", prefix, i); } if(r != 0) return r; } for(i=0; i<8; i++) { if(i < 4) { if(inst->dir_ & 1) direction = HAL_OUT; else direction = HAL_IN; } else { if(inst->dir_ & 4) direction = HAL_OUT; else direction = HAL_IN; } r = hal_pin_bit_newf(direction, &(inst->c[i]), comp_id, "%s.c%d", prefix, i); if(r != 0) return r; if(direction == HAL_OUT) { r = hal_pin_bit_newf(direction, &(inst->ci[i].not_), comp_id, "%s.c%d-not", prefix, i); } else { r = hal_param_bit_newf(HAL_RW, &(inst->ci[i].invert), comp_id, "%s.c%d-invert", prefix, i); } if(r != 0) return r; } r = hal_param_u32_newf(HAL_RO, &(inst->dir_), comp_id, "%s.dir", prefix); if(r != 0) return r; rtapi_snprintf(buf, HAL_NAME_LEN, "%s.read", prefix); r = hal_export_funct(buf, (void(*)(void *inst, long))read, inst, 0, 0, comp_id); if(r != 0) return r; rtapi_snprintf(buf, HAL_NAME_LEN, "%s.write", prefix); r = hal_export_funct(buf, (void(*)(void *inst, long))write, inst, 0, 0, comp_id); if(r != 0) return r; rtapi_print_msg(RTAPI_MSG_DBG, "registering %s ... %x %x\n", prefix, (dir&3) | ((dir & 0xc) << 1) | 0x80, ioaddr); WRITE((dir&3) | ((dir & 0xc) << 1) | 0x80, ioaddr, 3); return 0;}static struct state *inst = 0;static int count = 0;static void write_relay(struct state *inst, long period) { int val = (!*inst->relay) ^ (!inst->relay_invert); // relay is active low if(val) { WRITE(0, inst->ioaddr, 3); } else { WRITE(0x10, inst->ioaddr, 3); }}static void write_all(struct state *inst, long period) { int i; for(i=0; i<count; i++) { write_relay(&inst[i], period); write(&inst[i].ports[0], period); write(&inst[i].ports[1], period); write(&inst[i].ports[2], period); }}static void read_all(struct state *inst, long period) { int i; for(i=0; i<count; i++) { read(&inst[i].ports[0], period); read(&inst[i].ports[1], period); read(&inst[i].ports[2], period); }}static int get_count(void);int rtapi_app_main(void) { int r = 0; int i, j; char buf[HAL_NAME_LEN + 2]; count = get_count(); comp_id = hal_init("pci_8255"); if(comp_id < 0) return comp_id; inst = hal_malloc(count * sizeof(struct state)); if(!inst) goto out_error; for(i=0; i<count; i++) { // PIB reset low, 15 cycle operation WRITE(0x30, io[i], 0); // relay off (active-high), cs low WRITE(0x10, io[i]+3, 0); // relay, CS# as outputs WRITE(0x11, io[i]+2, 0); for(j=0; j<3; j++) { rtapi_snprintf(buf, HAL_NAME_LEN, "pci8255.%d.%d", i, j); r = export(buf, &inst[i].ports[j], io[i] + 0xc0 + 16*j, (dir[i] >> (4*j)) & 0xf); if(r != 0) goto out_error; } hal_pin_bit_newf(HAL_IN, &(inst[i].relay), comp_id, "pci8255.%d.relay", i); hal_param_bit_newf(HAL_RW, &(inst[i].relay_invert), comp_id, "pci8255.%d.relay-invert", i); rtapi_snprintf(buf, HAL_NAME_LEN, "pci8255.%d.write-relay", i); r = hal_export_funct(buf, (void(*)(void *inst, long))write_relay, &inst[i], 0, 0, comp_id); r = hal_param_u32_newf(HAL_RO, &(inst->ioaddr), comp_id, "pci8255.%d.io-addr", i); inst->ioaddr = io[i]; if(r != 0) return r; } r = hal_export_funct("pci8255.read-all", (void(*)(void *inst, long))read_all, inst, 0, 0, comp_id); r = hal_export_funct("pci8255.write-all", (void(*)(void *inst, long))write_all, inst, 0, 0, comp_id);out_error: if(r) { extra_cleanup(); hal_exit(comp_id); } else { hal_ready(comp_id); } return r;}void rtapi_app_exit(void) { extra_cleanup(); hal_exit(comp_id);}#define FUNCTION(name) static void name(struct state *inst, long period)#define EXTRA_CLEANUP() static void extra_cleanup(void)#define fperiod (period * 1e-9)#define a(i) (*inst->a[i])#define b(i) (*inst->b[i])#define c(i) (*inst->c[i])#define ai_invert(i) (inst->ai[i].invert)#define bi_invert(i) (inst->bi[i].invert)#define ci_invert(i) (inst->ci[i].invert)#define ai_not(i) (*inst->ai[i].not_)#define bi_not(i) (*inst->bi[i].not_)#define ci_not(i) (*inst->ci[i].not_)#define ioaddr (inst->ioaddr)#define dir_ (inst->dir_)#include "rtapi_errno.h"int get_count(void) { int i = 0; for(i=0; i<MAX && io[i]; i++) { /* Nothing */ } return i;}#if 0static int extra_setup(void) { int byte; rtapi_print_msg(RTAPI_MSG_DBG, "requesting I/O region 0x%x\n", io[extra_arg]); if(!rtapi_request_region(io[extra_arg], 16, "pci_8255")) { // set this I/O port to 0 so that EXTRA_CLEANUP does not release the IO // ports that were never requested. io[extra_arg] = 0; return -EBUSY; } dir_ = dir[extra_arg/3] & 0xf; ioaddr = io[extra_arg/3]; byte = (1<<7) + ((dir_ & 8) ? (1<<4) : 0) + ((dir_ & 4) ? (1<<3) : 0) + ((dir_ & 2) ? (1<<1) : 0) + ((dir_ & 1) ? (1<<0) : 0); WRITE(byte, ioaddr, 3); return 0;}#endifstatic void extra_cleanup(void) {#if 0 int i; for(i=0; i < MAX && io[i]; i++) { rtapi_print_msg(RTAPI_MSG_DBG, "releasing I/O region 0x%x\n", io[i]); rtapi_release_region(io[i], 16); }#endif}static void write(struct port *inst, long period) { int p = dir_; static int first=1; int i; if((p & 5) == 0) { int byte = 0; for(i=0; i<8; i++) { int t = (c(i) != 0) ^ (ci_invert(i) != 0); if(t) byte |= 1 << i; } WRITE(byte, ioaddr, 2); if(first) rtapi_print_msg(RTAPI_MSG_DBG, "write: 2a %02x\n", byte); } else if((p & 5) == 4) { int byte = 0; for(i=0; i<4; i++) { int t = (c(i) != 0) ^ (ci_invert(i) != 0); if(t) byte |= 1 << i; } WRITE(byte, ioaddr, 2); if(first) rtapi_print_msg(RTAPI_MSG_DBG, "write: 2b %02x\n", byte); } else if((p & 5) == 1) { int byte = 0; for(i=4; i<8; i++) { int t = (c(i) != 0) ^ (ci_invert(i) != 0); if(t) byte |= 1 << i; } WRITE(byte, ioaddr, 2); if(first) rtapi_print_msg(RTAPI_MSG_DBG, "write: 2c %02x\n", byte); } if((p & 2) == 0) { int byte = 0; for(i=0; i<8; i++) { int t = (b(i) != 0) ^ (bi_invert(i) != 0); if(t) byte |= 1 << i; } WRITE(byte, ioaddr, 1); if(first) rtapi_print_msg(RTAPI_MSG_DBG, "write: 1 %02x\n", byte); } if((p & 8) == 0) { int byte = 0; for(i=0; i<8; i++) { int t = (a(i) != 0) ^ (ai_invert(i) != 0); if(t) byte |= 1 << i; } WRITE(byte, ioaddr, 0); if(first) rtapi_print_msg(RTAPI_MSG_DBG, "write: 0 %02x\n", byte); } first = 0;}static void read(struct port *inst, long period) { int p = dir_; int i; if((p & 5) == 5) { int byte = READ(ioaddr, 2); for(i=0; i<8; i++) { int t = (byte & (1<<i)) != 0; c(i) = t; ci_not(i) = !t; } } else if((p & 5) == 4) { int byte = READ(ioaddr, 2); for(i=4; i<8; i++) { int t = (byte & (1<<i)) != 0; c(i) = t; ci_not(i) = !t; } } else if((p & 5) == 1) { int byte = READ(ioaddr, 2); for(i=0; i<4; i++) { int t = (byte & (1<<i)) != 0; c(i) = t; ci_not(i) = !t; } } if(p & 2) { int byte = READ(ioaddr, 1); for(i=0; i<8; i++) { int t = (byte & (1<<i)) != 0; b(i) = t; bi_not(i) = !t; } } if(p & 8) { int byte = READ(ioaddr, 0); for(i=0; i<8; i++) { int t = (byte & (1<<i)) != 0; a(i) = t; ai_not(i) = !t; } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?