I wrote some EMC2 HAL driver to use the generic linux GPIO API for driving the device. The thing works like the parport HAL, but is more flexible, as any GPIO-port or GPIO-expansion-card supported by linux can be used for bitbanging the stepper signals and so on.
There's a "cfg" module parameter, which configures which GPIO ports are used. The default string probably is not very useful, but you get the idea of what it does. Some comments? Index: emc2/src/hal/drivers/hal_linux_gpio.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ emc2/src/hal/drivers/hal_linux_gpio.c 2008-07-05 17:49:55.000000000 +0200 @@ -0,0 +1,341 @@ +/* + * Linux GPIO HAL driver + * + * Copyright 2008 Michael Buesch <[EMAIL PROTECTED]> + * + * Derived from the HAL skeleton: + * Copyright John Kasunich and Martin Kuhnle. + * + * Licensed under the GNU/GPL version 2. + */ + +#ifndef RTAPI +# error hal_linux_gpio needs RTAPI, check makefile and flags +#endif + +#include "rtapi.h" +#include "rtapi_app.h" +#include "hal.h" + +#include <linux/gpio.h> + + +#define PFX "hal-linux-gpio: " + +#define MAX_NR_IN_PINS 256 +#define MAX_NR_OUT_PINS 256 + +enum pin_type { + PIN_UNUSED = 0, + PIN_OUT, + PIN_IN, +}; + +struct gpio_pin { + /* The HAL state of the pin */ + hal_bit_t *pin; + /* Inverted */ + hal_bit_t *inv_pin; + /* The hardware state of the pin. This is only valid + * for OUT pins. */ + bool hw_state; + /* Type of the pin */ + enum pin_type type; + /* The GPIO number of the pin */ + unsigned int gpio; +}; + +struct port_state { + struct gpio_pin out[MAX_NR_OUT_PINS]; + struct gpio_pin in[MAX_NR_IN_PINS]; +}; + +static struct port_state *pstate; /* The GPIO ports state */ +static int comp_id; /* component ID */ + +/* Configuration string */ +static char *cfg = "1=out,2=out,3=out,4=out,5=in,6=in,7=in,8=in"; +RTAPI_MP_STRING(cfg, "config string"); + + +/* Port write callback */ +static void write_port(void *d, long period) +{ + struct port_state *port = d; + struct gpio_pin *pin; + unsigned int i; + bool state; + + for (i = 0; i < MAX_NR_OUT_PINS; i++) { + pin = &(port->out[i]); + + if (pin->type == PIN_UNUSED) + break; + state = !!(*(pin->pin)); + if (*(pin->inv_pin)) + state = !state; + if (state == pin->hw_state) + continue; /* Nothing to do */ + + gpio_set_value(pin->gpio, state); + pin->hw_state = state; + } +} + +/* Port read callback */ +static void read_port(void *d, long period) +{ + struct port_state *port = d; + struct gpio_pin *pin; + unsigned int i; + bool state; + + for (i = 0; i < MAX_NR_IN_PINS; i++) { + pin = &(port->in[i]); + + if (pin->type == PIN_UNUSED) + break; + state = !!gpio_get_value(pin->gpio); + *(pin->pin) = state; + *(pin->inv_pin) = !state; + } +} + +static void free_gpio_pins(struct port_state *port) +{ + struct gpio_pin *pin; + unsigned int i; + + for (i = 0; i < MAX_NR_IN_PINS; i++) { + pin = &(port->in[i]); + if (pin->type == PIN_UNUSED) + break; + gpio_free(pin->gpio); + } + for (i = 0; i < MAX_NR_OUT_PINS; i++) { + pin = &(port->out[i]); + if (pin->type == PIN_UNUSED) + break; + gpio_free(pin->gpio); + } +} + +static int export_functions(struct port_state *port) +{ + char name[HAL_NAME_LEN]; + int err; + + snprintf(name, HAL_NAME_LEN, "linux-gpio.%d.read", 0); + err = hal_export_funct(name, read_port, port, 0, 0, comp_id); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Failed to register READ function\n"); + err = -ENOMEM; + goto out; + } + + snprintf(name, HAL_NAME_LEN, "linux-gpio.%d.write", 0); + err = hal_export_funct(name, write_port, port, 0, 0, comp_id); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Failed to register WRITE function\n"); + err = -ENOMEM; + goto out; + } + + err = 0; +out: + return err; +} + +static int build_port(struct port_state *port, const char *config) +{ + const char *end; + char one_cfg[24]; /* temporary config for one pin */ + char direction[sizeof(one_cfg)]; + unsigned int gpio; + int res, err; + unsigned int in_idx = 0; + unsigned int out_idx = 0; + struct gpio_pin *pin; + + /* First parse the pin config and register the pins. */ + while (1) { + if (strlen(config) == 0) + break; + memset(one_cfg, 0, sizeof(one_cfg)); + end = strchr(config, ','); + if (!end) { /* is last param */ + strlcpy(one_cfg, config, sizeof(one_cfg) - 1); + config = ""; + } else { + size_t nr = (size_t)(end - config); + memcpy(one_cfg, config, min(nr, sizeof(one_cfg) - 1)); + config = end + 1; /* config = next param */ + } + if (strlen(one_cfg) == 0) + continue; + + res = sscanf(one_cfg, "%u=%s", &gpio, direction); + if (res != 2) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Invalid pin configuration: %s\n", + one_cfg); + err = -EINVAL; + goto err_unroll_gpio; + } + + if (strcmp(direction, "in") == 0) { + /* New input pin */ + if (in_idx >= MAX_NR_IN_PINS) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Too many IN ports configured (>%d)\n", + MAX_NR_IN_PINS); + err = -EINVAL; + goto err_unroll_gpio; + } + pin = &(port->in[in_idx]); + + err = gpio_request(gpio, "emc-hal"); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "GPIO-%u request failed: %d\n", + gpio, err); + goto err_unroll_gpio; + } + gpio_direction_input(gpio); + pin->gpio = gpio; + err = hal_pin_bit_newf(HAL_OUT, &pin->pin, comp_id, + "linux-gpio.%d.pin-%u-in", 0, gpio); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Failed to allocate HAL bit\n"); + err = -ENOMEM; + gpio_free(gpio); + goto err_unroll_gpio; + } + err = hal_pin_bit_newf(HAL_OUT, &pin->inv_pin, comp_id, + "linux-gpio.%d.pin-%u-in-not", 0, gpio); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Failed to allocate HAL bit\n"); + err = -ENOMEM; + gpio_free(gpio); + goto err_unroll_gpio; + } + + pin->type = PIN_IN; + in_idx++; + continue; + } + + if (strcmp(direction, "out") == 0) { + /* New output pin */ + if (out_idx >= MAX_NR_OUT_PINS) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Too many OUT ports configured (>%d)\n", + MAX_NR_OUT_PINS); + err = -EINVAL; + goto err_unroll_gpio; + } + pin = &(port->out[out_idx]); + + err = gpio_request(gpio, "emc-hal"); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "GPIO-%u request failed: %d\n", + gpio, err); + goto err_unroll_gpio; + } + pin->hw_state = 0; + gpio_direction_output(gpio, pin->hw_state); + pin->gpio = gpio; + err = hal_pin_bit_newf(HAL_IN, &pin->pin, comp_id, + "linux-gpio.%d.pin-%u-out", 0, gpio); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Failed to allocate HAL bit\n"); + err = -ENOMEM; + gpio_free(gpio); + goto err_unroll_gpio; + } + err = hal_pin_bit_newf(HAL_IN, &pin->inv_pin, comp_id, + "linux-gpio.%d.pin-%u-out-invert", 0, gpio); + if (err) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Failed to allocate HAL bit\n"); + err = -ENOMEM; + gpio_free(gpio); + goto err_unroll_gpio; + } + + pin->type = PIN_OUT; + out_idx++; + continue; + } + + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Invalid pin direction: %s\n", + one_cfg); + err = -EINVAL; + goto err_unroll_gpio; + } + + /* Export the HAL functions */ + err = export_functions(port); + if (err) + goto err_unroll_gpio; + + return 0; + +err_unroll_gpio: + free_gpio_pins(port); + + return err; +} + +int rtapi_app_main(void) +{ + int err; + + err = -ENODEV; + comp_id = hal_init("hal_linux_gpio"); + if (comp_id < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "hal_init failed\n"); + goto err_out; + } + + err = -ENOMEM; + pstate = hal_malloc(sizeof(*pstate)); + if (!pstate) { + rtapi_print_msg(RTAPI_MSG_ERR, PFX + "Failed to allocate SHM\n"); + goto err_hal_exit; + } + + err = build_port(pstate, cfg); + if (err) + goto err_hal_exit; + + rtapi_print_msg(RTAPI_MSG_INFO, PFX + "linux-GPIO HAL driver ready\n"); + hal_ready(comp_id); + + return 0; + +err_hal_exit: + hal_exit(comp_id); +err_out: + return err; +} + +void rtapi_app_exit(void) +{ + free_gpio_pins(pstate); + hal_exit(comp_id); +} + +MODULE_AUTHOR("Michael Buesch"); +MODULE_DESCRIPTION("Linux GPIO driver for EMC HAL"); +MODULE_LICENSE("GPL"); Index: emc2/src/Makefile =================================================================== --- emc2.orig/src/Makefile 2008-07-03 23:47:53.000000000 +0200 +++ emc2/src/Makefile 2008-07-03 23:49:20.000000000 +0200 @@ -638,6 +638,8 @@ hal_speaker-objs := hal/drivers/hal_speaker.o $(MATHSTUB) obj-$(CONFIG_HAL_SKELETON) += hal_skeleton.o hal_skeleton-objs := hal/drivers/hal_skeleton.o $(MATHSTUB) +obj-$(CONFIG_HAL_LINUX_GPIO) += hal_linux_gpio.o +hal_linux_gpio-objs := hal/drivers/hal_linux_gpio.o $(MATHSTUB) obj-$(CONFIG_HOSTMOT2) += hostmot2.o hm2_7i43.o hm2_5i20.o hostmot2-objs := \ Index: emc2/src/Makefile.inc.in =================================================================== --- emc2.orig/src/Makefile.inc.in 2008-07-03 23:49:25.000000000 +0200 +++ emc2/src/Makefile.inc.in 2008-07-03 23:49:56.000000000 +0200 @@ -194,6 +194,7 @@ CONFIG_HAL_PPMC=m CONFIG_PCI_8255=m CONFIG_HOSTMOT2=m +CONFIG_HAL_LINUX_GPIO=m [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ -- Greetings Michael. ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ Emc-developers mailing list Emc-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/emc-developers