/*
   "bus_resources.h"

   created by: grayspace aka J. Leveille
   for: UbixOS Project
   date: May 12, 2002

   purpose: master header file for bus resource management

   $Id: bus_resources.h,v 1.1.1.1 2003/01/12 00:20:19 reddawg Exp $
*/

#ifndef _BUS_RESOURCES_H
#define _BUS_RESOURCES_H

/* Intel 32-bit architecture */
#if TCPU_IA32

/* DMA channels */
#define MIN_DMA_CHANNEL       (0)
#define MAX_DMA_CHANNEL       (7)
#define NUM_DMA_CHANNELS      (MAX_DMA_CHANNEL - MIN_DMA_CHANNEL - 1)

/* IRQs */
#define MIN_IRQ               (0)
#define MAX_IRQ               (15)
#define NUM_IRQS              (MAX_IRQ - MIN_IRQ - 1)

/* Port IO Range */
#define MIN_PORTIO_ADDR       (0)
#define MAX_PORTIO_ADDR       (1023)
#define MAXBITS_PORTIO_ADDR   (10)

/* Memory Range */
#define MIN_MEMIO_ADDR        (0)
#define MAX_MEMIO_ADDR        (0xFFFFFFFF)
#define MAXBITS_MEMIO_ADDR    (32)

/* NOTE: 'BI_' denotes roughly something related to BUS info */

/* for building/use-with device-info/bus-resource-info structures */
#define BI_NUMBITS_IRQS          (4)
#define BI_NUMBITS_DMA_CHANNELS  (3)
#define BI_IRQ_BIT               (0)
#define BI_DMA_CHANNEL_BIT       (BI_IRQ_BIT + BI_NUMBITS_IRQS)

#define BI_IRQ_MASK\
            MAKEMASK_GS( BI_NUMBITS_IRQS, BI_IRQ_BIT )
#define BI_DMA_CHANNEL_MASK\
            MAKEMASK_GS( BI_NUMBITS_DMA_CHANNELS, BI_DMA_CHANNEL_BIT )

#define BI_NUMBITS_PORTIO_BASEADDR  (16)
#define BI_NUMBITS_PORTIO_OVERADDR  (16)
#define BI_PORTIO_BASEADDR_BIT      (0)
#define BI_PORTIO_OVERADDR_BIT      (  BI_PORTIO_BASEADDR_BIT\
                                       + BI_NUMBITS_PORTIO_BASEADDR  )
#define BI_PORTIO_BASEADDR_MASK\
            MAKEMASK_GS( BI_NUMBITS_PORTIO_BASEADDR, BI_PORTIO_BASEADDR_BIT )
#define BI_PORTIO_OVERADDR_MASK\
            MAKEMASK_GS( BI_NUMBITS_PORTIO_OVERADDR, BI_PORTIO_OVERADDR_BIT )

/* maximum number of DMAs and IRQs a device can use
   NOTE: *must* be same                            */
#define BI_MAX_DMAANDIRQS  (2)
#define BI_MAX_DMAS        (BI_MAX_DMAANDIRQS)
#define BI_MAX_IRQS        (BI_MAX_DMAANDIRQS)

/* maximum number of Port IO ranges a device can use */
#define BI_MAX_PORTIO_RANGES  (4)

/* maximum number of Memory IO ranges a device can use */
#define BI_MAX_MEMIO_RANGES   (4)

/* structure for storing a device's bus resources */
typedef struct tagBUS_RESOURCES
{
   /* DMA and IRQ info */
   BYTEg a_dmairq[BI_MAX_DMAANDIRQS];

   /*
      bits [0,1]  number of IRQs used
      bits [2,3]  number of DMA channels used
      bits [4,7]  number of port IO ranges used
   */
   BYTEg resource_counts1;

   /*
      bits [0,3]  number of memory ranges used
      bits [4,7]  ???
   */
   BYTEg resource_counts2;

   /* Port IO Ranges */
   DWORDg a_portiorange[BI_MAX_PORTIO_RANGES];

   /* Memory IO Ranges */
   DWORDg a_memiorange_base[BI_MAX_MEMIO_RANGES];
   DWORDg a_memiorange_last[BI_MAX_MEMIO_RANGES];
}
BUS_RESOURCES;

/* NOTE: 'BUS_RES' denotes interface functions/macros on
         the 'BUS_RESOURCES' structure                   */

#if (BI_IRQ_BIT == 0)
   /* get IRQ 'idx' from resource description 'br' */
   #define BUS_RES_GETIRQ( br, idx ) ((br).a_dmairq[(idx)]&BI_IRQ_MASK)

   /* set IRQ 'idx' in resource description 'br' to 'irq' */
   #define BUS_RES_SETIRQ( br, idx, irq )\
            (br).a_dmairq[(idx)] &= BI_IRQ_MASK;\
            (br).a_dmairq[(idx)] |= (irq)
#else
   /* get IRQ 'idx' from resource description 'br' */
   #define BUS_RES_GETIRQ( br, idx )\
            GETBITVAL_GS( (br).a_dmairq[(idx)], BI_IRQ_MASK, BI_IRQ_BIT )

   /* set IRQ 'idx' in resource description 'br' to 'irq' */
   #define BUS_RES_SETIRQ( br, idx, irq )\
            SETBITVAL_FAST_GS(   (br).a_dmairq[(idx)],\
                                 BI_IRQ_MASK,\
                                 BI_IRQ_BIT,\
                                 (irq)                )
#endif

/* get DMA 'idx' from resource description 'br' */
#define BUS_RES_GETDMA( br, idx )\
         GETBITVAL_GS( (br).a_dmairq[(idx)], BI_DMA_MASK, BI_DMA_BIT )

/* set DMA 'idx' in resource description 'br' to 'dma' */
#define BUS_RES_SETDMA( br, idx, dma )\
         SETBITVAL_FAST_GS(   (br).a_dmairq[(idx)],\
                              BI_DMA_MASK,\
                              BI_DMA_BIT,\
                              (dma)                )

#if (BI_PORTIO_BASEADDR_BIT == 0) && (BI_PORTIO_OVERADDR_BIT == BI_NUMBITS_PORTIO_BASEADDR )
   /* get port IO base address 'idx' from resource description 'br' */
   #define BUS_RES_GETPORTIOBASE( br, idx )\
            ((br).a_portiorange[(idx)]&BI_PORTIO_BASEADDR_MASK)

   /* get port IO 'over' address 'idx' from resource description 'br' */
   #define BUS_RES_GETPORTIOOVER( br, idx )\
            ((br).a_portiorange[(idx)]>>BI_PORTIO_OVERADDR_BIT)

   /* get port IO range 'idx' from resource description 'br'
      into 'baseaddr_o' and 'overaddr_o'                    */
   #define BUS_RES_GETPORTIORANGE( br, idx, baseaddr_o, overaddr_o )\
            (baseaddr_o)\
               = ((br).a_portiorange[(idx)] & BI_PORTIO_BASEADDR_MASK);\
            (overaddr_o)\
               = ((br).a_portiorange[(idx)] >> BI_PORTIO_OVERADDR_BIT)

   /* set port IO range 'idx' in resource description 'br'
      to 'baseaddr' and 'overaddr'                       */
   #define BUS_RES_SETPORTIORANGE( br, idx, baseaddr, overaddr )\
            ((br).a_portiorange[(idx)]\
               = ((overaddr)<<BI_PORTIO_OVERADDR_BIT);\
            ((br).a_portiorange[(idx)]\
               |= (baseaddr)
#else /* #if   (BI_PORTIO_BASEADDR_BIT == 0)
               && (BI_PORTIO_OVERADDR_BIT == BI_NUMBITS_PORTIO_BASEADDR ) */
   /* get port IO base address 'idx' from resource description 'br' */
   #define BUS_RES_GETPORTIOBASE( br, idx )\
            GETBITVAL_GS(  (br).a_portiorange[(idx)],\
                           BI_PORTIO_BASEADDR_MASK,\
                           BI_PORTIO_BASEADDR_BIT     )

   /* get port IO 'over' address 'idx' from resource description 'br' */
   #define BUS_RES_GETPORTIOOVER( br, idx )\
            GETBITVAL_GS(  (br).a_portiorange[(idx)],\
                           BI_PORTIO_OVERADDR_MASK,\
                           BI_PORTIO_OVERADDR_BIT     )

   /* get port IO range 'idx' from resource description 'br'
      into 'baseaddr_o' and 'overaddr_o'                    */
   #define BUS_RES_GETPORTIORANGE( br, idx, baseaddr_o, overaddr_o )\
            (baseaddr_o)\
               = GETBITVAL_GS(   (br).a_portiorange[(idx)],\
                                 BI_PORTIO_BASEADDR_MASK,\
                                 BI_PORTIO_BASEADDR_BIT     );\
            (overaddr_o)\
               = GETBITVAL_GS(   (br).a_portiorange[(idx)],\
                                 BI_PORTIO_OVERADDR_MASK,\
                                 BI_PORTIO_OVERADDR_BIT     )

   /* set port IO range 'idx' in resource description 'br'
      to 'baseaddr' and 'overaddr'                       */
   #define BUS_RES_SETPORTIORANGE( br, idx, baseaddr, overaddr )\
            SETBITVAL_FAST_GS(   (br).a_portiorange[(idx)],\
                                 BI_PORTIO_BASEADDR_MASK,\
                                 BI_PORTIO_BASEADDR_BIT,\
                                 (baseaddr)                 )\
            SETBITVAL_FAST_GS(   (br).a_portiorange[(idx)],\
                                 BI_PORTIO_OVERADDR_MASK,\
                                 BI_PORTIO_OVERADDR_BIT,\
                                 (overaddr)                 )
#endif /* #else #if  (BI_PORTIO_BASEADDR_BIT == 0)
                     && (  BI_PORTIO_OVERADDR_BIT
                           == BI_NUMBITS_PORTIO_BASEADDR )  */

/* get mem IO base address 'idx' from resource description 'br' */
#define BUS_RES_GETMIOBASE( br, idx )\
         ((br).a_memiorange_base[(idx)])

/* get mem IO 'last' address 'idx' from resource description 'br' */
#define BUS_RES_GETMEMIOLAST( br, idx )\
         ((br).a_memiorange_last[(idx)])

/* get mem IO range 'idx' from resource description 'br'
   into 'baseaddr_o' and 'lastaddr_o'                    */
#define BUS_RES_GETMEMIORANGE( br, idx, baseaddr_o, lastaddr_o )\
         (baseaddr_o)\
            = (br).a_memiorange_base[(idx)];\
         (lastaddr_o)\
            = (br).a_memiorange_last[(idx)]

/* set port IO range 'idx' in resource description 'br'
   to 'baseaddr' and 'lastaddr'                       */
#define BUS_RES_SETMEMIORANGE( br, idx, baseaddr, lastaddr )\
         (br).a_memiorange_base[(idx)] = baseaddr;\
         (br).a_memiorange_last[(idx)] = lastaddr

/* HACK: because no defines used for bit numbers */

/* get number of IRQs used/assigned-to device */
#define BUS_RES_GETIRQSUSED( br )\
            (((br).resource_counts1 & 0x0C)>>2)
/* set number of IRQs used/assigned-to device */
#define BUS_RES_SETIRQSUSED( br, irqsused )\
            (br).resource_counts1 &= ~0x0C;\
            (br).resource_counts1 |= ((irqsused)<<2)

/* get number of DMAs used/assigned-to device */
#define BUS_RES_GETDMASUSED( br )\
            ((br).resource_counts1 & 3)
/* set number of DMAs used/assigned-to device */
#define BUS_RES_SETDMASUSED( br, dmasused )\
            (br).resource_counts1 &= ~3;\
            (br).resource_counts1 |= (dmasused)

/* get number of port IO ranges used/assigned-to device */
#define BUS_RES_GETPORTIORANGESUSED( br )\
            (((br).resource_counts1)>>4)
/* get number of port IO ranges used/assigned-to device */
#define BUS_RES_SETPORTIORANGESUSED( br, rangesused )\
            (br).resource_counts1 &= 0x0F;\
            (br).resource_counts1 |= ((rangesused)<<4)

/* get number of port IO ranges used/assigned-to device */
#define BUS_RES_GETMEMIORANGESUSED( br )\
            (((br).resource_counts2) & 0x0F)
/* get number of port IO ranges used/assigned-to device */
#define BUS_RES_SETMEMIORANGESUSED( br, rangesused )\
            (br).resource_counts2 &= 0xF0;\
            (br).resource_counts2 |= (rangesused)

#else /* #if TCPU_IA32 */

#error unknown target CPU!!!

#endif /* #if TCPU_??? */

#include "bus_resources_portio.h"

#endif /* _BUS_RESOURCES_H */