version 4.2.0
[fx2fw-sdcc] / fx2 / isr.c
1 /* -*- c++ -*- */\r
2 /*-----------------------------------------------------------------------------\r
3  * Interrupt handling for FX2\r
4  *-----------------------------------------------------------------------------\r
5  * Code taken from USRP2 firmware (GNU Radio Project), version 3.0.2,\r
6  * Copyright 2003 Free Software Foundation, Inc.\r
7  *-----------------------------------------------------------------------------\r
8  * This code is part of usbjtag. usbjtag is free software; you can redistribute\r
9  * it and/or modify it under the terms of the GNU General Public License as\r
10  * published by the Free Software Foundation; either version 2 of the License,\r
11  * or (at your option) any later version. usbjtag is distributed in the hope\r
12  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\r
13  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.  You should have received a\r
15  * copy of the GNU General Public License along with this program in the file\r
16  * COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
17  * St, Fifth Floor, Boston, MA  02110-1301  USA\r
18  *-----------------------------------------------------------------------------\r
19  */\r
20 \r
21 #include "isr.h"\r
22 #include "fx2regs.h"\r
23 #include "syncdelay.h"\r
24 \r
25 extern xdata unsigned char _standard_interrupt_vector[];\r
26 extern xdata unsigned char _usb_autovector[];\r
27 extern xdata unsigned char _fifo_gpif_autovector[];\r
28 \r
29 #define LJMP_OPCODE     0x02\r
30 \r
31 /*\r
32  * Hook standard interrupt vector.\r
33  *\r
34  * vector_number is from the SV_<foo> list.\r
35  * addr is the address of the interrupt service routine.\r
36  */\r
37 void \r
38 hook_sv (unsigned char vector_number, unsigned short addr)\r
39 {\r
40   bit   t;\r
41   \r
42   // sanity checks\r
43 \r
44   if (vector_number < SV_MIN || vector_number > SV_MAX)\r
45     return;\r
46 \r
47   if ((vector_number & 0x0f) != 0x03 && (vector_number & 0x0f) != 0x0b)\r
48     return;\r
49 \r
50   t = EA;\r
51   EA = 0;\r
52   _standard_interrupt_vector[vector_number] = LJMP_OPCODE;\r
53   _standard_interrupt_vector[vector_number + 1] = addr >> 8;\r
54   _standard_interrupt_vector[vector_number + 2] = addr & 0xff;\r
55   EA = t;\r
56 }\r
57 \r
58 /*\r
59  * Hook usb interrupt vector.\r
60  *\r
61  * vector_number is from the UV_<foo> list.\r
62  * addr is the address of the interrupt service routine.\r
63  */\r
64 void \r
65 hook_uv (unsigned char vector_number, unsigned short addr)\r
66 {\r
67   bit   t;\r
68   \r
69   // sanity checks\r
70 \r
71 #if UV_MIN>0\r
72   if (vector_number < UV_MIN) return;\r
73 #endif\r
74   if (vector_number > UV_MAX)\r
75     return;\r
76 \r
77   if ((vector_number & 0x3) != 0)\r
78     return;\r
79 \r
80   t = EA;\r
81   EA = 0;\r
82   _usb_autovector[vector_number] = LJMP_OPCODE;\r
83   _usb_autovector[vector_number + 1] = addr >> 8;\r
84   _usb_autovector[vector_number + 2] = addr & 0xff;\r
85   EA = t;\r
86 }\r
87 \r
88 /*\r
89  * Hook fifo/gpif interrupt vector.\r
90  *\r
91  * vector_number is from the FGV_<foo> list.\r
92  * addr is the address of the interrupt service routine.\r
93  */\r
94 void \r
95 hook_fgv (unsigned char vector_number, unsigned short addr)\r
96 {\r
97   bit   t;\r
98   \r
99   // sanity checks\r
100 \r
101   if (vector_number < FGV_MIN || vector_number > FGV_MAX)\r
102     return;\r
103 \r
104   if ((vector_number & 0x3) != 0)\r
105     return;\r
106 \r
107   t = EA;\r
108   EA = 0;\r
109   _fifo_gpif_autovector[vector_number] = LJMP_OPCODE;\r
110   _fifo_gpif_autovector[vector_number + 1] = addr >> 8;\r
111   _fifo_gpif_autovector[vector_number + 2] = addr & 0xff;\r
112   EA = t;\r
113 }\r
114 \r
115 /*\r
116  * One time call to enable autovectoring for both USB and FIFO/GPIF.\r
117  *\r
118  * This disables all USB and FIFO/GPIF interrupts and clears\r
119  * any pending interrupts too.  It leaves the master USB and FIFO/GPIF\r
120  * interrupts enabled.\r
121  */\r
122 void\r
123 setup_autovectors (void)\r
124 {\r
125   // disable master usb and fifo/gpif interrupt enables\r
126   EIUSB = 0;\r
127   EIEX4 = 0;\r
128 \r
129   hook_sv (SV_INT_2, (unsigned short) _usb_autovector);\r
130   hook_sv (SV_INT_4, (unsigned short) _fifo_gpif_autovector);\r
131 \r
132   // disable all fifo interrupt enables\r
133   SYNCDELAY;\r
134   EP2FIFOIE = 0;        SYNCDELAY;\r
135   EP4FIFOIE = 0;        SYNCDELAY;\r
136   EP6FIFOIE = 0;        SYNCDELAY;\r
137   EP8FIFOIE = 0;        SYNCDELAY;\r
138 \r
139   // clear all pending fifo irqs        \r
140   EP2FIFOIRQ = 0xff;    SYNCDELAY;\r
141   EP4FIFOIRQ = 0xff;    SYNCDELAY;\r
142   EP6FIFOIRQ = 0xff;    SYNCDELAY;\r
143   EP8FIFOIRQ = 0xff;    SYNCDELAY;\r
144 \r
145   IBNIE  = 0;\r
146   IBNIRQ = 0xff;\r
147   NAKIE  = 0;\r
148   NAKIRQ = 0xff;\r
149   USBIE  = 0;\r
150   USBIRQ = 0xff;\r
151   EPIE   = 0;\r
152   EPIRQ  = 0xff;\r
153   SYNCDELAY;    GPIFIE = 0;             \r
154   SYNCDELAY;    GPIFIRQ = 0xff;\r
155   USBERRIE = 0;\r
156   USBERRIRQ = 0xff;\r
157   CLRERRCNT = 0;\r
158   \r
159   INTSETUP = bmAV2EN | bmAV4EN | bmINT4IN;\r
160 \r
161   // clear master irq's for usb and fifo/gpif\r
162   EXIF &= ~bmEXIF_USBINT;\r
163   EXIF &= ~bmEXIF_IE4;\r
164   \r
165   // enable master usb and fifo/gpif interrrupts\r
166   EIUSB = 1;\r
167   EIEX4 = 1;\r
168 }\r