/*************************************************************************** byteblaster.c - Low-level functions to access the byteblaster ------------------------------------------------------------- begin : Sun Jan 09 2005 copyright : (C) 2005 by Aurelien Jarno email : aurelien@aurel32.net ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ /* Application specific includes */ #include "byteblaster.h" #include "main.h" /* Standard includes */ #include #include #include #include #ifdef HAVE_LINUX_PPDEV_H # include #endif #ifdef HAVE_LINUX_PARPORT_H # include #endif #ifdef HAVE_DEV_PPBUS_PPI_H # include #endif #ifdef HAVE_DEV_PPBUS_PPBCONF_H # include # define PPRDATA PPIGDATA # define PPWDATA PPISDATA # define PPRSTATUS PPIGSTATUS # define PPWSTATUS PPISSTATUS # define PPRCONTROL PPIGCTRL # define PPWCONTROL PPISCTRL # define PARPORT_CONTROL_AUTOFD AUTOFEED # define PARPORT_STATUS_ACK nACK # define PARPORT_STATUS_SELECT SELECT # define PARPORT_STATUS_BUSY nBUSY #endif /*************************************************************************** * * * Private functions * * * ***************************************************************************/ static void out_data(int device, unsigned char mask, unsigned char val) { static unsigned char data = 0; data = (data & ~mask) | val; ioctl(device, PPWDATA, &data); } static void set_AUTOFEED(int device, int value) { unsigned char control; ioctl(device, PPRCONTROL, &control); control &= ~PARPORT_CONTROL_AUTOFD; if (value != 0) control |= PARPORT_CONTROL_AUTOFD; ioctl(device, PPWCONTROL, &control); usleep(100000); } static void set_D5(int device, int value) { /* D5 */ out_data(device, 0x20, (value != 0)? 0x20 : 0x00); } static int get_ACK(int device) { unsigned char status; ioctl(device, PPRSTATUS, &status); return (status & PARPORT_STATUS_ACK) == PARPORT_STATUS_ACK; } static int open_parport(char *device_name) { int dev; if (debug) printf("Opening %s\n", device_name); dev = open(device_name, O_RDWR); #ifdef PPCLAIM if (dev < 0) { if (!quiet) perror("open"); return -1; } if (ioctl(dev, PPCLAIM) < 0) { if (!quiet) perror("open"); perror("ioctl"); close(dev); return -1; } #endif return dev; } static void close_parport(int device) { if (device) { #ifdef PPRELEASE ioctl(device, PPRELEASE); #endif close(device); } } static int detect_byteblaster(int device) { if (debug) printf("Detecting byteblaster\n"); /* ACK and D5 are connected together */ if (debug) printf("Driving D5 low\n"); set_D5(device, 0); usleep(10000); if (get_ACK(device) == 1) { if (debug) fprintf(stderr, "ACK stuck high\n"); return -1; } if (debug) printf("Driving D5 high\n"); set_D5(device, 1); usleep(10000); if (get_ACK(device) == 0) { if (debug) fprintf(stderr, "ACK stuck low\n"); return -1; } if (debug) printf("Driving D5 low\n"); set_D5(device, 0); usleep(10000); if (get_ACK(device) == 1) { if (debug) fprintf(stderr, "ACK stuck high\n"); return -1; } return 0; } /*************************************************************************** * * * Public functions * * * ***************************************************************************/ int get_nSTATUS(int device) { unsigned char status; ioctl(device, PPRSTATUS, &status); return (status & PARPORT_STATUS_SELECT) == PARPORT_STATUS_SELECT; } int get_CONF_DONE(int device) { unsigned char status; ioctl(device, PPRSTATUS, &status); return (status & PARPORT_STATUS_BUSY) != PARPORT_STATUS_BUSY; } void set_DCLK(int device, int value) { /* D0 */ out_data(device, 0x01, (value != 0)? 0x01 : 0x00); } void set_nCONFIG(int device, int value) { /* D1 */ out_data(device, 0x02, (value != 0)? 0x02 : 0x00); } void set_DATA0(int device, int value) { /* D6 */ out_data(device, 0x40, (value != 0)? 0x40 : 0x00); } int open_byteblaster(char *devicename) { int dev; dev = open_parport(devicename); if (dev < 0 ) { if (!quiet) fprintf(stderr, "Can't open %s!\n", devicename); return -1; } if (detect_byteblaster(dev) < 0) { if (!quiet) fprintf(stderr, "Byteblaster not found on %s!\n", devicename); close_byteblaster(dev); return -1; } return dev; } void close_byteblaster(int device) { enable_byteblaster(device, 0); close_parport(device); } void enable_byteblaster(int device, int value) { set_AUTOFEED(device, value); }