/*
 *  sys/pcmcia.h
 *
 *  Copyright by QNX Software Systems Limited 1994. All rights reserved.
 *
 */
#ifndef __PCMCIA_H_INCLUDED
#define __PCMCIA_H_INCLUDED

#ifndef __TYPES_H_INCLUDED
 #include "sys/types.h"
#endif

#ifndef _FCNTL_H_INCLUDED
 #include "fcntl.h"
#endif

#define	PCMCIA_NAME				"qnx/pcmcia"

#define _PCMCIA_MAX_WINDOWS		10

#pragma pack(1);

struct _pcmcia_info {
	short				socket;			// Socket number (0 based)
	unsigned short		status;			// Card status (from socket services spec)
	unsigned long		flags;			// Flags (_PCMCIA_FLAG_*)
	unsigned char		vcc;			// Current Vcc (in tenths of volts)
	unsigned char		vpp;			// Current Vpp (in tenths of volts)
	unsigned char		num_windows;
	unsigned char		dummy1;
	unsigned long		reserved1;
	unsigned long		reserved2;
	struct _pcmcia_window {
		unsigned short			window;		// Window type (_PCMCIA_WINDOW_*)
		unsigned short			flags;		// Window flags (_PCMCIA_WINFLAG_*)
		mpid_t					pid;		// Locking pid
		unsigned short			device;		// Device type (_PCMCIA_DEV_*)
		unsigned long			dev_size;	// Size of memory device
		unsigned long			reserved3;
		union {
# ifndef NO_PARTITION
			struct _pcmcia_partition {
				unsigned short			reserved4; // partition;		// partition type (_PCMCIA_PARTYPE_*)
				unsigned short			reserved5; // region;			// Region index
				unsigned long			reserved6; // base;			// Base address
				unsigned long			reserved7; // size;			// Size of window
				unsigned short			reserved8; // jedec;			// JEDEC id 
				unsigned char			reserved9; // erase_size;		// erase block size as a power of 2
				unsigned char			reserved10; // device_size;	// device size as a power of 2
				unsigned char			reserved11; // device;			// device type (_PCMCIA_DEVTYPE_*)
				unsigned char			reserved12;
				unsigned short			reserved13;
				unsigned long			reserved14;
				unsigned long			reserved15;
			}						partition;
# endif /* NO_PARTITION */
			struct _pcmcia_irq {
				unsigned short			flags;			// (_PCMCIA_IRQFLAG_*)
				unsigned short			irq;
			}						irq;
			struct _pcmcia_dma {
				unsigned short			flags;			// (_PCMCIA_DMAFLAG_*)
				unsigned short			dma;
			}						dma;
			struct _pcmcia_memio {
				unsigned long			base;			// Base address (in host address space)
				unsigned long			size;			// Size of window
				unsigned long			offset;			// offset of region from base of card
				unsigned short			flags;			// (_PCMCIA_MEMIOFLAG_*)
			}						memio;
		} un;
	} window[_PCMCIA_MAX_WINDOWS];
};

typedef int pcmcia_t;

#define _PCMCIA_STATUS_WP			0x0001		// same as socket services
#define _PCMCIA_STATUS_BVD1			0x0010
#define _PCMCIA_STATUS_BVD2			0x0020
#define _PCMCIA_STATUS_RDYBSY		0x0040
#define _PCMCIA_STATUS_CD			0x0080

#define _PCMCIA_FLAG_CARD			0x00000001	// Card inserted in slot
#define _PCMCIA_FLAG_BATT_LOW		0x00000002	// Card battery is low
#define _PCMCIA_FLAG_CONFIGURED		0x00000004	// IO card was detected and configured
#define _PCMCIA_FLAG_NO_RESOURCES	0x00000008	// Unable to configure due to lack of resources
#define _PCMCIA_FLAG_IOMEM			0x00000010  // Socket configured as io+memory interface
#define _PCMCIA_FLAG_RECONFIGURE	0x00000020  // Socket has a configure pending
#define _PCMCIA_FLAG_UNKNOWN		0x00000040  // Unknown card in socket

#define _PCMCIA_WINDOW_UNUSED		0x0000		// Window slot is unused
#define _PCMCIA_WINDOW_MEMORY		0x0001		// Window describes a memory region
#define _PCMCIA_WINDOW_IO			0x0002		// Window describes an io region
#define _PCMCIA_WINDOW_IRQ			0x0003		// Window describes irq usage
#define _PCMCIA_WINDOW_DMA			0x0004		// Window describes dma usage
#define _PCMCIA_WINDOW_PARTITION	0x0005		// Window describes a partition

#define _PCMCIA_WINFLAG_NEXT		0x0001		// The next window is logically part of this window (ie devices with two i/o port ranges)
#define _PCMCIA_WINFLAG_UNLOCKABLE	0x0002		// This window cannot be locked
#define _PCMCIA_WINFLAG_TEMPORARY	0x0004		// This window will go away when unlocked
#define _PCMCIA_WINFLAG_BOOT		0x0008		// This window was used for boot
#define _PCMCIA_WINFLAG_LOCK_RO		0x0100		// This window has RO lock(s)
#define _PCMCIA_WINFLAG_LOCK_RW		0x0200		// This window has a RW lock
#define _PCMCIA_WINFLAG_LOCK_EXCL	0x0400		// This window has an exclusive lock

#define _PCMCIA_DEV_UNKNOWN			0xFFFF		// Unknown device
#define _PCMCIA_DEV_ALL				0x0000		// All devices
#define _PCMCIA_DEV_MEMORY			0x0100		// Memory type device
#define _PCMCIA_DEV_SERIAL			0x0201		// 16450 serial device
#define _PCMCIA_DEV_PARALLEL		0x0301		// PC parallel device
#define _PCMCIA_DEV_FIXED_DISK		0x0400		// Any hard drive
#define _PCMCIA_DEV_ATA				0x0401		// ATA hard drive
#define _PCMCIA_DEV_VIDEO			0x0500		// Any video adapter
#define _PCMCIA_DEV_VGA				0x0501		// VGA adapter
#define _PCMCIA_DEV_NETWORK			0x0600		// Any network adapter
#define _PCMCIA_DEV_NE2000			0x0601		// NE2000 compatible adapter
#define _PCMCIA_DEV_WAVELAN			0x0602		// NCR Wireless Wavelan
#define _PCMCIA_DEV_AIMS			0x0700		// Auto Incrementing Mass Storage
#define _PCMCIA_DEV_SCSI			0x8000		// Any SCSI interface
#define _PCMCIA_DEV_ADAPTEC_T340	0x8001		// Adaptec T340 SCSI adapter NCR53C400
#define _PCMCIA_DEV_ADAPTEC_T460	0x8002		// Adaptec T460 SCSI adapter
#define _PCMCIA_DEV_SOUND			0x8100		// Any sound adapter
#define _PCMCIA_DEV_SOUNDBLASTER	0x8101		// Soundblaster compatible adapter

#define _PCMCIA_IRQFLAG_LEVEL		0x0001		// The irq is set for level mode
#define _PCMCIA_IRQFLAG_SHARE		0x0002		// The irq is shared

#define _PCMCIA_MEMIOFLAG_ATTRIBUTE	0x0001		// The region maps to attribute memory
#define _PCMCIA_MEMIOFLAG_16BIT		0x0002		// The window is 16-bits wide

#define _PCMCIA_ARM_INSERT_REMOVE	0x0001		// Notify card insertion/removal events
#define _PCMCIA_ARM_BATT_LOW		0x0002		// Notify on battery low events
#define _PCMCIA_ARM_RECONFIGURE		0x0003		// Notify on reconfiguration requests

#define _PCMCIA_PARTYPE_UNKNOWN		0x00		// Unknown or unformatted partition
#define _PCMCIA_PARTYPE_TUPLE		0x01		// Tuple partition
#define _PCMCIA_PARTYPE_ATTRIBUTE	0x02		// Attribute partition
#define _PCMCIA_PARTYPE_FREE		0x03		// Unused partition
#define _PCMCIA_PARTYPE_REGION		0x04		// Region partition
#define _PCMCIA_PARTYPE_FAT			0x10		// MS-DOS FAT type
#define _PCMCIA_PARTYPE_QNX2		0x11		// QNX 2.xx file system
#define _PCMCIA_PARTYPE_QNX4		0x12		// QNX 4.xx file system
#define _PCMCIA_PARTYPE_FFS1		0x20		// Microsoft FFS 1.0
#define _PCMCIA_PARTYPE_FFS2		0x21		// Microsoft FFS 2.0
#define _PCMCIA_PARTYPE_QXIP		0x30		// QNX execute-in-place
#define _PCMCIA_PARTYPE_XIP			0x31		// PCMCIA execute-in-place
#define _PCMCIA_PARTYPE_LFS			0x40		// Linear File Store

#define _PCMCIA_DEVTYPE_NULL		0x00		// Null device
#define _PCMCIA_DEVTYPE_ROM			0x01		// ROM device
#define _PCMCIA_DEVTYPE_OTPROM		0x02		// One-time programable PROM
#define _PCMCIA_DEVTYPE_EPROM		0x03		// UV PROM
#define _PCMCIA_DEVTYPE_EEPROM		0x04		// EEPROM
#define _PCMCIA_DEVTYPE_FLASH		0x05		// Flash EPROM
#define _PCMCIA_DEVTYPE_SRAM		0x06		// Static RAM
#define _PCMCIA_DEVTYPE_DRAM		0x07		// Dynamic RAM
#define _PCMCIA_DEVTYPE_FUNCSPEC	0x0d		// Function specific area
#define _PCMCIA_DEVTYPE_UNKNOWN		0xff		// unknown device type

#define _PCMCIA_MEMTYPE_COMMON		0x0000		// for raw reads
#define _PCMCIA_MEMTYPE_ATTRIBUTE	0x0001		

#define _PCMCIA_VPP_0_VOLTS		0		// voltage setting 0V
#define _PCMCIA_VPP_5_VOLTS		1		// voltage setting 5V
#define _PCMCIA_VPP_12_VOLTS		2		// voltage setting 12V

#ifdef __cplusplus
extern "C" {
#endif

/*
 * General PCMCIA functions
 */
 
extern pcmcia_t qnx_pcmcia_attach(nid_t nid);
extern int qnx_pcmcia_detach(pcmcia_t handle);
extern int qnx_pcmcia_arm(pcmcia_t handle, int devtype, unsigned event, int sig_or_negproxy); // devtype=_PCMCIA_DEV_*, only 1 notification per devtype, 0=disarm
extern int qnx_pcmcia_info(pcmcia_t handle, int socket, struct _pcmcia_info *info, unsigned size);
extern int qnx_pcmcia_lock(pcmcia_t handle, int socket, int window, int oflag);
extern int qnx_pcmcia_unlock(pcmcia_t handle, int socket, int window);
extern int qnx_pcmcia_reconfigure(pcmcia_t handle, int socket);
extern int qnx_pcmcia_reconfig_socket(pcmcia_t handle, int socket, int vpp);

/*
 * PCMCIA Memory functions
 */
 
extern ssize_t qnx_pcmcia_mem_read(pcmcia_t handle, int socket, int window, unsigned long offset, ssize_t size, void *data);
extern ssize_t qnx_pcmcia_mem_write(pcmcia_t handle, int socket, int window, unsigned long offset, ssize_t size, const void *data);
extern long qnx_pcmcia_mem_erase(pcmcia_t handle, int socket, int window, long block_start, long block_count);
extern int qnx_pcmcia_window_alloc(pcmcia_t handle, int socket, int window, long *size, paddr_t *phys);
extern int qnx_pcmcia_window_free(pcmcia_t handle, int socket, int window);
extern long qnx_pcmcia_window_map(pcmcia_t handle, int socket, int window, long offset, long *size);
extern ssize_t qnx_pcmcia_raw_read(pcmcia_t handle, int socket, int type, long addr, ssize_t len, void *buf);
extern int qnx_pcmcia_partition_type(pcmcia_t handle, int socket, int index, int type);
#if !defined(__386__) && ( defined(__SMALL__) || defined(__MEDIUM__) )
extern ssize_t qnx_pcmcia_mem_far_read(pcmcia_t handle, int socket, int window, long offset, ssize_t size, void far *data);
extern ssize_t qnx_pcmcia_mem_far_write(pcmcia_t handle, int socket, int window, long offset, ssize_t size, const void far *data);
extern ssize_t qnx_pcmcia_raw_far_read(pcmcia_t handle, int socket, int type, long addr, ssize_t len, void far *buf);
#else
#define qnx_pcmcia_mem_far_read(_h, _s, _w, _o, _n, _d)		qnx_pcmcia_mem_read(_h, _s, _w, _o, _n, _d)
#define qnx_pcmcia_mem_far_write(_h, _s, _w, _o, _n, _d)	qnx_pcmcia_mem_write(_h, _s, _w, _o, _n, _d)
#define qnx_pcmcia_raw_far_read (_h, _s, _t, _a, _n, _d)	qnx_pcmcia_raw_read(_h, _s, _t, _a, _n, _d)
#endif

/*
 * PCMCIA IO functions and structures
 */
 
struct _pcmcia_io {
	int				type;		// device type
	int				socket;		// Socket number
	int				index;		// window within socket (usually zero)
	int				dma;		// dma used
	unsigned long	flags;		// event card state (_PCMCIA_FLAG_*)
	unsigned		base;		// IO port base address
	unsigned		size;		// Number of IO ports used
	unsigned		base2;		// Second IO port (used for IDE (ATA) drives)
	unsigned		size2;		// Second IO port count
	int				irq;		// irq level
	unsigned		irq_flags;	// irq flags
};

#define qnx_pcmcia_io_attach(_n)			qnx_pcmcia_attach(_n)
#define qnx_pcmcia_io_detach(_h)			qnx_pcmcia_detach(_h)
#define qnx_pcmcia_io_arm(_h, _t, _p)		qnx_pcmcia_arm(_h, _t, _PCMCIA_ARM_INSERT_REMOVE | _PCMCIA_ARM_RECONFIGURE, _p)
#define qnx_pcmcia_io_lock(_h, _s, _w)		qnx_pcmcia_lock(_h, _s, _w, O_RDWR | O_EXCL)
#define qnx_pcmcia_io_unlock(_h, _s, _w)	qnx_pcmcia_unlock(_h, _s, _w)

extern int qnx_pcmcia_io_info(pcmcia_t handle, int devtype, struct _pcmcia_io *info);	// -1 = no more events

/*
 * PCMCIA resource management defines, functions and structures 
 */
 
struct _pcmcia_resource {
	unsigned short 			base;
	unsigned short			length;
};
				
#define _PCMCIA_RESOURCE_MEMORY			0
#define _PCMCIA_RESOURCE_IO				1
#define _PCMCIA_RESOURCE_IRQ			2
#define _PCMCIA_RESOURCE_DMA			3

#define _PCMCIA_RESOURCE_PRIORITIES		2

extern int qnx_pcmcia_resource_clear (pcmcia_t handle);
extern int qnx_pcmcia_resource_add (pcmcia_t handle, int type, int priority, int count, const struct _pcmcia_resource *resources);
extern int qnx_pcmcia_resource_query (pcmcia_t handle, int type, int subtype, int count, struct _pcmcia_resource *resources);
extern int qnx_pcmcia_resource_reread (pcmcia_t handle);

#ifdef __cplusplus
};
#endif

#pragma pack();

#endif
