// Copyright (C) 2008 Jeff Epler // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "rtapi.h" #include "rtapi_app.h" #include "hal.h" #include "rtapi_string.h" #define MAX 16 MODULE_LICENSE("GPL"); int 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 #define SHIFT 4 static 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 + 1]; 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, sizeof(buf), "%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, sizeof(buf), "%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> (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, sizeof(buf), "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