BeBox Zone Logo
 
About
Home
News
Forums
Registry
Tech Info
BeBox Overview
BeBooks
BeBox Peripherals
BeBox Bezel
BootROM
Clock Generation
Floppy Disk Drive
Geekport
I/O Board
Infrared Ports
ISA Bus
Joystick Ports
Keyboard/Mouse Controller
Main Processor Board
MIDI Ports
Memory Controller and PCI Bridge
Parallel Ports
PCI Bus
Processor Board Overview
Processor Bus
Processors
Real-Time Clock
Reset and Interrupts
Serial Ports
SCSI
Sound System
Voltage Regulation
History
Opinions
Images
Articles
FAQs
Links
Operating Systems
Software
Contact Us





















/* ++++++++++
	FILE:	digital.c
	REVS:	$Revision: 1.14 $
	NAME:	herold
	DATE:	Tue Jan 23 13:09:56 PST 1996
	Copyright (c) 1996-97 by Be Incorporated.  All Rights Reserved.

	Driver for the digital i/o portion of the geek port.
+++++ */

#include 
#include 
#include 
#include 
#include 
#include 

#ifndef DEBUG
#define DEBUG 0
#endif

#if DEBUG
#define ddprintf dprintf
#else
#define ddprintf
#endif

/* -----
	private definitions and types
----- */

#define PORT_A_MASK	0x01
#define PORT_B_MASK	0x02


/* -----
	private globals
----- */

static int		open_count[2] = {0,0};	/* # outstanding opens to each port */
static spinlock	port_locks[2] = {0,0};	/* locks for port access */
static vshort 	*output_enable;			/* -> output enable reg */
static vchar	*port_addr[2];			/* -> ports */


/* ----------
	find_digport - determines if digital port hardware is present, and
	set up globals to point to it.
----- */
bool
find_digport (void)
{
	area_info	a;
	area_id		id;

	if (io_card_version() < 0)
		return FALSE;

	id = find_area ("isa_io");
	if (id < 0)
		return FALSE;
	if (get_area_info (id, &a) < 0)
		return FALSE;

	output_enable = (vshort *) ((char *)a.address + GEEK_OUTPUT_ENABLE);
	port_addr[0] = (vchar *)a.address + GEEK_DIGITAL_PORT_A;
	port_addr[1] = (vchar *)a.address + GEEK_DIGITAL_PORT_B;
	
	return TRUE;
}
	

/* ----------
	lock_port - gains exclusive access to hw, driver resources
----- */
static cpu_status
lock_port (int id)
{
	cpu_status	ps;
	
	ps = disable_interrupts();
	acquire_spinlock (port_locks + id);

	return ps;
}


/* ----------
	unlock_port - relinquish exclusive access to hw, driver resources
----- */
static void
unlock_port (int id, cpu_status ps)
{
	release_spinlock (port_locks + id);
	restore_interrupts(ps);
}


/* ----------
	set_digital_port_direction

	assumes port is locked, or does not have to be.
----- */
static void
set_digital_port_direction (int id, int direction)
{
	short		oe;
	static char	masks[2] = {PORT_A_MASK, PORT_B_MASK};

	oe = B_LENDIAN_TO_HOST_INT16 (*output_enable);
	__eieio();
 	if (direction == DIGITAL_PORT_INPUT)
		*output_enable = B_HOST_TO_LENDIAN_INT16 (oe & ~masks[id]);
	else
		*output_enable = B_HOST_TO_LENDIAN_INT16 (oe  | masks[id]);
	__eieio();
}
 

/* ----------
	init_hardware - looks for geekport, sets digital ports to inputs
----- */
status_t
init_hardware (void)
{
	if (!find_digport())
		return B_ERROR;

	set_digital_port_direction (0, DIGITAL_PORT_INPUT);
	set_digital_port_direction (1, DIGITAL_PORT_INPUT);

	return B_NO_ERROR;
}


/* ----------
	init_driver - set up driver globals
----- */
status_t
init_driver (void)
{
	return find_digport() ? B_NO_ERROR : B_ERROR;
}


/* ----------
	digital_port_open - set up digital ports
----- */
static status_t 
digital_port_open (const char *name, uint32 flags, void **cookie)
{
	int			id;
	cpu_status	ps;

	/* distinguish open of port a from port b */

	ddprintf("opening '%s'\n", name);
	id = (name [strlen(name)-1] == 'a') ? 0 : 1;

	ps = lock_port (id);
	open_count [id] += 1;				/* count opens on this port */
	unlock_port (id, ps);

	*cookie = (void *)id;				/* remember which port this is */
	return B_NO_ERROR;
}



/* ----------
	digital_port_close
----- */
static status_t
digital_port_close (void *cookie)
{
	cpu_status	ps;
	int			id;

	id = (int) cookie;
	if (id < 0 || id > 1)				/* sanity check */
		return B_ERROR;

	ps = lock_port (id);

	open_count[id] -= 1;
	if (open_count[id] == 0)
		set_digital_port_direction (id, DIGITAL_PORT_INPUT);
	
	unlock_port (id, ps);
	
	return B_NO_ERROR;
}


/* ----------
	digital_port_read
----- */

static status_t
digital_port_read (void *cookie, off_t pos, void *buf, size_t *nbytes)
{
	int			id;

	id = (int) cookie;
	if (id < 0 || id > 1)				/* sanity check */
		return B_ERROR;

	*(char *)buf = *port_addr[id];

	return B_NO_ERROR;
}


/* ----------
	digital_port_write
----- */

static status_t
digital_port_write (void *cookie, off_t pos, const void *buf, size_t *nbytes) 
{
	int			id;

	id = (int) cookie;
	if (id < 0 || id > 1)				/* sanity check */
		return B_ERROR;

	*port_addr[id] = *(char *)buf;

	return B_NO_ERROR;
}


/* ----------
	digital_port_control
----- */

static status_t
digital_port_control (void *cookie, uint32 op, void *arg, size_t len)
{
	int 		id;
	int			dir;
	cpu_status	ps;

	id = (int) cookie;
	if (id < 0 || id > 1)				/* sanity check */
		return B_ERROR;

	switch (op) {
	case SET_DIGITAL_PORT_DIRECTION:

		dir = (int)arg;
		if (dir != DIGITAL_PORT_INPUT && dir != DIGITAL_PORT_OUTPUT)
			return B_ERROR;
		
		ps = lock_port (id);
		set_digital_port_direction (id, dir);
		unlock_port (id, ps);

		return B_NO_ERROR;
	}
	return B_ERROR;
}


/* -----------
    digital_port_free
----------- */

static status_t
digital_port_free (void *cookie)
{
	return B_NO_ERROR;
}


/* -----
	public globals and functions
----- */

static const char *digital_name[] = {
  "beboxhw/geekport/digital/digital_port_a",
  "beboxhw/geekport/digital/digital_port_b",
  NULL
};


device_hooks	digital_port_devices = 	{
    digital_port_open, 		/* -> open entry point */
    digital_port_close, 	/* -> close entry point */
    digital_port_free,      /* -> free cookies allocated */
    digital_port_control, 	/* -> control entry point */
    digital_port_read,		/* -> read entry point */
    digital_port_write		/* -> write entry point */
};

const char **
publish_devices()
{
	return digital_name;
}

device_hooks *
find_device(const char *name)
{
	return &digital_port_devices;
}








 Questions? Comments? Contact Andrew Lampert (webmaster at bebox dot nu).


BeUnited
BeBits
LeBuzz Blog
BeOS Radio
BeDope

© 1998-2009 Andrew Lampert