summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/motorola_powerpc/irq/i8259.c
blob: c5c31e2d23444075788740f3cb6d9d3742b6ad55 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

/*
 *  This file contains the implementation of the function described in irq.h
 *  related to Intel 8259 Programmable Interrupt controller.
 *
 *  Copyright (C) 1998, 1999 valette@crf.canon.fr
 *
 *  The license and distribution terms for this file may be
 *  found in found in the file LICENSE in this distribution or at
 *  http://www.OARcorp.com/rtems/license.html.
 *
 *  $Id$
 */
  
#include <bsp.h>
#include <bsp/irq.h>

/*-------------------------------------------------------------------------+
| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register.
+--------------------------------------------------------------------------*/
/*
 * lower byte is interrupt mask on the master PIC.
 * while upper bits are interrupt on the slave PIC.
 * This cache is initialized in ldseg.s
 */
volatile rtems_i8259_masks i8259s_cache;

/*-------------------------------------------------------------------------+
|         Function:  BSP_irq_disable_at_i8259s
|      Description: Mask IRQ line in appropriate PIC chip.
| Global Variables: i8259s_cache
|        Arguments: vector_offset - number of IRQ line to mask.
|          Returns: Nothing. 
+--------------------------------------------------------------------------*/
int BSP_irq_disable_at_i8259s    (const rtems_irq_symbolic_name irqLine)
{
  unsigned short mask;
  unsigned int 	level;

  if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) ||
       ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET)
       )
    return 1;
  
  _CPU_ISR_Disable(level);
  
  mask = 1 << irqLine;
  i8259s_cache |= mask;
  
  if (irqLine < 8)
  {
    outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
  }
  else
  {
    outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) > 8));
  }
  _CPU_ISR_Enable (level);

  return 0;
} 

/*-------------------------------------------------------------------------+
|         Function:  BSP_irq_enable_at_i8259s
|      Description: Unmask IRQ line in appropriate PIC chip.
| Global Variables: i8259s_cache
|        Arguments: irqLine - number of IRQ line to mask.
|          Returns: Nothing. 
+--------------------------------------------------------------------------*/
int BSP_irq_enable_at_i8259s    (const rtems_irq_symbolic_name irqLine)
{
  unsigned short mask;
  unsigned int 	level;

  if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) ||
       ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET )
       )
    return 1;

  _CPU_ISR_Disable(level);
  
  mask = ~(1 << irqLine);
  i8259s_cache &= mask;
  
  if (irqLine < 8)
  {
    outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
  }
  else
  {
    outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) > 8));
  }
  _CPU_ISR_Enable (level);

  return 0;
} /* mask_irq */

int BSP_irq_enabled_at_i8259s        	(const rtems_irq_symbolic_name irqLine)
{
  unsigned short mask;

  if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) ||
       ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET)
     )
    return 1;

  mask = (1 << irqLine);
  return  (~(i8259s_cache & mask));
}
  

/*-------------------------------------------------------------------------+
|         Function: BSP_irq_ack_at_i8259s
|      Description: Signal generic End Of Interrupt (EOI) to appropriate PIC.
| Global Variables: None.
|        Arguments: irqLine - number of IRQ line to acknowledge.
|          Returns: Nothing. 
+--------------------------------------------------------------------------*/
int BSP_irq_ack_at_i8259s  	(const rtems_irq_symbolic_name irqLine)
{
  if (irqLine >= 8) {
   outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI);
  }
  outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI);

  return 0;

} /* ackIRQ */

void BSP_i8259s_init(void)
{
  /*
   * init master 8259 interrupt controller
   */
  outport_byte(PIC_MASTER_COMMAND_IO_PORT, 0x11); /* Start init sequence */
  outport_byte(PIC_MASTER_IMR_IO_PORT, 0x00);/* Vector base  = 0 */
  outport_byte(PIC_MASTER_IMR_IO_PORT, 0x04);/* edge tiggered, Cascade (slave) on IRQ2 */
  outport_byte(PIC_MASTER_IMR_IO_PORT, 0x01);/* Select 8086 mode */
  outport_byte(PIC_MASTER_IMR_IO_PORT, 0xFB); /* Mask all except cascade */
  /*
   * init slave  interrupt controller
   */
  outport_byte(PIC_SLAVE_COMMAND_IO_PORT, 0x11); /* Start init sequence */
  outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x08);/* Vector base  = 8 */
  outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x02);/* edge triggered, Cascade (slave) on IRQ2 */
  outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x01); /* Select 8086 mode */
  outport_byte(PIC_SLAVE_IMR_IO_PORT, 0xFF); /* Mask all */
  
  i8259s_cache = 0xFFFB;
}