/*
 * This is 'pwrm', the laptop power manager.
 *
 * Copyright (c) 1992,93 Hansruedi Heeb
 *
 * 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 1, 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.
 *
 * Author's address: heeb@iis.ethz.ch
 */

#include "pwrm.h"
#include "portio.h"

void inline outb_p(char value, unsigned short port)
{
__asm__ __volatile__ ("outb %%al,%%dx"
		::"a" ((char) value),"d" ((unsigned short) port));
	SLOW_DOWN_IO;
}

void inline outw_p(char value, unsigned short port)
{
__asm__ __volatile__ ("outw %%ax,%%dx"
		::"a" (value),"d" ((unsigned short) port));
	SLOW_DOWN_IO;
}

unsigned int inline inb_p(unsigned short port)
{
	unsigned int _v;
__asm__ __volatile__ ("inb %%dx,%%al"
		:"=a" (_v):"d" ((unsigned short) port),"0" (0));
	SLOW_DOWN_IO;
	return _v;
}

unsigned int inline inw_p(unsigned short port)
{
	unsigned int _v;
__asm__ __volatile__ ("inw %%dx,%%ax"
		:"=a" (_v):"d" ((unsigned short) port),"0" (0));
	SLOW_DOWN_IO;
	return _v;
}

void inline unlock()
{
  outb_p(UNLOCK_VALUE,LOCK_UNLOCK_REGISTER_PORT);
}

void inline lock()
{
  outb_p(LOCK_VALUE,LOCK_UNLOCK_REGISTER_PORT);
}

void write_locked_port(int value, int port)
{
#ifdef DEBUG
  if (value>0xffff || port>0xffff) {
    fprintf(stderr,"*** attempt to write %x to port %x, exit.",value,port);
    exit(1);
  }
#endif
  unlock();
  outw_p(value,port);
  lock();
}

int read_locked_port(int port)
{
  int value;

#ifdef DEBUG
  if (port>0xffff) {
    fprintf(stderr,"*** attempt to read from port %x, exit.",port);
    exit(1);
  }
#endif
  unlock();
  value=inw_p(port);
  lock();
  return(value);
}

void write_locked_byte_port(int value, int port)
{
#ifdef DEBUG
  if (value>0xff || port>0xffff) {
    fprintf(stderr,"*** attempt to write %x to byte port %x, exit.",
	    value,port);
    exit(1);
  }
#endif
  unlock();
  outb_p(value,port);
  lock();
}

int read_locked_byte_port(int port)
{
  int value;

#ifdef DEBUG
  if (port>0xffff) {
    fprintf(stderr,"*** attempt to read from port %x, exit.",port);
    exit(1);
  }
#endif
  unlock();
  value=inb_p(port);
  lock();
  return(value);
}

int test_port_bit(int nr, int port)
/*
 * Return a bit in a port as boolean value.
 */
{
  int inp;

#ifdef DEBUG
  if (port>0xffff || nr>15) {
    fprintf(stderr,"*** attempt to test bit %d in port %x, exit.",nr,port);
    exit(1);
  }
#endif
  inp=read_locked_port(port);
  return(((inp >> nr) & 0x01) == 0x01);
}

int test_byte_port_bit(int nr, int port)
/*
 * Return a bit in a port as boolean value.
 */
{
  int inp;

#ifdef DEBUG
  if (port>0xffff || nr>7) {
    fprintf(stderr,"*** attempt to test bit %d in port %x, exit.",nr,port);
    exit(1);
  }
#endif
  inp=read_locked_byte_port(port);
  return(((inp >> nr) & 0x01) == 0x01);
}
