void rtapi_app_exit(void) { int retval; /* disable parallel port hardware interrupts */ rtapi_outb(rtapi_inb(PARPORT_BASE_ADDRESS + 2) & (~0x10), PARPORT_BASE_ADDRESS + 2); /* clear ISR */ retval = rtapi_disable_interrupt(PARPORT_IRQ); if (retval < 0) { rtapi_print("extint exit: rtapi_disable_interrupt returned %d\n", retval); return; } retval = rtapi_irq_delete(PARPORT_IRQ); if (retval < 0) { rtapi_print("extint exit: rtapi_irq_delete returned %d\n", retval); return; } rtapi_print("extint exit: interrupt count is %d\n", timer_count); retval = rtapi_exit(module); if (retval < 0) { rtapi_print("extint exit: rtapi_exit returned %d\n", retval); return; } }
int rtapi_app_main(void) { int retval; module = rtapi_init("EXTINT"); if (module < 0) { rtapi_print("extint init: rtapi_init returned %d\n", module); return -1; } /* set up ISR */ retval = rtapi_irq_new(PARPORT_IRQ, module, parport_irq_handler); if (retval < 0) { rtapi_print("extint init: rtapi_irq_new returned %d\n", retval); return -1; } retval = rtapi_enable_interrupt(PARPORT_IRQ); if (retval < 0) { rtapi_print("extint init: rtapi_enable_interrupt returned %d\n", retval); return -1; } /* enable parallel port hardware interrupts */ rtapi_outb(rtapi_inb(PARPORT_BASE_ADDRESS + 2) | 0x10, PARPORT_BASE_ADDRESS + 2); return 0; }
static void write_port(void *arg, long period) { skeleton_t *port; unsigned char outdata; port = arg; outdata = *(port->data_out) & 0xFF; /* write it to the hardware */ rtapi_outb(outdata, 0x378); }
static void reset_port(void *arg, long period) { parport_t *port = arg; long long deadline, reset_time_tsc; unsigned char outdata = (port->outdata&~port->reset_mask) ^ port->reset_val; if(port->reset_time > period/4) port->reset_time = period/4; reset_time_tsc = ns2tsc(port->reset_time); if(outdata != port->outdata) { deadline = port->write_time + reset_time_tsc; while(rtapi_get_clocks() < deadline) {} rtapi_outb(outdata, port->base_addr); } outdata = (port->outdata_ctrl&~port->reset_mask_ctrl)^port->reset_val_ctrl; if(outdata != port->outdata_ctrl) { /* correct for hardware inverters on pins 1, 14, & 17 */ outdata ^= 0x0B; deadline = port->write_time_ctrl + reset_time_tsc; while(rtapi_get_clocks() < deadline) {} rtapi_outb(outdata, port->base_addr + 2); } }
static int pins_and_params(char *argv[]) { long port_addr[MAX_PORTS]; int data_dir[MAX_PORTS]; int use_control_in[MAX_PORTS]; int force_epp[MAX_PORTS]; int n, retval; /* clear port_addr and data_dir arrays */ for (n = 0; n < MAX_PORTS; n++) { port_addr[n] = 0; data_dir[n] = 0; use_control_in[n] = 0; force_epp[n] = 0; } /* parse config string, results in port_addr[] and data_dir[] arrays */ num_ports = 0; n = 0; while ((num_ports < MAX_PORTS) && (argv[n] != 0)) { port_addr[num_ports] = parse_port_addr(argv[n]); if (port_addr[num_ports] < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PARPORT: ERROR: bad port address '%s'\n", argv[n]); return -1; } n++; if (argv[n] != 0) { /* is the next token 'in' or 'out' ? */ if ((argv[n][0] == 'i') || (argv[n][0] == 'I')) { /* we aren't picky, anything starting with 'i' means 'in' ;-) */ data_dir[num_ports] = 1; use_control_in[num_ports] = 0; n++; } else if ((argv[n][0] == 'o') || (argv[n][0] == 'O')) { /* anything starting with 'o' means 'out' */ data_dir[num_ports] = 0; use_control_in[num_ports] = 0; n++; } else if ((argv[n][0] == 'e') || (argv[n][0] == 'E')) { /* anything starting with 'e' means 'epp', which is just like 'out' but with EPP mode requested, primarily for the G540 with its charge pump missing-pullup drive issue */ data_dir[num_ports] = 0; use_control_in[num_ports] = 0; force_epp[num_ports] = 1; n++; } else if ((argv[n][0] == 'x') || (argv[n][0] == 'X')) { /* experimental: some parports support a bidirectional * control port. Enable this with pins 2-9 in output mode, * which gives a very nice 8 outs and 9 ins. */ data_dir[num_ports] = 0; use_control_in[num_ports] = 1; n++; } } num_ports++; } /* OK, now we've parsed everything */ if (num_ports == 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PARPORT: ERROR: no ports configured\n"); return -1; } /* have good config info, connect to the HAL */ comp_id = hal_init("hal_parport"); if (comp_id < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PARPORT: ERROR: hal_init() failed\n"); return -1; } /* allocate shared memory for parport data */ port_data_array = hal_malloc(num_ports * sizeof(parport_t)); if (port_data_array == 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PARPORT: ERROR: hal_malloc() failed\n"); hal_exit(comp_id); return -1; } /* export all the pins and params for each port */ for (n = 0; n < num_ports; n++) { int modes = 0; if(use_control_in[n]) { modes = PARPORT_MODE_TRISTATE; } else if(force_epp[n]) { modes = PARPORT_MODE_EPP; } retval = hal_parport_get(comp_id, &port_data_array[n].portdata, port_addr[n], -1, modes); if(retval < 0) { // failure message already printed by hal_parport_get hal_exit(comp_id); return retval; } /* config addr and direction */ port_data_array[n].base_addr = port_data_array[n].portdata.base; port_data_array[n].data_dir = data_dir[n]; port_data_array[n].use_control_in = use_control_in[n]; if(force_epp[n] && port_data_array[n].portdata.base_hi) { /* select EPP mode in ECR */ outb(0x94, port_data_array[n].portdata.base_hi + 2); } /* set data port (pins 2-9) direction to "in" if needed */ if (data_dir[n]) { rtapi_outb(rtapi_inb(port_data_array[n].base_addr+2) | 0x20, port_data_array[n].base_addr+2); } /* export all vars */ retval = export_port(n, &(port_data_array[n])); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "PARPORT: ERROR: port %d var export failed\n", n); hal_exit(comp_id); return retval; } } return 0; }
static void write_port(void *arg, long period) { parport_t *port; int b; unsigned char outdata, mask; port = arg; /* are we using the data port for output? */ if (port->data_dir == 0) { int reset_mask=0, reset_val=0; /* yes */ outdata = 0x00; mask = 0x01; /* assemble output byte for data port from 8 source variables */ for (b = 0; b < 8; b++) { /* get the data, add to output byte */ if ((*(port->data_out[b])) && (!port->data_inv[b])) { outdata |= mask; } if ((!*(port->data_out[b])) && (port->data_inv[b])) { outdata |= mask; } if (port->data_reset[b]) { reset_mask |= mask; if(port->data_inv[b]) reset_val |= mask; } mask <<= 1; } /* write it to the hardware */ rtapi_outb(outdata, port->base_addr); port->write_time = rtapi_get_clocks(); port->reset_val = reset_val; port->reset_mask = reset_mask; port->outdata = outdata; /* prepare to build control port byte, with direction bit clear */ outdata = 0x00; } else { /* prepare to build control port byte, with direction bit set */ outdata = 0x20; } /* are we using the control port for input? */ if (port->use_control_in) { /* yes, force those pins high */ outdata |= 0x0F; } else { int reset_mask=0, reset_val=0; /* no, assemble output byte from 4 source variables */ mask = 0x01; for (b = 0; b < 4; b++) { /* get the data, add to output byte */ if ((*(port->control_out[b])) && (!port->control_inv[b])) { outdata |= mask; } if ((!*(port->control_out[b])) && (port->control_inv[b])) { outdata |= mask; } if (port->control_reset[b]) { reset_mask |= mask; if(port->control_inv[b]) reset_val |= mask; } mask <<= 1; } port->reset_mask_ctrl = reset_mask; port->reset_val_ctrl = reset_val; port->outdata_ctrl = outdata; } /* correct for hardware inverters on pins 1, 14, & 17 */ outdata ^= 0x0B; /* write it to the hardware */ rtapi_outb(outdata, port->base_addr + 2); port->write_time_ctrl = rtapi_get_clocks(); }