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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [syn/] [components/] [sd_card/] [firmware/] [bsp/] [drivers/] [src/] [altera_avalon_jtag_uart_init.c] - Blame information for rev 8

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 alfik
/******************************************************************************
2
*                                                                             *
3
* License Agreement                                                           *
4
*                                                                             *
5
* Copyright (c) 2007 Altera Corporation, San Jose, California, USA.           *
6
* All rights reserved.                                                        *
7
*                                                                             *
8
* Permission is hereby granted, free of charge, to any person obtaining a     *
9
* copy of this software and associated documentation files (the "Software"),  *
10
* to deal in the Software without restriction, including without limitation   *
11
* the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
12
* and/or sell copies of the Software, and to permit persons to whom the       *
13
* Software is furnished to do so, subject to the following conditions:        *
14
*                                                                             *
15
* The above copyright notice and this permission notice shall be included in  *
16
* all copies or substantial portions of the Software.                         *
17
*                                                                             *
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
19
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
20
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
21
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
22
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
23
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
24
* DEALINGS IN THE SOFTWARE.                                                   *
25
*                                                                             *
26
* This agreement shall be governed in all respects by the laws of the State   *
27
* of California and by the laws of the United States of America.              *
28
*                                                                             *
29
******************************************************************************/
30
 
31
#include <string.h>
32
#include <fcntl.h>
33
#include <errno.h>
34
#include <limits.h>
35
 
36
#include <sys/stat.h>
37
 
38
#include "sys/alt_irq.h"
39
#include "sys/alt_alarm.h"
40
#include "sys/ioctl.h"
41
#include "alt_types.h"
42
 
43
#include "altera_avalon_jtag_uart_regs.h"
44
#include "altera_avalon_jtag_uart.h"
45
 
46
#include "sys/alt_log_printf.h"
47
 
48
#ifndef ALTERA_AVALON_JTAG_UART_SMALL
49
 
50
/* ----------------------------------------------------------- */
51
/* ------------------------- FAST DRIVER --------------------- */
52
/* ----------------------------------------------------------- */
53
#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
54
static void altera_avalon_jtag_uart_irq(void* context);
55
#else
56
static void altera_avalon_jtag_uart_irq(void* context, alt_u32 id);
57
#endif 
58
static alt_u32 altera_avalon_jtag_uart_timeout(void* context);
59
 
60
/*
61
 * Driver initialization code.  Register interrupts and start a timer
62
 * which we can use to check whether the host is there.
63
 * Return 1 on sucessful IRQ register and 0 on failure.
64
 */
65
 
66
void altera_avalon_jtag_uart_init(altera_avalon_jtag_uart_state* sp,
67
                                  int irq_controller_id, int irq)
68
{
69
  ALT_FLAG_CREATE(&sp->events, 0);
70
  ALT_SEM_CREATE(&sp->read_lock, 1);
71
  ALT_SEM_CREATE(&sp->write_lock, 1);
72
 
73
  /* enable read interrupts at the device */
74
  sp->irq_enable = ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK;
75
 
76
  IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable);
77
 
78
  /* register the interrupt handler */
79
#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
80
  alt_ic_isr_register(irq_controller_id, irq, altera_avalon_jtag_uart_irq,
81
                      sp, NULL);
82
#else
83
  alt_irq_register(irq, sp, altera_avalon_jtag_uart_irq);
84
#endif  
85
 
86
  /* Register an alarm to go off every second to check for presence of host */
87
  sp->host_inactive = 0;
88
 
89
  if (alt_alarm_start(&sp->alarm, alt_ticks_per_second(),
90
    &altera_avalon_jtag_uart_timeout, sp) < 0)
91
  {
92
    /* If we can't set the alarm then record "don't know if host present"
93
     * and behave as though the host is present.
94
     */
95
    sp->timeout = INT_MAX;
96
  }
97
 
98
  /* ALT_LOG - see altera_hal/HAL/inc/sys/alt_log_printf.h */
99
  ALT_LOG_JTAG_UART_ALARM_REGISTER(sp, sp->base);
100
}
101
 
102
/*
103
 * Interrupt routine
104
 */
105
#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
106
static void altera_avalon_jtag_uart_irq(void* context)
107
#else
108
static void altera_avalon_jtag_uart_irq(void* context, alt_u32 id)
109
#endif
110
{
111
  altera_avalon_jtag_uart_state* sp = (altera_avalon_jtag_uart_state*) context;
112
  unsigned int base = sp->base;
113
 
114
  /* ALT_LOG - see altera_hal/HAL/inc/sys/alt_log_printf.h */
115
  ALT_LOG_JTAG_UART_ISR_FUNCTION(base, sp);
116
 
117
  for ( ; ; )
118
  {
119
    unsigned int control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base);
120
 
121
    /* Return once nothing more to do */
122
    if ((control & (ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK | ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK)) == 0)
123
      break;
124
 
125
    if (control & ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK)
126
    {
127
      /* process a read irq.  Start by assuming that there is data in the
128
       * receive FIFO (otherwise why would we have been interrupted?)
129
       */
130
      unsigned int data = 1 << ALTERA_AVALON_JTAG_UART_DATA_RAVAIL_OFST;
131
 
132
      for ( ; ; )
133
      {
134
        /* Check whether there is space in the buffer.  If not then we must not
135
         * read any characters from the buffer as they will be lost.
136
         */
137
        unsigned int next = (sp->rx_in + 1) % ALTERA_AVALON_JTAG_UART_BUF_LEN;
138
        if (next == sp->rx_out)
139
          break;
140
 
141
        /* Try to remove a character from the FIFO and find out whether there
142
         * are any more characters remaining.
143
         */
144
        data = IORD_ALTERA_AVALON_JTAG_UART_DATA(base);
145
 
146
        if ((data & ALTERA_AVALON_JTAG_UART_DATA_RVALID_MSK) == 0)
147
          break;
148
 
149
        sp->rx_buf[sp->rx_in] = (data & ALTERA_AVALON_JTAG_UART_DATA_DATA_MSK) >> ALTERA_AVALON_JTAG_UART_DATA_DATA_OFST;
150
        sp->rx_in = (sp->rx_in + 1) % ALTERA_AVALON_JTAG_UART_BUF_LEN;
151
 
152
        /* Post an event to notify jtag_uart_read that a character has been read */
153
        ALT_FLAG_POST (sp->events, ALT_JTAG_UART_READ_RDY, OS_FLAG_SET);
154
      }
155
 
156
      if (data & ALTERA_AVALON_JTAG_UART_DATA_RAVAIL_MSK)
157
      {
158
        /* If there is still data available here then the buffer is full
159
         * so turn off receive interrupts until some space becomes available.
160
         */
161
        sp->irq_enable &= ~ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK;
162
        IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(base, sp->irq_enable);
163
 
164
        /* Dummy read to ensure IRQ is cleared prior to ISR completion */
165
        IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base);
166
      }
167
    }
168
 
169
    if (control & ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK)
170
    {
171
      /* process a write irq */
172
      unsigned int space = (control & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK) >> ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST;
173
 
174
      while (space > 0 && sp->tx_out != sp->tx_in)
175
      {
176
        IOWR_ALTERA_AVALON_JTAG_UART_DATA(base, sp->tx_buf[sp->tx_out]);
177
 
178
        sp->tx_out = (sp->tx_out + 1) % ALTERA_AVALON_JTAG_UART_BUF_LEN;
179
 
180
        /* Post an event to notify jtag_uart_write that a character has been written */
181
        ALT_FLAG_POST (sp->events, ALT_JTAG_UART_WRITE_RDY, OS_FLAG_SET);
182
 
183
        space--;
184
      }
185
 
186
      if (space > 0)
187
      {
188
        /* If we don't have any more data available then turn off the TX interrupt */
189
        sp->irq_enable &= ~ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK;
190
        IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable);
191
 
192
        /* Dummy read to ensure IRQ is cleared prior to ISR completion */
193
        IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base);
194
      }
195
    }
196
  }
197
}
198
 
199
/*
200
 * Timeout routine is called every second
201
 */
202
 
203
static alt_u32
204
altera_avalon_jtag_uart_timeout(void* context)
205
{
206
  altera_avalon_jtag_uart_state* sp = (altera_avalon_jtag_uart_state *) context;
207
 
208
  unsigned int control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base);
209
 
210
  if (control & ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK)
211
  {
212
    IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable | ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK);
213
    sp->host_inactive = 0;
214
  }
215
  else if (sp->host_inactive < INT_MAX - 2) {
216
    sp->host_inactive++;
217
 
218
    if (sp->host_inactive >= sp->timeout) {
219
      /* Post an event to indicate host is inactive (for jtag_uart_read */
220
      ALT_FLAG_POST (sp->events, ALT_JTAG_UART_TIMEOUT, OS_FLAG_SET);
221
    }
222
  }
223
 
224
  return alt_ticks_per_second();
225
}
226
 
227
/*
228
 * The close() routine is implemented to drain the JTAG UART transmit buffer
229
 * when not in "small" mode. This routine will wait for transimt data to be
230
 * emptied unless a timeout from host-activity occurs. If the driver flags
231
 * have been set to non-blocking mode, this routine will exit immediately if
232
 * any data remains. This routine should be called indirectly (i.e. though
233
 * the C library close() routine) so that the file descriptor associated
234
 * with the relevant stream (i.e. stdout) can be closed as well. This routine
235
 * does not manage file descriptors.
236
 *
237
 * The close routine is not implemented for the small driver; instead it will
238
 * map to null. This is because the small driver simply waits while characters
239
 * are transmitted; there is no interrupt-serviced buffer to empty
240
 */
241
int altera_avalon_jtag_uart_close(altera_avalon_jtag_uart_state* sp, int flags)
242
{
243
  /*
244
   * Wait for all transmit data to be emptied by the JTAG UART ISR, or
245
   * for a host-inactivity timeout, in which case transmit data will be lost
246
   */
247
  while ( (sp->tx_out != sp->tx_in) && (sp->host_inactive < sp->timeout) ) {
248
    if (flags & O_NONBLOCK) {
249
      return -EWOULDBLOCK;
250
    }
251
  }
252
 
253
  return 0;
254
}
255
 
256
#endif /* !ALTERA_AVALON_JTAG_UART_SMALL */

powered by: WebSVN 2.1.0

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