OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [frv/] [frv400/] [v2_0/] [src/] [frv400_misc.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      frv400_misc.c
4
//
5
//      HAL misc board support code for Fujitsu MB93091 ( FR-V 400)
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    gthomas
44
// Contributors: gthomas
45
// Date:         2001-09-07
46
// Purpose:      HAL board support
47
// Description:  Implementations of HAL board interfaces
48
//
49
//####DESCRIPTIONEND####
50
//
51
//========================================================================*/
52
 
53
#include <pkgconf/hal.h>
54
#include <pkgconf/system.h>
55
#include CYGBLD_HAL_PLATFORM_H
56
 
57
#include <cyg/infra/cyg_type.h>         // base types
58
#include <cyg/infra/cyg_trac.h>         // tracing macros
59
#include <cyg/infra/cyg_ass.h>          // assertion macros
60
#include <cyg/infra/diag.h>             // diag_printf() and friends
61
 
62
#include <cyg/hal/hal_io.h>             // IO macros
63
#include <cyg/hal/hal_arch.h>           // Register state info
64
#include <cyg/hal/hal_diag.h>
65
#include <cyg/hal/hal_intr.h>           // Interrupt names
66
#include <cyg/hal/hal_cache.h>
67
#include <cyg/hal/frv400.h>             // Hardware definitions
68
#include <cyg/hal/hal_if.h>             // calling interface API
69
 
70
#include <pkgconf/io_pci.h>
71
#include <cyg/io/pci_hw.h>
72
#include <cyg/io/pci.h>
73
 
74
static cyg_uint32 _period;
75
 
76
void hal_clock_initialize(cyg_uint32 period)
77
{
78
    _period = period;
79
    // Set timer #1 to run in terminal count mode for period
80
    HAL_WRITE_UINT8(_FRV400_TCTR, _FRV400_TCTR_SEL1|_FRV400_TCTR_RLOHI|_FRV400_TCTR_MODE0);
81
    HAL_WRITE_UINT8(_FRV400_TCSR1, period & 0xFF);
82
    HAL_WRITE_UINT8(_FRV400_TCSR1, period >> 8);
83
    // Configure interrupt
84
    HAL_INTERRUPT_CONFIGURE(CYGNUM_HAL_INTERRUPT_TIMER1, 1, 1);  // Interrupt when TOUT1 is high
85
}
86
 
87
void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
88
{
89
    cyg_int16 offset;
90
    cyg_uint8 _val;
91
 
92
    // Latch & read counter from timer #1
93
    HAL_WRITE_UINT8(_FRV400_TCTR, _FRV400_TCTR_LATCH|_FRV400_TCTR_RLOHI|_FRV400_TCTR_SEL1);
94
    HAL_READ_UINT8(_FRV400_TCSR1, _val);
95
    offset = _val;
96
    HAL_READ_UINT8(_FRV400_TCSR1, _val);
97
    offset |= _val << 8;    // This will be the number of clocks beyond 0
98
    period += offset;
99
    // Reinitialize with adjusted count
100
    // Set timer #1 to run in terminal count mode for period
101
    HAL_WRITE_UINT8(_FRV400_TCTR, _FRV400_TCTR_SEL1|_FRV400_TCTR_RLOHI|_FRV400_TCTR_MODE0);
102
    HAL_WRITE_UINT8(_FRV400_TCSR1, period & 0xFF);
103
    HAL_WRITE_UINT8(_FRV400_TCSR1, period >> 8);
104
}
105
 
106
// Read the current value of the clock, returning the number of hardware "ticks"
107
// that have occurred (i.e. how far away the current value is from the start)
108
 
109
void hal_clock_read(cyg_uint32 *pvalue)
110
{
111
    cyg_int16 offset;
112
    cyg_uint8 _val;
113
 
114
    // Latch & read counter from timer #1
115
    HAL_WRITE_UINT8(_FRV400_TCTR, _FRV400_TCTR_LATCH|_FRV400_TCTR_RLOHI|_FRV400_TCTR_SEL1);
116
    HAL_READ_UINT8(_FRV400_TCSR1, _val);
117
    offset = _val;
118
    HAL_READ_UINT8(_FRV400_TCSR1, _val);
119
    offset |= _val << 8;
120
 
121
    // 'offset' is the current timer value
122
    *pvalue = _period - offset;
123
}
124
 
125
// Delay for some number of useconds.
126
// Assumptions:
127
//   Use timer #2
128
//   Min granularity is 10us
129
#define _MIN_DELAY 10
130
 
131
void hal_delay_us(int us)
132
{
133
    cyg_uint8 stat;
134
    int timeout;
135
 
136
    while (us >= _MIN_DELAY) {
137
        us -= _MIN_DELAY;
138
        // Set timer #2 to run in terminal count mode for _MIN_DELAY us
139
        HAL_WRITE_UINT8(_FRV400_TCTR, _FRV400_TCTR_SEL2|_FRV400_TCTR_RLOHI|_FRV400_TCTR_MODE0);
140
        HAL_WRITE_UINT8(_FRV400_TCSR2, _MIN_DELAY & 0xFF);
141
        HAL_WRITE_UINT8(_FRV400_TCSR2, _MIN_DELAY >> 8);
142
        timeout = 100000;
143
        // Wait for TOUT to indicate terminal count reached
144
        do {
145
            HAL_WRITE_UINT8(_FRV400_TCTR, _FRV400_TCTR_RB|_FRV400_TCTR_RB_NCOUNT|_FRV400_TCTR_RB_CTR2);
146
            HAL_READ_UINT8(_FRV400_TCSR2, stat);
147
            if (--timeout == 0) break;
148
        } while ((stat & _FRV400_TCxSR_TOUT) == 0);
149
    }
150
}
151
 
152
//
153
// Early stage hardware initialization
154
//   Some initialization has already been done before we get here.  For now
155
// just set up the interrupt environment.
156
 
157
long _system_clock;  // Calculated clock frequency
158
 
159
void hal_hardware_init(void)
160
{
161
    cyg_uint32 clk;
162
 
163
    // Set up interrupt controller
164
    HAL_WRITE_UINT16(_FRV400_IRC_MASK, 0xFFFE);  // All masked
165
    HAL_WRITE_UINT16(_FRV400_IRC_RC, 0xFFFE);    // All cleared
166
    HAL_WRITE_UINT16(_FRV400_IRC_IRL, 0x10);     // Clear IRL (interrupt request latch)    
167
 
168
    // Onboard FPGA interrupts
169
    HAL_WRITE_UINT16(_FRV400_FPGA_CONTROL, _FRV400_FPGA_CONTROL_IRQ);  // Enable IRQ registers
170
    HAL_WRITE_UINT16(_FRV400_FPGA_IRQ_MASK,      // Set up for LAN, PCI INTx
171
                     0x7FFE &
172
                     ~(_FRV400_FPGA_IRQ_LAN |
173
                       _FRV400_FPGA_IRQ_INTA |
174
                       _FRV400_FPGA_IRQ_INTB |
175
                       _FRV400_FPGA_IRQ_INTC |
176
                       _FRV400_FPGA_IRQ_INTD)
177
        );
178
    HAL_WRITE_UINT16(_FRV400_FPGA_IRQ_LEVELS,    // Set up for LAN, PCI INTx
179
                     0x7FFE &
180
                     ~(_FRV400_FPGA_IRQ_LAN |
181
                       _FRV400_FPGA_IRQ_INTA |
182
                       _FRV400_FPGA_IRQ_INTB |
183
                       _FRV400_FPGA_IRQ_INTC |
184
                       _FRV400_FPGA_IRQ_INTD)
185
        );
186
    HAL_INTERRUPT_CONFIGURE(CYGNUM_HAL_INTERRUPT_LAN, 1, 0);  // Level, low
187
 
188
    // Set up system clock
189
    HAL_READ_UINT32(_FRV400_MB_CLKSW, clk);
190
    _system_clock = (((clk&0xFF) * 125 * 2) / 240) * 1000000;
191
 
192
    // Set scalers to achieve 1us resolution in timer
193
    HAL_WRITE_UINT8(_FRV400_TPRV, _system_clock / (1000*1000));
194
    HAL_WRITE_UINT8(_FRV400_TCKSL0, 0x80);
195
    HAL_WRITE_UINT8(_FRV400_TCKSL1, 0x80);
196
    HAL_WRITE_UINT8(_FRV400_TCKSL2, 0x80);
197
 
198
    hal_if_init();
199
 
200
    // Initialize real-time clock (for delays, etc, even if kernel doesn't use it)
201
    hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
202
 
203
    _frv400_pci_init();
204
}
205
 
206
//
207
// Interrupt control
208
//
209
 
210
void hal_interrupt_mask(int vector)
211
{
212
    cyg_uint16 _mask;
213
 
214
    switch (vector) {
215
    case CYGNUM_HAL_INTERRUPT_LAN:
216
        HAL_READ_UINT16(_FRV400_FPGA_IRQ_MASK, _mask);
217
        _mask |= _FRV400_FPGA_IRQ_LAN;
218
        HAL_WRITE_UINT16(_FRV400_FPGA_IRQ_MASK, _mask);
219
        break;
220
    }
221
    HAL_READ_UINT16(_FRV400_IRC_MASK, _mask);
222
    _mask |= (1<<(vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1));
223
    HAL_WRITE_UINT16(_FRV400_IRC_MASK, _mask);
224
}
225
 
226
void hal_interrupt_unmask(int vector)
227
{
228
    cyg_uint16 _mask;
229
 
230
    switch (vector) {
231
    case CYGNUM_HAL_INTERRUPT_LAN:
232
        HAL_READ_UINT16(_FRV400_FPGA_IRQ_MASK, _mask);
233
        _mask &= ~_FRV400_FPGA_IRQ_LAN;
234
        HAL_WRITE_UINT16(_FRV400_FPGA_IRQ_MASK, _mask);
235
        break;
236
    }
237
    HAL_READ_UINT16(_FRV400_IRC_MASK, _mask);
238
    _mask &= ~(1<<(vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1));
239
    HAL_WRITE_UINT16(_FRV400_IRC_MASK, _mask);
240
}
241
 
242
void hal_interrupt_acknowledge(int vector)
243
{
244
    cyg_uint16 _mask;
245
 
246
    switch (vector) {
247
    case CYGNUM_HAL_INTERRUPT_LAN:
248
        HAL_WRITE_UINT16(_FRV400_FPGA_IRQ_REQUEST,      // Clear LAN interrupt
249
                         0x7FFE & ~_FRV400_FPGA_IRQ_LAN);
250
        break;
251
    }
252
    _mask = (1<<(vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1));
253
    HAL_WRITE_UINT16(_FRV400_IRC_RC, _mask);
254
    HAL_WRITE_UINT16(_FRV400_IRC_IRL, 0x10);  // Clears IRL latch
255
}
256
 
257
//
258
// Configure an interrupt
259
//  level - boolean (0=> edge, 1=>level)
260
//  up - edge: (0=>falling edge, 1=>rising edge)
261
//       level: (0=>low, 1=>high)
262
//
263
void hal_interrupt_configure(int vector, int level, int up)
264
{
265
    cyg_uint16 _irr, _tmr, _trig;
266
 
267
    if (level) {
268
        if (up) {
269
            _trig = 0;     // level, high
270
        } else {
271
            _trig = 1;     // level, low
272
        }
273
    } else {
274
        if (up) {
275
            _trig = 2;     // edge, rising
276
        } else {
277
            _trig = 3;     // edge, falling
278
        }
279
    }
280
    switch (vector) {
281
    case  CYGNUM_HAL_INTERRUPT_TIMER0:
282
        HAL_READ_UINT16(_FRV400_IRC_IRR5, _irr);
283
        _irr = (_irr & 0xFFF0) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<0);
284
        HAL_WRITE_UINT16(_FRV400_IRC_IRR5, _irr);
285
        HAL_READ_UINT16(_FRV400_IRC_ITM0, _tmr);
286
        _tmr = (_tmr & 0xFFFC) | (_trig<<0);
287
        HAL_WRITE_UINT16(_FRV400_IRC_ITM0, _tmr);
288
        break;
289
    case  CYGNUM_HAL_INTERRUPT_TIMER1:
290
        HAL_READ_UINT16(_FRV400_IRC_IRR5, _irr);
291
        _irr = (_irr & 0xFF0F) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<4);
292
        HAL_WRITE_UINT16(_FRV400_IRC_IRR5, _irr);
293
        HAL_READ_UINT16(_FRV400_IRC_ITM0, _tmr);
294
        _tmr = (_tmr & 0xFFF3) | (_trig<<2);
295
        HAL_WRITE_UINT16(_FRV400_IRC_ITM0, _tmr);
296
        break;
297
    case  CYGNUM_HAL_INTERRUPT_TIMER2:
298
        HAL_READ_UINT16(_FRV400_IRC_IRR5, _irr);
299
        _irr = (_irr & 0xF0FF) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<8);
300
        HAL_WRITE_UINT16(_FRV400_IRC_IRR5, _irr);
301
        HAL_READ_UINT16(_FRV400_IRC_ITM0, _tmr);
302
        _tmr = (_tmr & 0xFFCF) | (_trig<<4);
303
        HAL_WRITE_UINT16(_FRV400_IRC_ITM0, _tmr);
304
        break;
305
    case  CYGNUM_HAL_INTERRUPT_DMA0:
306
        HAL_READ_UINT16(_FRV400_IRC_IRR4, _irr);
307
        _irr = (_irr & 0xFFF0) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<0);
308
        HAL_WRITE_UINT16(_FRV400_IRC_IRR4, _irr);
309
        HAL_READ_UINT16(_FRV400_IRC_ITM0, _tmr);
310
        _tmr = (_tmr & 0xFCFF) | (_trig<<8);
311
        HAL_WRITE_UINT16(_FRV400_IRC_ITM0, _tmr);
312
        break;
313
    case  CYGNUM_HAL_INTERRUPT_DMA1:
314
        HAL_READ_UINT16(_FRV400_IRC_IRR4, _irr);
315
        _irr = (_irr & 0xFF0F) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<4);
316
        HAL_WRITE_UINT16(_FRV400_IRC_IRR4, _irr);
317
        HAL_READ_UINT16(_FRV400_IRC_ITM0, _tmr);
318
        _tmr = (_tmr & 0xF3FF) | (_trig<<10);
319
        HAL_WRITE_UINT16(_FRV400_IRC_ITM0, _tmr);
320
        break;
321
    case  CYGNUM_HAL_INTERRUPT_DMA2:
322
        HAL_READ_UINT16(_FRV400_IRC_IRR4, _irr);
323
        _irr = (_irr & 0xF0FF) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<8);
324
        HAL_WRITE_UINT16(_FRV400_IRC_IRR4, _irr);
325
        HAL_READ_UINT16(_FRV400_IRC_ITM0, _tmr);
326
        _tmr = (_tmr & 0xCFFF) | (_trig<<12);
327
        HAL_WRITE_UINT16(_FRV400_IRC_ITM0, _tmr);
328
        break;
329
    case  CYGNUM_HAL_INTERRUPT_DMA3:
330
        HAL_READ_UINT16(_FRV400_IRC_IRR4, _irr);
331
        _irr = (_irr & 0x0FFF) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<12);
332
        HAL_WRITE_UINT16(_FRV400_IRC_IRR4, _irr);
333
        HAL_READ_UINT16(_FRV400_IRC_ITM0, _tmr);
334
        _tmr = (_tmr & 0x3FFF) | (_trig<<14);
335
        HAL_WRITE_UINT16(_FRV400_IRC_ITM0, _tmr);
336
        break;
337
    case  CYGNUM_HAL_INTERRUPT_UART0:
338
        HAL_READ_UINT16(_FRV400_IRC_IRR6, _irr);
339
        _irr = (_irr & 0xFFF0) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<0);
340
        HAL_WRITE_UINT16(_FRV400_IRC_IRR6, _irr);
341
        HAL_READ_UINT16(_FRV400_IRC_ITM1, _tmr);
342
        _tmr = (_tmr & 0xFCFF) | (_trig<<8);
343
        HAL_WRITE_UINT16(_FRV400_IRC_ITM1, _tmr);
344
        break;
345
    case  CYGNUM_HAL_INTERRUPT_UART1:
346
        HAL_READ_UINT16(_FRV400_IRC_IRR6, _irr);
347
        _irr = (_irr & 0xFF0F) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<4);
348
        HAL_WRITE_UINT16(_FRV400_IRC_IRR6, _irr);
349
        HAL_READ_UINT16(_FRV400_IRC_ITM1, _tmr);
350
        _tmr = (_tmr & 0xF3FF) | (_trig<<10);
351
        HAL_WRITE_UINT16(_FRV400_IRC_ITM1, _tmr);
352
        break;
353
    case  CYGNUM_HAL_INTERRUPT_EXT0:
354
        HAL_READ_UINT16(_FRV400_IRC_IRR3, _irr);
355
        _irr = (_irr & 0xFFF0) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<0);
356
        HAL_WRITE_UINT16(_FRV400_IRC_IRR3, _irr);
357
        HAL_READ_UINT16(_FRV400_IRC_TM1, _tmr);
358
        _tmr = (_tmr & 0xFFFC) | (_trig<<0);
359
        HAL_WRITE_UINT16(_FRV400_IRC_TM1, _tmr);
360
        break;
361
    case  CYGNUM_HAL_INTERRUPT_EXT1:
362
        HAL_READ_UINT16(_FRV400_IRC_IRR3, _irr);
363
        _irr = (_irr & 0xFF0F) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<4);
364
        HAL_WRITE_UINT16(_FRV400_IRC_IRR3, _irr);
365
        HAL_READ_UINT16(_FRV400_IRC_TM1, _tmr);
366
        _tmr = (_tmr & 0xFFF3) | (_trig<<2);
367
        HAL_WRITE_UINT16(_FRV400_IRC_TM1, _tmr);
368
        break;
369
    case  CYGNUM_HAL_INTERRUPT_EXT2:
370
        HAL_READ_UINT16(_FRV400_IRC_IRR3, _irr);
371
        _irr = (_irr & 0xF0FF) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<8);
372
        HAL_WRITE_UINT16(_FRV400_IRC_IRR3, _irr);
373
        HAL_READ_UINT16(_FRV400_IRC_TM1, _tmr);
374
        _tmr = (_tmr & 0xFFCF) | (_trig<<4);
375
        HAL_WRITE_UINT16(_FRV400_IRC_TM1, _tmr);
376
        break;
377
    case  CYGNUM_HAL_INTERRUPT_EXT3:
378
        HAL_READ_UINT16(_FRV400_IRC_IRR3, _irr);
379
        _irr = (_irr & 0x0FFF) | ((vector-CYGNUM_HAL_VECTOR_EXTERNAL_INTERRUPT_LEVEL_1+1)<<12);
380
        HAL_WRITE_UINT16(_FRV400_IRC_IRR3, _irr);
381
        HAL_READ_UINT16(_FRV400_IRC_TM1, _tmr);
382
        _tmr = (_tmr & 0xFF3F) | (_trig<<6);
383
        HAL_WRITE_UINT16(_FRV400_IRC_TM1, _tmr);
384
        break;
385
    default:
386
        ; // Nothing to do
387
    };
388
}
389
 
390
void hal_interrupt_set_level(int vector, int level)
391
{
392
//    UNIMPLEMENTED(__FUNCTION__);
393
}
394
 
395
// PCI support
396
 
397
externC void
398
_frv400_pci_init(void)
399
{
400
    static int _init = 0;
401
    cyg_uint8 next_bus;
402
    cyg_uint32 cmd_state;
403
 
404
    if (_init) return;
405
    _init = 1;
406
 
407
    // Enable controller - most of the basic configuration
408
    // was set up at boot time in "platform.inc"
409
 
410
    // Setup for bus mastering
411
    HAL_PCI_CFG_READ_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0),
412
                            CYG_PCI_CFG_COMMAND, cmd_state);
413
    if ((cmd_state & CYG_PCI_CFG_COMMAND_MEMORY) == 0) {
414
        HAL_PCI_CFG_WRITE_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0),
415
                                 CYG_PCI_CFG_COMMAND,
416
                                 CYG_PCI_CFG_COMMAND_MEMORY |
417
                                 CYG_PCI_CFG_COMMAND_MASTER |
418
                                 CYG_PCI_CFG_COMMAND_PARITY |
419
                                 CYG_PCI_CFG_COMMAND_SERR);
420
 
421
        // Setup latency timer field
422
        HAL_PCI_CFG_WRITE_UINT8(0, CYG_PCI_DEV_MAKE_DEVFN(0,0),
423
                                CYG_PCI_CFG_LATENCY_TIMER, 32);
424
 
425
        // Configure PCI bus.
426
        next_bus = 1;
427
        cyg_pci_configure_bus(0, &next_bus);
428
    }
429
 
430
}
431
 
432
externC void
433
_frv400_pci_translate_interrupt(int bus, int devfn, int *vec, int *valid)
434
{
435
    cyg_uint8 req;
436
    cyg_uint8 dev = CYG_PCI_DEV_GET_DEV(devfn);
437
 
438
    if (dev == CYG_PCI_MIN_DEV) {
439
        // On board LAN
440
        *vec = CYGNUM_HAL_INTERRUPT_LAN;
441
        *valid = true;
442
    } else {
443
        HAL_PCI_CFG_READ_UINT8(bus, devfn, CYG_PCI_CFG_INT_PIN, req);
444
        if (0 != req) {
445
            CYG_ADDRWORD __translation[4] = {
446
                CYGNUM_HAL_INTERRUPT_PCIINTC,   /* INTC# */
447
                CYGNUM_HAL_INTERRUPT_PCIINTB,   /* INTB# */
448
                CYGNUM_HAL_INTERRUPT_PCIINTA,   /* INTA# */
449
                CYGNUM_HAL_INTERRUPT_PCIINTD};  /* INTD# */
450
 
451
            /* The PCI lines from the different slots are wired like this  */
452
            /* on the PCI backplane:                                       */
453
            /*                pin6A     pin7B    pin7A   pin8B             */
454
            /* I/O Slot 1     INTA#     INTB#    INTC#   INTD#             */
455
            /* I/O Slot 2     INTD#     INTA#    INTB#   INTC#             */
456
            /* I/O Slot 3     INTC#     INTD#    INTA#   INTB#             */
457
            /*                                                             */
458
            /* (From PCI Development Backplane, 3.2.2 Interrupts)          */
459
            /*                                                             */
460
            /* Devsel signals are wired to, resulting in device IDs:       */
461
            /* I/O Slot 1     AD30 / dev 19      [(8+1)&3 = 1]             */
462
            /* I/O Slot 2     AD29 / dev 18      [(7+1)&3 = 0]             */
463
            /* I/O Slot 3     AD28 / dev 17      [(6+1)&3 = 3]             */
464
 
465
            *vec = __translation[((req+dev)&3)];
466
            *valid = true;
467
        } else {
468
            /* Device will not generate interrupt requests. */
469
            *valid = false;
470
        }
471
        diag_printf("Int - dev: %d, req: %d, vector: %d\n", dev, req, *vec);
472
    }
473
}
474
 
475
// PCI configuration space access
476
#define _EXT_ENABLE 0x80000000  // Could be 0x80000000
477
 
478
static __inline__ cyg_uint32
479
_cfg_addr(int bus, int devfn, int offset)
480
{
481
    return _EXT_ENABLE | (bus << 22) | (devfn << 8) | (offset << 0);
482
}
483
 
484
externC cyg_uint8
485
_frv400_pci_cfg_read_uint8(int bus, int devfn, int offset)
486
{
487
    cyg_uint32 cfg_addr, addr, status;
488
    cyg_uint8 cfg_val = (cyg_uint8)0xFF;
489
 
490
#ifdef CYGPKG_IO_PCI_DEBUG
491
    diag_printf("%s(bus=%x, devfn=%x, offset=%x) = ", __FUNCTION__, bus, devfn, offset);
492
#endif // CYGPKG_IO_PCI_DEBUG
493
    if ((bus == 0) && (CYG_PCI_DEV_GET_DEV(devfn) == 0)) {
494
        // PCI bridge
495
        addr = _FRV400_PCI_CONFIG + ((offset << 1) ^ 0x03);
496
    } else {
497
        cfg_addr = _cfg_addr(bus, devfn, offset ^ 0x03);
498
        HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, cfg_addr);
499
        addr = _FRV400_PCI_CONFIG_DATA + ((offset & 0x03) ^ 0x03);
500
    }
501
    HAL_READ_UINT8(addr, cfg_val);
502
    HAL_READ_UINT16(_FRV400_PCI_STAT_CMD, status);
503
    if (status & _FRV400_PCI_STAT_ERROR_MASK) {
504
        // Cycle failed - clean up and get out
505
        cfg_val = (cyg_uint8)0xFF;
506
        HAL_WRITE_UINT16(_FRV400_PCI_STAT_CMD, status & _FRV400_PCI_STAT_ERROR_MASK);
507
    }
508
#ifdef CYGPKG_IO_PCI_DEBUG
509
    diag_printf("%x\n", cfg_val);
510
#endif // CYGPKG_IO_PCI_DEBUG
511
    HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, 0);
512
    return cfg_val;
513
}
514
 
515
externC cyg_uint16
516
_frv400_pci_cfg_read_uint16(int bus, int devfn, int offset)
517
{
518
    cyg_uint32 cfg_addr, addr, status;
519
    cyg_uint16 cfg_val = (cyg_uint16)0xFFFF;
520
 
521
#ifdef CYGPKG_IO_PCI_DEBUG
522
    diag_printf("%s(bus=%x, devfn=%x, offset=%x) = ", __FUNCTION__, bus, devfn, offset);
523
#endif // CYGPKG_IO_PCI_DEBUG
524
    if ((bus == 0) && (CYG_PCI_DEV_GET_DEV(devfn) == 0)) {
525
        // PCI bridge
526
        addr = _FRV400_PCI_CONFIG + ((offset << 1) ^ 0x02);
527
    } else {
528
        cfg_addr = _cfg_addr(bus, devfn, offset ^ 0x02);
529
        HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, cfg_addr);
530
        addr = _FRV400_PCI_CONFIG_DATA + ((offset & 0x03) ^ 0x02);
531
    }
532
    HAL_READ_UINT16(addr, cfg_val);
533
    HAL_READ_UINT16(_FRV400_PCI_STAT_CMD, status);
534
    if (status & _FRV400_PCI_STAT_ERROR_MASK) {
535
        // Cycle failed - clean up and get out
536
        cfg_val = (cyg_uint16)0xFFFF;
537
        HAL_WRITE_UINT16(_FRV400_PCI_STAT_CMD, status & _FRV400_PCI_STAT_ERROR_MASK);
538
    }
539
#ifdef CYGPKG_IO_PCI_DEBUG
540
    diag_printf("%x\n", cfg_val);
541
#endif // CYGPKG_IO_PCI_DEBUG
542
    HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, 0);
543
    return cfg_val;
544
}
545
 
546
externC cyg_uint32
547
_frv400_pci_cfg_read_uint32(int bus, int devfn, int offset)
548
{
549
    cyg_uint32 cfg_addr, addr, status;
550
    cyg_uint32 cfg_val = (cyg_uint32)0xFFFFFFFF;
551
 
552
#ifdef CYGPKG_IO_PCI_DEBUG
553
    diag_printf("%s(bus=%x, devfn=%x, offset=%x) = ", __FUNCTION__, bus, devfn, offset);
554
#endif // CYGPKG_IO_PCI_DEBUG
555
    if ((bus == 0) && (CYG_PCI_DEV_GET_DEV(devfn) == 0)) {
556
        // PCI bridge
557
        addr = _FRV400_PCI_CONFIG + (offset << 1);
558
    } else {
559
        cfg_addr = _cfg_addr(bus, devfn, offset);
560
        HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, cfg_addr);
561
        addr = _FRV400_PCI_CONFIG_DATA;
562
    }
563
    HAL_READ_UINT32(addr, cfg_val);
564
    HAL_READ_UINT16(_FRV400_PCI_STAT_CMD, status);
565
    if (status & _FRV400_PCI_STAT_ERROR_MASK) {
566
        // Cycle failed - clean up and get out
567
        cfg_val = (cyg_uint32)0xFFFFFFFF;
568
        HAL_WRITE_UINT16(_FRV400_PCI_STAT_CMD, status & _FRV400_PCI_STAT_ERROR_MASK);
569
    }
570
#ifdef CYGPKG_IO_PCI_DEBUG
571
    diag_printf("%x\n", cfg_val);
572
#endif // CYGPKG_IO_PCI_DEBUG
573
    HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, 0);
574
    return cfg_val;
575
}
576
 
577
externC void
578
_frv400_pci_cfg_write_uint8(int bus, int devfn, int offset, cyg_uint8 cfg_val)
579
{
580
    cyg_uint32 cfg_addr, addr, status;
581
 
582
#ifdef CYGPKG_IO_PCI_DEBUG
583
    diag_printf("%s(bus=%x, devfn=%x, offset=%x, val=%x)\n", __FUNCTION__, bus, devfn, offset, cfg_val);
584
#endif // CYGPKG_IO_PCI_DEBUG
585
    if ((bus == 0) && (CYG_PCI_DEV_GET_DEV(devfn) == 0)) {
586
        // PCI bridge
587
        addr = _FRV400_PCI_CONFIG + ((offset << 1) ^ 0x03);
588
    } else {
589
        cfg_addr = _cfg_addr(bus, devfn, offset ^ 0x03);
590
        HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, cfg_addr);
591
        addr = _FRV400_PCI_CONFIG_DATA + ((offset & 0x03) ^ 0x03);
592
    }
593
    HAL_WRITE_UINT8(addr, cfg_val);
594
    HAL_READ_UINT16(_FRV400_PCI_STAT_CMD, status);
595
    if (status & _FRV400_PCI_STAT_ERROR_MASK) {
596
        // Cycle failed - clean up and get out
597
        HAL_WRITE_UINT16(_FRV400_PCI_STAT_CMD, status & _FRV400_PCI_STAT_ERROR_MASK);
598
    }
599
    HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, 0);
600
}
601
 
602
externC void
603
_frv400_pci_cfg_write_uint16(int bus, int devfn, int offset, cyg_uint16 cfg_val)
604
{
605
    cyg_uint32 cfg_addr, addr, status;
606
 
607
#ifdef CYGPKG_IO_PCI_DEBUG
608
    diag_printf("%s(bus=%x, devfn=%x, offset=%x, val=%x)\n", __FUNCTION__, bus, devfn, offset, cfg_val);
609
#endif // CYGPKG_IO_PCI_DEBUG
610
    if ((bus == 0) && (CYG_PCI_DEV_GET_DEV(devfn) == 0)) {
611
        // PCI bridge
612
        addr = _FRV400_PCI_CONFIG + ((offset << 1) ^ 0x02);
613
    } else {
614
        cfg_addr = _cfg_addr(bus, devfn, offset ^ 0x02);
615
        HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, cfg_addr);
616
        addr = _FRV400_PCI_CONFIG_DATA + ((offset & 0x03) ^ 0x02);
617
    }
618
    HAL_WRITE_UINT16(addr, cfg_val);
619
    HAL_READ_UINT16(_FRV400_PCI_STAT_CMD, status);
620
    if (status & _FRV400_PCI_STAT_ERROR_MASK) {
621
        // Cycle failed - clean up and get out
622
        HAL_WRITE_UINT16(_FRV400_PCI_STAT_CMD, status & _FRV400_PCI_STAT_ERROR_MASK);
623
    }
624
    HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, 0);
625
}
626
 
627
externC void
628
_frv400_pci_cfg_write_uint32(int bus, int devfn, int offset, cyg_uint32 cfg_val)
629
{
630
    cyg_uint32 cfg_addr, addr, status;
631
 
632
#ifdef CYGPKG_IO_PCI_DEBUG
633
    diag_printf("%s(bus=%x, devfn=%x, offset=%x, val=%x)\n", __FUNCTION__, bus, devfn, offset, cfg_val);
634
#endif // CYGPKG_IO_PCI_DEBUG
635
    if ((bus == 0) && (CYG_PCI_DEV_GET_DEV(devfn) == 0)) {
636
        // PCI bridge
637
        addr = _FRV400_PCI_CONFIG + (offset << 1);
638
    } else {
639
        cfg_addr = _cfg_addr(bus, devfn, offset);
640
        HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, cfg_addr);
641
        addr = _FRV400_PCI_CONFIG_DATA;
642
    }
643
    HAL_WRITE_UINT32(addr, cfg_val);
644
    HAL_READ_UINT16(_FRV400_PCI_STAT_CMD, status);
645
    if (status & _FRV400_PCI_STAT_ERROR_MASK) {
646
        // Cycle failed - clean up and get out
647
        HAL_WRITE_UINT16(_FRV400_PCI_STAT_CMD, status & _FRV400_PCI_STAT_ERROR_MASK);
648
    }
649
    HAL_WRITE_UINT32(_FRV400_PCI_CONFIG_ADDR, 0);
650
}
651
 
652
// ------------------------------------------------------------------------
653
//
654
// Hardware breakpoint/watchpoint support
655
// ======================================
656
//
657
// Now follows a load of extreme unpleasantness to deal with the totally
658
// broken debug model of this device.
659
//
660
// To modify the special hardware debug registers, it is necessary to put
661
// the CPU into "debug mode".  This can only be done by executing a break
662
// instruction, or taking a special hardware break event as described by
663
// the special hardware debug registers.
664
//
665
// But once in debug mode, no break is taken, and break instructions are
666
// ignored, because we are in debug mode.
667
//
668
// So we must exit debug mode for normal running, which you can only do via
669
// a rett #1 instruction.  Because rett is for returning from traps, it
670
// halts the CPU if you do it with traps enabled.  So you have to mess
671
// about disabling traps before the rett.  Also, because rett #1 is for
672
// returning from a *debug* trap, you can only issue it from debug mode -
673
// or it halts the CPU.
674
//
675
// To be able to set and unset hardware debug breakpoints and watchpoints,
676
// we must enter debug mode (via a "break" instruction).  Fortunately, it
677
// is possible to return from a "break" remaining in debug mode, using a
678
// rett #0, so we can arrange that a break instruction just means "go to
679
// debug mode".
680
//
681
// So we can manipulate the special hardware debug registers by executing a
682
// "break", doing the work, then doing the magic sequence to rett #1.
683
// These are encapsulated in HAL_FRV_ENTER_DEBUG_MODE() and
684
// HAL_FRV_EXIT_DEBUG_MODE() from plf_stub.h
685
//
686
// So, we get into break_hander() for two reasons:
687
//   1) a break instruction.  Detect this and do nothing; return skipping
688
//      over the break instruction.  CPU remains in debug mode.
689
//   2) a hardware debug trap.  Continue just as for a normal exception;
690
//      GDB and the stubs will handle it.  But first, exit debug mode, or
691
//      stuff happening in the stubs will go wrong.
692
//
693
// In order to be certain that we are in debug mode, for performing (2)
694
// safely, vectors.S installs a special debug trap handler on vector #255.
695
// That's the reason for break_handler() existing as a separate routine.
696
// 
697
// Note that there is no need to define CYGSEM_HAL_FRV_HW_DEBUG for the
698
// FRV_FRV400 target; while we do use Hardware Debug, we don't use *that*
699
// sort of hardware debug, specifically we do not use hardware single-step,
700
// because it breaks as soon as we exit debug mode, ie. whilst we are still
701
// within the stub.  So in fact defining CYGSEM_HAL_FRV_HW_DEBUG is bad; I
702
// guess it is mis-named.
703
//
704
 
705
// ------------------------------------------------------------------------
706
// First a load of ugly boilerplate for register access.
707
 
708
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
709
 
710
#include <cyg/hal/hal_stub.h>           // HAL_STUB_HW_STOP_NONE et al
711
#include <cyg/hal/frv_stub.h>           // register names PC, PSR et al
712
#include <cyg/hal/plf_stub.h>           // HAL_FRV_EXIT_DEBUG_MODE()
713
 
714
// First a load of glue
715
static inline unsigned get_bpsr(void) {
716
    unsigned retval;
717
    asm volatile ( "movsg   bpsr,%0\n" : "=r" (retval) : /* no inputs */  );
718
    return retval;}
719
static inline void set_bpsr(unsigned val) {
720
    asm volatile ( "movgs   %0,bpsr\n" : /* no outputs */  : "r" (val) );}
721
 
722
static inline unsigned get_dcr(void) {
723
    unsigned retval;
724
    asm volatile ( "movsg   dcr,%0\n" : "=r" (retval) : /* no inputs */  );
725
    return retval;}
726
static inline void set_dcr(unsigned val) {
727
    asm volatile ( "movgs   %0,dcr\n" : /* no outputs */  : "r" (val) );}
728
 
729
static inline unsigned get_brr(void) {
730
    unsigned retval;
731
    asm volatile ( "movsg   brr,%0\n" : "=r" (retval) : /* no inputs */  );
732
    return retval;}
733
static inline void set_brr(unsigned val) {
734
    asm volatile ( "movgs   %0,brr\n" : /* no outputs */  : "r" (val) );}
735
 
736
// Four Instruction Break Address Registers
737
static inline unsigned get_ibar0(void) {
738
    unsigned retval;
739
    asm volatile ( "movsg   ibar0,%0\n" : "=r" (retval) : /* no inputs */  );
740
    return retval;}
741
static inline void set_ibar0(unsigned val) {
742
    asm volatile ( "movgs   %0,ibar0\n" : /* no outputs */  : "r" (val) );}
743
 
744
static inline unsigned get_ibar1(void) {
745
    unsigned retval;
746
    asm volatile ( "movsg   ibar1,%0\n" : "=r" (retval) : /* no inputs */  );
747
    return retval;}
748
static inline void set_ibar1(unsigned val){
749
    asm volatile ( "movgs   %0,ibar1\n" : /* no outputs */  : "r" (val) );}
750
 
751
static inline unsigned get_ibar2(void) {
752
    unsigned retval;
753
    asm volatile ( "movsg   ibar2,%0\n" : "=r" (retval) : /* no inputs */  );
754
    return retval;}
755
static inline void set_ibar2(unsigned val) {
756
    asm volatile ( "movgs   %0,ibar2\n" : /* no outputs */  : "r" (val) );}
757
 
758
static inline unsigned get_ibar3(void) {
759
    unsigned retval;
760
    asm volatile ( "movsg   ibar3,%0\n" : "=r" (retval) : /* no inputs */  );
761
    return retval;}
762
static inline void set_ibar3(unsigned val){
763
    asm volatile ( "movgs   %0,ibar3\n" : /* no outputs */  : "r" (val) );}
764
 
765
// Two Data Break Address Registers
766
static inline unsigned get_dbar0(void) {
767
    unsigned retval;
768
    asm volatile ( "movsg   dbar0,%0\n" : "=r" (retval) : /* no inputs */  );
769
    return retval;}
770
static inline void set_dbar0(unsigned val){
771
    asm volatile ( "movgs   %0,dbar0\n" : /* no outputs */  : "r" (val) );}
772
 
773
static inline unsigned get_dbar1(void){
774
    unsigned retval;
775
    asm volatile ( "movsg   dbar1,%0\n" : "=r" (retval) : /* no inputs */  );
776
    return retval;}
777
static inline void set_dbar1(unsigned val){
778
    asm volatile ( "movgs   %0,dbar1\n" : /* no outputs */  : "r" (val) );}
779
 
780
// Two times two Data Break Data Registers
781
static inline unsigned get_dbdr00(void){
782
    unsigned retval;
783
    asm volatile ( "movsg   dbdr00,%0\n" : "=r" (retval) : /* no inputs */  );
784
    return retval;}
785
static inline void set_dbdr00(unsigned val){
786
    asm volatile ( "movgs   %0,dbdr00\n" : /* no outputs */  : "r" (val) );}
787
 
788
static inline unsigned get_dbdr01(void){
789
    unsigned retval;
790
    asm volatile ( "movsg   dbdr01,%0\n" : "=r" (retval) : /* no inputs */  );
791
    return retval;}
792
static inline void set_dbdr01(unsigned val){
793
    asm volatile ( "movgs   %0,dbdr01\n" : /* no outputs */  : "r" (val) );}
794
 
795
static inline unsigned get_dbdr10(void){
796
    unsigned retval;
797
    asm volatile ( "movsg   dbdr10,%0\n" : "=r" (retval) : /* no inputs */  );
798
    return retval;}
799
static inline void set_dbdr10(unsigned val){
800
    asm volatile ( "movgs   %0,dbdr10\n" : /* no outputs */  : "r" (val) );}
801
 
802
static inline unsigned get_dbdr11(void){
803
    unsigned retval;
804
    asm volatile ( "movsg   dbdr11,%0\n" : "=r" (retval) : /* no inputs */  );
805
    return retval;}
806
static inline void set_dbdr11(unsigned val){
807
    asm volatile ( "movgs   %0,dbdr11\n" : /* no outputs */  : "r" (val) );}
808
 
809
// Two times two Data Break Mask Registers
810
static inline unsigned get_dbmr00(void){
811
    unsigned retval;
812
    asm volatile ( "movsg   dbmr00,%0\n" : "=r" (retval) : /* no inputs */  );
813
    return retval;}
814
static inline void set_dbmr00(unsigned val){
815
    asm volatile ( "movgs   %0,dbmr00\n" : /* no outputs */  : "r" (val) );}
816
 
817
static inline unsigned get_dbmr01(void){
818
    unsigned retval;
819
    asm volatile ( "movsg   dbmr01,%0\n" : "=r" (retval) : /* no inputs */  );
820
    return retval;}
821
static inline void set_dbmr01(unsigned val){
822
    asm volatile ( "movgs   %0,dbmr01\n" : /* no outputs */  : "r" (val) );}
823
 
824
static inline unsigned get_dbmr10(void){
825
    unsigned retval;
826
    asm volatile ( "movsg   dbmr10,%0\n" : "=r" (retval) : /* no inputs */  );
827
    return retval;}
828
static inline void set_dbmr10(unsigned val){
829
    asm volatile ( "movgs   %0,dbmr10\n" : /* no outputs */  : "r" (val) );}
830
 
831
static inline unsigned get_dbmr11(void){
832
    unsigned retval;
833
    asm volatile ( "movsg   dbmr11,%0\n" : "=r" (retval) : /* no inputs */  );
834
    return retval;}
835
static inline void set_dbmr11(unsigned val){
836
    asm volatile ( "movgs   %0,dbmr11\n" : /* no outputs */  : "r" (val) );}
837
 
838
// and here's the prototype.  Which compiles, believe it or not.
839
static inline unsigned get_XXXX(void){
840
    unsigned retval;
841
    asm volatile ( "movsg   XXXX,%0\n" : "=r" (retval) : /* no inputs */  );
842
    return retval;}
843
static inline void set_XXXX(unsigned val){
844
    asm volatile ( "movgs   %0,XXXX\n" : /* no outputs */  : "r" (val) );}
845
 
846
// ------------------------------------------------------------------------
847
// This is called in the same manner as exception_handler() in hal_misc.c
848
// Comments compare and contrast what we do here.
849
 
850
static unsigned int saved_brr = 0;
851
 
852
void
853
break_handler(HAL_SavedRegisters *regs)
854
{
855
    unsigned int i, old_bpsr;
856
 
857
    // See if it an actual "break" instruction.
858
    i = get_brr();
859
    saved_brr |= i; // do not lose previous state
860
    // Acknowledge the trap, clear the "factor" (== cause)
861
    set_brr( 0 );
862
 
863
    // Now leave debug mode so that it's safe to run the stub code.
864
 
865
    // Unfortunately, leaving debug mode isn't a self-contained
866
    // operation.  The only means of doing it is with a "rett #1"
867
    // instruction, which will also restore the previous values of
868
    // the ET and S status flags.  We can massage the BPSR
869
    // register so that the flags keep their current values, but
870
    // we need to save the old one first.
871
    i = old_bpsr = get_bpsr ();
872
    i |= _BPSR_BS; // Stay in supervisor mode
873
    i &= ~_BPSR_BET; // Keep traps disabled
874
    set_bpsr (i);
875
    HAL_FRV_EXIT_DEBUG_MODE();
876
 
877
    // Only perturb this variable if stopping, not
878
    // just for a break instruction.
879
    _hal_registers = regs;
880
 
881
    // Continue with the standard mechanism:
882
    __handle_exception();
883
 
884
    // Go back into debug mode.
885
    HAL_FRV_ENTER_DEBUG_MODE();
886
    // Restore the original BPSR register.
887
    set_bpsr (old_bpsr);
888
    return;
889
}
890
 
891
// ------------------------------------------------------------------------
892
 
893
// Now the routines to manipulate said hardware break and watchpoints.
894
 
895
int cyg_hal_plf_hw_breakpoint(int setflag, void *vaddr, int len)
896
{
897
    unsigned int addr = (unsigned)vaddr;
898
    unsigned int dcr;
899
    unsigned int retcode = 0;
900
 
901
    HAL_FRV_ENTER_DEBUG_MODE();
902
    dcr = get_dcr();
903
 
904
    // GDB manual suggests that idempotency is required, so first remove
905
    // any identical BP in residence.  Implements remove arm anyway.
906
    if ( 0 != (dcr & (_DCR_IBE0 | _DCR_IBCE0)) &&
907
         get_ibar0() == addr                       )
908
        dcr &=~(_DCR_IBE0 | _DCR_IBCE0);
909
    else if ( 0 != (dcr & (_DCR_IBE1 | _DCR_IBCE1)) &&
910
              get_ibar1() == addr                       )
911
        dcr &=~(_DCR_IBE1 | _DCR_IBCE1);
912
    else if ( 0 != (dcr & (_DCR_IBE2 | _DCR_IBCE2)) &&
913
              get_ibar2() == addr                       )
914
        dcr &=~(_DCR_IBE2 | _DCR_IBCE2);
915
    else if ( 0 != (dcr & (_DCR_IBE3 | _DCR_IBCE3)) &&
916
              get_ibar3() == addr                       )
917
        dcr &=~(_DCR_IBE3 | _DCR_IBCE3);
918
    else
919
        retcode = -1;
920
 
921
    if (setflag) {
922
        retcode = 0; // it is OK really
923
        if ( 0 == (dcr & (_DCR_IBE0 | _DCR_IBCE0)) ) {
924
            set_ibar0(addr);
925
            dcr |= _DCR_IBE0;
926
        }
927
        else if ( 0 == (dcr & (_DCR_IBE1 | _DCR_IBCE1)) ) {
928
            set_ibar1(addr);
929
            dcr |= _DCR_IBE1;
930
        }
931
        else if ( 0 == (dcr & (_DCR_IBE2 | _DCR_IBCE2)) ) {
932
            set_ibar2(addr);
933
            dcr |= _DCR_IBE2;
934
        }
935
        else if ( 0 == (dcr & (_DCR_IBE3 | _DCR_IBCE3)) ) {
936
            set_ibar3(addr);
937
            dcr |= _DCR_IBE3;
938
        }
939
        else
940
            retcode = -1;
941
    }
942
 
943
    if ( 0 == retcode )
944
        set_dcr(dcr);
945
    HAL_FRV_EXIT_DEBUG_MODE();
946
    return retcode;
947
}
948
 
949
int cyg_hal_plf_hw_watchpoint(int setflag, void *vaddr, int len, int type)
950
{
951
    unsigned int addr = (unsigned)vaddr;
952
    unsigned int mode;
953
    unsigned int dcr;
954
    unsigned int retcode = 0;
955
    unsigned long long mask;
956
    unsigned int mask0, mask1;
957
    int i;
958
 
959
    // Check the length fits within one block.
960
    if ( ((~7) & (addr + len - 1)) != ((~7) & addr) )
961
        return -1;
962
 
963
    // Assuming big-endian like the platform seems to be...
964
 
965
    // Get masks for the 8-byte span.  00 means enabled, ff means ignore a
966
    // byte, which is why this looks funny at first glance.
967
    mask = 0x00ffffffffffffffULL >> ((len - 1) << 3);
968
    for (i = 0; i < (addr & 7); i++) {
969
        mask >>= 8;
970
        mask |= 0xff00000000000000ULL;
971
    }
972
 
973
    mask0 = mask >> 32;
974
    mask1 = mask & 0xffffffffULL;
975
 
976
    addr &=~7; // round to 8-byte block
977
 
978
    HAL_FRV_ENTER_DEBUG_MODE();
979
    dcr = get_dcr();
980
 
981
    // GDB manual suggests that idempotency is required, so first remove
982
    // any identical WP in residence.  Implements remove arm anyway.
983
    if (      0 != (dcr & (7 * _DCR_DBASE0)) &&
984
              get_dbar0() == addr            &&
985
              get_dbmr00() == mask0 && get_dbmr01() == mask1 )
986
        dcr &=~(7 * _DCR_DBASE0);
987
    else if ( 0 != (dcr & (7 * _DCR_DBASE1)) &&
988
              get_dbar1() == addr&&
989
              get_dbmr10() == mask0 && get_dbmr11() == mask1 )
990
        dcr &=~(7 * _DCR_DBASE1);
991
    else
992
        retcode = -1;
993
 
994
    if (setflag) {
995
        retcode = 0; // it is OK really
996
        if      (type == 2)       mode = 2; // break on write
997
        else if (type == 3)       mode = 4; // break on read
998
        else if (type == 4)       mode = 6; // break on any access
999
        else {
1000
            mode = 0; // actually add no enable at all.
1001
            retcode = -1;
1002
        }
1003
        if ( 0 == (dcr & (7 * _DCR_DBASE0)) ) {
1004
            set_dbar0(addr);
1005
            // Data and Mask 0,1 to zero (mask no bits/bytes)
1006
            set_dbdr00(0); set_dbdr01(0); set_dbmr00(mask0); set_dbmr01(mask1);
1007
            mode *= _DCR_DBASE0;
1008
            dcr |= mode;
1009
        }
1010
        else if ( 0 == (dcr & (7 * _DCR_DBASE1)) ) {
1011
            set_dbar1(addr);
1012
            set_dbdr10(0); set_dbdr11(0); set_dbmr10(mask0); set_dbmr11(mask1);
1013
            mode *= _DCR_DBASE1;
1014
            dcr |= mode;
1015
        }
1016
        else
1017
            retcode = -1;
1018
    }
1019
 
1020
    if ( 0 == retcode )
1021
        set_dcr(dcr);
1022
    HAL_FRV_EXIT_DEBUG_MODE();
1023
    return retcode;
1024
}
1025
 
1026
// Return indication of whether or not we stopped because of a
1027
// watchpoint or hardware breakpoint. If stopped by a watchpoint,
1028
// also set '*data_addr_p' to the data address which triggered the
1029
// watchpoint.
1030
int cyg_hal_plf_is_stopped_by_hardware(void **data_addr_p)
1031
{
1032
    unsigned int brr;
1033
    int retcode = HAL_STUB_HW_STOP_NONE;
1034
    unsigned long long mask;
1035
 
1036
    // There was a debug event. Check the BRR for details
1037
    brr = saved_brr;
1038
    saved_brr = 0;
1039
 
1040
    if ( brr & (_BRR_IB0 | _BRR_IB1 | _BRR_IB2 | _BRR_IB3) ) {
1041
        // then it was an instruction break
1042
        retcode = HAL_STUB_HW_STOP_BREAK;
1043
    }
1044
    else if ( brr & (_BRR_DB0 | _BRR_DB1) ) {
1045
        unsigned int addr, kind;
1046
        kind = get_dcr();
1047
        if ( brr & (_BRR_DB0) ) {
1048
            addr = get_dbar0();
1049
            kind &= 7 * _DCR_DBASE0;
1050
            kind /= _DCR_DBASE0;
1051
            mask = (((unsigned long long)get_dbmr00())<<32) | (unsigned long long)get_dbmr01();
1052
        } else {
1053
            addr = get_dbar1();
1054
            kind &= 7 * _DCR_DBASE1;
1055
            kind /= _DCR_DBASE1;
1056
            mask = (((unsigned long long)get_dbmr10())<<32) | (unsigned long long)get_dbmr11();
1057
        }
1058
 
1059
        if ( data_addr_p ) {
1060
            // Scan for a zero byte in the mask - this gives the true address.
1061
            //              0123456789abcdef
1062
            while ( 0 != (0xff00000000000000LLU & mask) ) {
1063
                mask <<= 8;
1064
                addr++;
1065
            }
1066
            *data_addr_p = (void *)addr;
1067
        }
1068
 
1069
        // Inverse of the mapping above in the "set" code.
1070
        if      (kind == 2)       retcode = HAL_STUB_HW_STOP_WATCH;
1071
        else if (kind == 6)       retcode = HAL_STUB_HW_STOP_AWATCH;
1072
        else if (kind == 4)       retcode = HAL_STUB_HW_STOP_RWATCH;
1073
    }
1074
    return retcode;
1075
}
1076
 
1077
// ------------------------------------------------------------------------
1078
 
1079
#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
1080
 
1081
/*------------------------------------------------------------------------*/
1082
// EOF frv400_misc.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.