Logo Search packages:      
Sourcecode: cbmlink version File versions  Download package

pcpar.c

Go to the documentation of this file.
/**
 * @file pcpar.c
 * Interface to accessing IBM PC like parallel ports
 * @author Marko Mäkelä (msmakela@nic.funet.fi)
 */

/*
 * Copyright © 2001,2002 Marko Mäkelä
 * 
 *     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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#define _BSD_SOURCE
#ifdef COMM_PC
# include "pcpar.h"
# include <stdio.h>
# include <stdlib.h>

#ifdef __BCC__
/* These are from bcc_io.c */
# asm
! int inportb (int port);
      .globl      _inportb
_inportb:
      pop   bx
      pop   dx
      dec   sp
      dec   sp
      in    al,dx
      sub   ah,ah
      jmp   bx

! void oportb (int port, char value);
      .globl      _oportb
_oportb:
      pop   bx
      pop   dx
      pop   ax
      sub   sp,*4
      out   dx,al
      jmp   bx
# endasm

/* Abort transfer in case of ctrl-break */
# asm
! void abreak (void);
      .globl _abreak
_abreak:
      and al,I 0x7f
      eseg
      mov byte [0x71],al      ; clear the keyboard interrupt flag
      pop es
      mov ax,*-1
      push ax
      call _exit
# endasm
#endif /* __BCC__ */

/** the base address for the printer port, and the address of the data port */
unsigned baseaddr;
/** the address of the status port */
unsigned stataddr;
/** the address of the control port */
unsigned ctrladdr;

/** recognized base addresses for ports */
static unsigned portbase[] = { 0x3bc, 0x378, 0x2bc, 0x278 };

#ifdef USE_PPDEV
/** the parallel port file descriptor */
static int parfd = -1;
# if defined __linux__ || defined __FreeBSD__
#  include <unistd.h>
#  include <sys/ioctl.h>
#  include <fcntl.h>
# endif /* __linux__ || __FreeBSD__ */
# ifdef __linux__
#  include <linux/ppdev.h>
# endif
# ifdef __FreeBSD__
#  include <machine/sysarch.h>
#  include <dev/ppbus/ppi.h>
# endif
#endif /* USE_PPDEV */

/** Open a parallel port
 * @param dev     the "device name" of the port
 * @return  the base address of the port (-1=ppdev), or 0 on failure
 */
unsigned
open_port (const char* dev)
{
  char* s;
  unsigned long p = strtoul (dev, &s, 0);
  if (!*dev || *s) {
#  ifdef USE_PPDEV
    baseaddr = (unsigned) -1;
#  else /* USE_PPDEV */
    fprintf (stderr, "open_port: unrecognized port %s\n", dev);
    return 0;
#  endif /* USE_PPDEV */
  }
  else if (p < (sizeof portbase) / sizeof *portbase)
    baseaddr = portbase[p];
  else {
    unsigned i = (sizeof portbase) / sizeof *portbase;
    while (i)
      if (p == portbase[--i])
      goto found;
    fprintf (stderr, "open_port: port %s out of range\n", dev);
    return 0;
  found:
    baseaddr = portbase[i];
  }

# ifdef USE_PPDEV
  if (baseaddr != (unsigned) -1) {
# endif /* USE_PPDEV */
# ifdef __linux__
    if (ioperm (baseaddr, 3, 1)) {
      perror ("open_port: ioperm");
      return 0;
    }
    /* give up the super user privileges */
    seteuid (getuid ());
# endif /* __linux__ */
# ifdef __FreeBSD__
    if (i386_set_ioperm (baseaddr, 3, 1)) {
      perror ("open_port: i386_set_ioperm");
      return 0;
    }
    /* give up the super user privileges */
    seteuid (getuid ());
# endif /* __FreeBSD__ */
    stataddr = baseaddr + 1;
    ctrladdr = baseaddr + 2;
# ifdef USE_PPDEV
  }
  else {
    if (0 > (parfd = open (dev, O_RDWR, 0))) {
      fputs ("open_port ", stderr);
      fputs(dev, stderr);
      perror (": open");
      return 0;
    }
#  ifdef __linux__
    if (ioctl (parfd, PPCLAIM, 0)) {
      fputs ("open_port ", stderr);
      fputs(dev, stderr);
      perror (": ioctl (PPCLAIM)");
      close (parfd);
      parfd = -1;
      return 0;
    }
#  endif /* __linux */
  }
# endif /* USE_PPDEV */
  return baseaddr;
}

# ifdef USE_PPDEV
/** Close the communication channel to the parallel port */
void
close_port (void)
{
  if (parfd == -1)
    return;
#  ifdef __linux__
  ioctl (parfd, PPRELEASE, 0);
#  endif /* __linux__ */
  close (parfd);
  parfd = -1;
}

/** write data bits to the parallel port
 * @param data    the data bits to be written
 * @return  zero on success, nonzero on failure
 */
int
write_data (char data)
{
  if (parfd == -1) {
    outbyte (data, baseaddr);
    return 0;
  }
#  ifdef __linux__
  if (ioctl (parfd, PPWDATA, &data)) {
    perror ("ioctl (PPWDATA)");
    return -1;
  }
#  endif /* __linux__ */
#  ifdef __FreeBSD__
  if (ioctl (parfd, PPISDATA, &data)) {
    perror ("ioctl (PPISDATA)");
    return -1;
  }
#  endif /* __FreeBSD__ */
  return 0;
}

/** write control bits to the parallel port
 * @param ctrl    the control bits to be written
 * @return  zero on success, nonzero on failure
 */
int
write_ctrl (char ctrl)
{
  if (parfd == -1) {
    outbyte (ctrl, ctrladdr);
    return 0;
  }
#  ifdef __linux__
  if (ioctl (parfd, PPWCONTROL, &ctrl)) {
    perror ("ioctl (PPWCONTROL)");
    return -1;
  }
#  endif /* __linux__ */
#  ifdef __FreeBSD__
  if (ioctl (parfd, PPISCTRL, &ctrl)) {
    perror ("ioctl (PPISCTRL)");
    return -1;
  }
#  endif /* __FreeBSD__ */
  return 0;
}

/** read the status bits of the parallel port
 * @return  the read status bits
 */
char
read_stat (void)
{
  char stat;
  if (parfd == -1)
    return inb (stataddr);
#  ifdef __linux__
  if (ioctl (parfd, PPRSTATUS, &stat)) {
    perror ("ioctl (PPRSTATUS)");
    return -1;
  }
#  endif /* __linux__ */
#  ifdef __FreeBSD__
  if (ioctl (parfd, PPIGSTATUS, &stat)) {
    perror ("ioctl (PPIGSTATUS)");
    return -1;
  }
#  endif /* __FreeBSD__ */
  return stat;
}

/** read the control bits of the parallel port
 * @return  the read control bits
 */
char
read_ctrl (void)
{
  char ctrl;
  if (parfd == -1)
    return inb (ctrladdr);
#  ifdef __linux__
  if (ioctl (parfd, PPRCONTROL, &ctrl)) {
    perror ("ioctl (PPRCONTROL)");
    return -1;
  }
#  endif /* __linux__ */
#  ifdef __FreeBSD__
  if (ioctl (parfd, PPIGCTRL, &ctrl)) {
    perror ("ioctl (PPIGCTRL)");
    return -1;
  }
#  endif /* __FreeBSD__ */
  return ctrl;
}
# endif /* USE_PPDEV */
#endif /* COMM_PC */

Generated by  Doxygen 1.6.0   Back to index