/*****************************************************************************/

/*
 *      realmagicdev.h -- NetStream2000 EM8400 (quasar) ``major level'' include
 *
 *      Copyright (C) 1999-2000  Sigma Designs
 *                    written by Emmanuel Michon <emmanuel_michon@sdesigns.com>
 *                           and Howard G. Page
 *
 *      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.
 */

/*****************************************************************************/

/*
 *  NetStream2000 device node    (MAJOR,MINOR)  meaning
 *  /dev/realmagic0          (122,0)         the 1st realmagic device
 *  /dev/realmagic1          (122,1)         the 2nd realmagic device
 *  ...and so on.
 */

#define REALMAGIC_MAJOR 122

/* beware: keep in sync with user space driver.

   scenario: there are two dmabuf_table arrays, one (per board) in kernel space, one 
   in user space. Entries must be kept in sync, indices will
   certainly match most of the times though it's not necessarily so 

   1. (allocation) user space finds an dmabuf_table entry with inuse=0, fills
   Size field and calls ioctl(IOCTL_DMABUF_ALLOC) and the kernel:
   - finds an entry with inuse=0
   - copies the user struct to kernel struct
   - calls dmaalloc(Size) and fills KernelVirtualAddress
   - calls virt_to_phys and fills PhysicalAddress
   - fills inuse=1 and ProcessVirtualAddress=0
   - and returns the struct back to user
   2. (mapping) user space calls mmap(...REMAP_DMA...) and the kernel:
   - finds the (only) table entry with inuse=1 and ProcessVirtualAddress=0
   - calls remap_page_range
   - fills ProcessVirtualAddress on kernel side if successful
   If mmap() successful, user space fills ProcessVirtualAddress field.
   
   [... The two structs should be in sync and usable ...]

   3. (unmapping) user space calls munmap --- no matching kernel code. If successful
   zeroes ProcessVirtualAddress. The two structs are not in sync then.
   4. (unallocation) user space calls ioctl(IOCTL_DMABUF_FREE) and the kernel
   - finds the (only) table entry with inuse=1 and matching KernelVirtualAddress
   - checks ProcessVirtualAddress==0 and calls dmafree
   - put inuse=0
   and returns the struct back to user

   Kernel side emergency situations:
   * open method puts inuse=0 thru the dmabuf_table whatever a previous close() has done. This
   may result in harmless dmaalloc'd space.
   * release method calls dmafree *even if* ProcessVirtualAddress is not zero (warning). 
   What will happen if the process accesses the mapped space is unclear.
   * init, cleanup module functions do not do anything towards this.
   
   user space threads: (allocation,mapping) and (unmapping,unallocation) should
   be made atomic some way (critical section).
 */

typedef struct  realmagic_dev_t_tag {
	struct file_operations *fops;

	struct pci_dev *pdev;
	
	unsigned long ioaddr;
	unsigned long vioaddr;
	int mapsize;

#ifdef _STREAMMACHINE_
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
	wait_queue_head_t quasar_queue;
#else
	struct wait_queue *quasar_queue;
#endif
#endif /*_STREAMMACHINE_*/

	unsigned long ring3_pid;
	unsigned long irqstilltobeserviced;
	unsigned long sawEOS;
	unsigned long ring0_irqcount;
	irq_data i_d;

	int opentimes;
	dmabuf_helper dmabuf_table[MAX_dmabuf];
} realmagic_dev_t;

#define REALMAGIC_MAX_DEV 32

extern unsigned short quasar_dev_id;

// this table stores up to REALMAGIC_MAX_DEV devices
extern realmagic_dev_t realmagic_dev_tab[REALMAGIC_MAX_DEV];
extern int realmagic_dev_idx;

