Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / kernel / rca / l0rca.c
1 /* -*- mode: c; c-basic-offset: 8; -*-
2  */
3 /*
4  *   RCA: Interface between CRAY RCA and linux kernel
5  *
6  * Copyright (c) 2003 Cray Inc.
7  *
8  *      This program is free software; you can redistribute it and/or
9  *      modify it under the terms of the GNU General Public License
10  *      as published by the Free Software Foundation; either version
11  *      2 of the License, or (at your option) any later version.
12  *
13  *
14  */
15 /*
16  * This code is licensed under the GNU General Public License,
17  * Version 2.  See the file COPYING for more details.
18  */
19
20
21 #include <lwk/kernel.h>
22 #include <lwk/string.h>
23 #include <lwk/errno.h>
24 #include <lwk/delay.h>
25 #include <lwk/version.h>
26 #include <rca/rca_l0_linux.h>
27 #include <rca/rca_l0.h>
28 extern void     set_debug_traps(void) ;         /* GDB routine */
29
30 #if defined(CONFIG_CRAY_RS_DEBUG)
31 #define assert(expr) \
32 if(!(expr)) {                                   \
33         printk( "Assertion failed! %s,%s,%s,line=%d\n", \
34                #expr,__FILE__,__FUNCTION__,__LINE__);          \
35 }
36 #else
37 #define assert(expr)
38 #endif /* CONFIG_CRAY_RS_DEBUG */
39
40 /* States for up channel. Used for calling the tx_done callback only if reqd */
41 #define CHAN_TX_STATE_AVAIL     (0)
42 #define CHAN_TX_STATE_FULL      (1)
43 #define GET_CHAN_STATE(x)       ((x)->state)
44 #define SET_CHAN_STATE(x, s)    ((x)->state = (s))
45
46 typedef struct l0rca_mapped_ch {
47         uint32_t num_obj;        /* number of objects    */
48         uint32_t intr_bit;
49         volatile uint32_t *ch_ridx;             /* Pointer to ridx */
50         volatile uint32_t *ch_widx;             /* Pointer to widx */
51         rs_event_t              *ch_buf_ptr;    /* Pointer to channel buffer */
52         l0rca_down_handle_t     down_handler;
53         l0rca_up_handle_t       up_handler;
54         uint32_t                reg_count;
55         int                     poll;           /* timeout */
56         int                     tshhld;         /* timeout */
57         int                     state;          /* outgoing chan full or not */
58 } l0rca_mapped_ch_t;
59
60 #define L0RCA_INITVAL   (0xAA55F00D)
61
62 typedef struct l0rca_mapped_config {
63         uint32_t        version;        /* config version */
64         rs_node_t       proc_id;        /* node id */
65         int32_t         proc_num;       /* cpu number (0-3) */
66         l0rca_mapped_ch_t       ch_data[NUM_L0RCA_CHANNELS];
67         volatile uint32_t       *l0rca_l0_intr_ptr;     /* interrupt to L0 */
68         uint32_t        initialized;
69 } l0rca_mapped_config_t;
70
71 /* Our copy with virt addrs; so we can directly access the config area */
72 l0rca_mapped_config_t l0rca_early_cfg = {0};
73
74 /* Pointer to the actual config struct in Seastar RAM shared memory */
75 l0rca_config_t *l0rca_cfg = NULL;
76
77 /* Store the size of the event header without the msg body */
78 uint32_t rs_ev_hdr_sz;
79
80
81 void send_intr_to_l0(l0rca_mapped_ch_t *ch)
82 {
83         volatile uint32_t *addr = &(((l0rca_intr_t *)(l0rca_early_cfg.l0rca_l0_intr_ptr))->l0r_intr_set);
84         SSPUT32(addr, (ch)->intr_bit);
85 }
86
87 /* 
88  * Function:    l0rca_event_data
89  * 
90  * Description: Return a pointer to the data portion and length of the
91  *              data portion of the event.
92  *              NB: Reflect any changes to l0rca_event_data in gdb_l0rca_event_data
93  * 
94  * Arguments: rs_event_t *evp IN: Event whose data is of interest
95  *            void **data OUT: Upon return will point to data portion of event
96  *            int32_t *len OUT: Upon return will have the length of the data
97  *                              portion of the event
98  *
99  * Returns: No Return Value.
100  * Note: The main purpose of this routine is to read in the data portion of the
101  * event from Seastar memory. 
102  */
103 void l0rca_event_data(rs_event_t *evp, void **data, int32_t *len)
104 {
105         /* Get length and data portion from the event */
106         *len = evp->ev_len;
107         *data = &evp->ev_data;
108 } /* l0rca_event_data */
109
110 /* 
111  * Function:    l0rca_get_proc_id
112  * 
113  * Description: Return the node/processor id.
114  * 
115  * Arguments: None
116  *
117  * Returns: The proc id.
118  */
119 rs_node_t l0rca_get_proc_id(void)
120 {
121         return l0rca_cfg->proc_id;
122 }
123
124 /* 
125  * Function:    l0rca_get_proc_num
126  * 
127  * Description: Returns this processor's CPU number, 0-3.
128  * 
129  * Arguments: None.
130  * 
131  * Returns: The CPU number of this node.
132  */
133 int l0rca_get_proc_num(void)
134 {
135     int tmp;
136     SSGET32(&(l0rca_cfg->proc_num),tmp);
137     return(tmp);
138 }
139
140 /*
141  * Function:    set_chan_tx_state
142  *
143  * Description: Looks at the read and write indices to determine if the
144  *              channel is full or not. Sets state accordingly.
145  *              NB: Reflect any changes to set_chan_tx_state in gdb_set_chan_tx_state.
146  *
147  * Arguments: l0rca_mapped_ch_t *ch_ptr IN: Pointer to channel being set.
148  *
149  * Returns: None
150  */
151 static inline void set_chan_tx_state(l0rca_mapped_ch_t *ch_ptr)
152 {
153         volatile uint32_t wx, rx;
154         int not_full;
155         SSGET32(ch_ptr->ch_widx, wx);
156         SSGET32(ch_ptr->ch_ridx, rx);
157         not_full = (wx - rx) < ch_ptr->num_obj;
158         SET_CHAN_STATE(ch_ptr, not_full  ? CHAN_TX_STATE_AVAIL : CHAN_TX_STATE_FULL);
159 }
160
161
162 /*
163  * Function:    l0rca_init_config
164  *
165  * Description: Read L0 - RCA communication config structure and populate 
166  *              our personal copy. If there is any error, the OS panics
167  *              since not being able to communicate with L0 is a total disaster.
168  *              If already initialized then returns silently.
169  *
170  * Arguments: None.
171  *
172  * Returns: None
173  */
174
175 void l0rca_init_config(void)
176 {
177         rs_event_t *ev_buf;
178         int i;
179         volatile uint64_t tmp64;
180         volatile uint32_t tmp32;
181
182         /* 
183          * Check if already initialized; No locking is needed as this 
184          * is called during the boot process from within the kernel (as 
185          * opposed from a driver)
186          */
187         if (L0RCA_INITVAL == l0rca_early_cfg.initialized)
188                 return;
189
190         l0rca_cfg = (l0rca_config_t *)rca_l0_comm_va(L0_SIC_RAM);
191
192         /* TODO - first order of business is to check the Version Number */
193         /* Also, should we panic if version mismatch? */
194 #ifdef CONFIG_CRAY_RS_DEBUG
195         printk ("l0 config at virtual %p\n", l0rca_cfg);
196         printk ("Phys event bufs 0x%llx intr reg 0x%llx\n",
197                 l0rca_cfg->l0rca_buf_addr,
198                 l0rca_cfg->l0rca_l0_intr_addr);
199 #endif /* CONFIG_CRAY_RS_DEBUG */
200
201         /* convert event buffer address from physical to virtual */
202         SSGET64(&(l0rca_cfg->l0rca_buf_addr),tmp64);
203         ev_buf = (rs_event_t *)rca_l0_comm_va(tmp64);
204
205         /* convert intr reg address from physical to virtual */
206         SSGET64(&(l0rca_cfg->l0rca_l0_intr_addr), tmp64);
207         l0rca_early_cfg.l0rca_l0_intr_ptr = (uint32_t *)rca_l0_comm_va(tmp64);
208
209 #ifdef CONFIG_CRAY_RS_DEBUG
210         printk ("event bufs %p intr reg %p\n", ev_buf,
211                 l0rca_early_cfg.l0rca_l0_intr_ptr);
212 #endif /* CONFIG_CRAY_RS_DEBUG */
213
214         /* Now setup the channel buffers */
215         for (i = 0; i < NUM_L0RCA_CHANNELS; i++)
216         {
217                 int num_obj; 
218                 SSGET32(&(l0rca_cfg->chnl_data[i].num_obj), tmp32);
219                 num_obj = tmp32;
220
221                 /* Skip if channel is unused */
222                 if (!num_obj)
223                         continue;
224
225                 /* Ensure num_obj is a power of 2 */
226                 if (num_obj & (num_obj - 1))
227                 {
228 #if 0
229                         panic ("l0rca_init_config: num_obj[%u] for channel %d is not power of 2\n",
230                                num_obj, i);
231 #endif
232                 }
233                 l0rca_early_cfg.ch_data[i].num_obj = num_obj;
234                 SSGET32(&(l0rca_cfg->chnl_data[i].l0_intr_bit), tmp32);
235                 l0rca_early_cfg.ch_data[i].intr_bit = tmp32;
236
237                 /* Point to the read/writew index */
238                 l0rca_early_cfg.ch_data[i].ch_ridx = &l0rca_cfg->chnl_data[i].ridx;
239                 l0rca_early_cfg.ch_data[i].ch_widx = &l0rca_cfg->chnl_data[i].widx;
240                 l0rca_early_cfg.ch_data[i].ch_buf_ptr = ev_buf;
241
242                 ev_buf += num_obj;
243
244 #ifdef CONFIG_CRAY_RS_DEBUG
245                 printk ("Buffer %p for channel %d rd %u wr %u\n", 
246                         l0rca_early_cfg.ch_data[i].ch_buf_ptr, i,
247                         l0rca_cfg->chnl_data[i].ridx,
248                         l0rca_cfg->chnl_data[i].widx);
249 #endif /* CONFIG_CRAY_RS_DEBUG */
250         }       /* End of for */
251
252         /* Set the remaining fields */
253         SSGET32(&(l0rca_cfg->version), l0rca_early_cfg.version);
254         SSGET32(&(l0rca_cfg->proc_id), l0rca_early_cfg.proc_id);
255         SSGET32(&(l0rca_cfg->proc_num), l0rca_early_cfg.proc_num);
256
257         /* Assumes ev_data is the last element TODO: this should be
258          * defined via a macro in the rs_event_t structure definition */
259         rs_ev_hdr_sz = offsetof(rs_event_t, ev_data);
260
261         /* Indicate we have a initialized the mapped copy */
262         l0rca_early_cfg.initialized = L0RCA_INITVAL;
263
264         return;
265 }
266
267 /* 
268  * Function:    register_ch_up
269  * 
270  * Description: Register function for the upload channel. It is expected that
271  * there be at most one registered user for an upload channel. This user 
272  * provides a callback to be invoked when the buffer drains below tshhld
273  * (only if the buffer became full last time the tshhld was crossed)
274  * 
275  * Arguments: int ch_num IN: channel number to register on
276  *            l0rca_up_handle_t handler IN: callback routine
277  *            int tshhld IN: buffer to drain before invoking callback; ignored
278  *                           if poll is negative.
279  *            int poll IN: if > zero - duration in ms to check for buffer drain
280  *                         if = zero - tx done interrupt invokes callback (TODO)
281  *                         if < zero - do nothing. It is assumed that the user (TODO)
282  *                         has her own means to check for buffer drain
283  *
284  * Returns: -EBUSY - If another user is already registered.
285  *          -EINVAL - if ch_num is not in range.
286  *          zero (SUCCESS) otherwise.
287  *
288  * Note: It is expected that the buffer is empty upon call to this routine. 
289  *       This should be true on system startup and after an unregister call.
290  *
291  * Note: As of 12/1/04, the polling is forced, and is hard coded in 
292  *   l0rca_linux.c.  Thus, the tshhld and poll params have no meaning.
293  */
294 int
295 register_ch_up(int ch_num, l0rca_up_handle_t handler, int tshhld, int poll)
296 {
297         volatile uint32_t wx, rx;
298         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
299
300         if (NUM_L0RCA_CHANNELS <= ch_num)
301                 return -EINVAL;
302
303         /* Allow only one user per channel */
304         if (ch_ptr->reg_count)
305                 return -EBUSY;
306
307         SSGET32(ch_ptr->ch_widx, wx);
308         SSGET32(ch_ptr->ch_ridx, rx);
309         assert(wx == rx);
310
311         SET_CHAN_STATE(ch_ptr, CHAN_TX_STATE_AVAIL);
312         ch_ptr->down_handler = NULL;    /* Clear the down handler */
313         ch_ptr->reg_count++;
314         ch_ptr->poll = poll;
315         ch_ptr->up_handler = handler;
316         ch_ptr->tshhld = tshhld;
317
318         return 0;
319 }
320
321 /* 
322  * Function:    register_ch_down
323  * 
324  * Description: Register function for the download channel. It is expected that
325  * there be at most one registered user for a download channel. This user 
326  * provides a callback to be invoked when data from L0 arrives on the channel.
327  * 
328  * Arguments: int ch_num IN: channel number to register on
329  *            l0rca_down_handle_t handler IN: callback routine
330  *            int poll IN: if > zero - duration in ms to check for event
331  *                         if = zero - event arrival is interrupt driven.
332  *                         if < zero - do nothing. It is assumed that the user
333  *                         has her own means to check for event arrival.
334  *
335  * Returns: EBUSY - If another user is already registered.
336  *          zero (SUCCESS) otherwise.
337  * 
338  * Note: As of 12/1/04, the polling is forced, and is hard coded in 
339  *   l0rca_linux.c.  Thus, the poll parameter has no meaning.
340  */
341 int register_ch_down(int ch_num, l0rca_down_handle_t handler, int poll)
342 {
343         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
344
345         if (NUM_L0RCA_CHANNELS <= ch_num)
346                 return -EINVAL;
347
348         /* Allow only one user per channel */
349         if (ch_ptr->reg_count)
350                 return -EBUSY;
351
352         ch_ptr->reg_count++;
353         ch_ptr->down_handler = handler;
354         ch_ptr->poll = poll;
355
356 #if 0
357         /* Do any OS specific initialization e.g. set irq, timers etc. */
358         if (l0rca_os_init())
359         {
360                 panic ("Unable to initialize OS service for L0RCA interface\n");
361         }
362 #endif
363
364         return 0;
365 }
366
367 #ifdef CONFIG_CRAY_RS_DEBUG
368 uint32_t l0rca_buf_full;
369 #endif /* CONFIG_CRAY_RS_DEBUG */
370 /* 
371  * Function:    ch_send_data
372  * 
373  * Description: Sends data towards the L0. 
374  * The data that buf points to is sent as the payload in an rs_event structure.
375  * The header is a separate parameter and the send routine directly copies
376  * the header and the data into the circular buffer, thus avoiding a copy.
377  *
378  * NB: Reflect any changes to ch_send_data in gdb_ch_send_data
379  * 
380  * Arguments: int ch_num IN: channel number on which to send data
381  *            rs_event_t *ev_hdr  IN: Header without len & timestamp
382  *            void* buf  IN: Buffer with data
383  *            int len    IN: length of data to transfer
384  *
385  * Returns: -EINVAL - if no user registered on the channel (Debug only)
386  *          -EFAULT - if buf or ev_hdr is NULL (Debug only)
387  *          -E2BIG -  if len exceeds max event payload (RS_MSG_LEN) (Debug only)
388  *          zero -    SUCCESS, all bytes sent.
389  *          > 0 -     Bytes not sent. Sender should retry.
390  *
391  * Notes: data in buf will be copied to the channel buffer, therfore, upon
392  *        return, user can free the buf. buf may not be NULL and the len must
393  *        not be zero. Use ch_send_event to send events with zero length data
394  *        portion.
395  */
396
397 int ch_send_data(int ch_num, const rs_event_t *ev_hdr, 
398                  void* buf, unsigned int len)
399 {
400         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
401         uint32_t ev_len = 0;
402         volatile uint32_t tmpwx, tmprx;
403
404 #ifdef CONFIG_CRAY_RS_DEBUG
405         uint32_t wr, rd, no_events;
406         if ((NULL == ev_hdr) || (NULL == buf))
407         {
408                 return -EFAULT;
409         }
410
411         if ((NUM_L0RCA_CHANNELS <= ch_num) || (0 == len) ||
412             (L0RCA_INITVAL != l0rca_early_cfg.initialized) ||
413             (0 == ch_ptr->reg_count))
414         {
415                 return -EINVAL;
416         }
417
418         /* Normalize the write & read indexes */
419         SSGET32(ch_ptr->ch_widx, tmpwx);
420         wr = tmpwx & (ch_ptr->num_obj - 1);
421         SSGET32(ch_ptr->ch_ridx, tmprx);
422         rd = tmprx & (ch_ptr->num_obj - 1);
423
424
425         /* Calculate the number of events we will be sending */
426         no_events = (len + RS_MSG_LEN -1)/RS_MSG_LEN;
427         if ((wr + (no_events) - rd) < ch_ptr->num_obj)
428         {
429             l0rca_buf_full++;
430         }
431
432 #endif /* CONFIG_CRAY_RS_DEBUG */
433
434         /* Optimize for buf not full and only one event needed to send */
435
436         /* 
437          * Masking of indexes is not needed for the check in while() below.
438          * Both widx & ridx are unsigned and increase monotonically such that
439          * ridx cannot lag behind widx by more than the circular buf size i.e.
440          * num_obj. widx will overflow before ridx.
441          * 'widx - ridx' will always yield the difference between the two 
442          * even if widx has overflowed and ridx has not yet overflowed.
443          */
444         SSGET32(ch_ptr->ch_widx, tmpwx);
445         SSGET32(ch_ptr->ch_ridx, tmprx);
446         while ((tmpwx - tmprx) < ch_ptr->num_obj)
447         {
448                 rs_event_t *wr_ev_ptr = 
449                   &ch_ptr->ch_buf_ptr[tmpwx & (ch_ptr->num_obj - 1)];
450
451                 /* Copy same header for each event */
452                 SSMEMPUT(wr_ev_ptr, (uint32_t*) ev_hdr, rs_ev_hdr_sz);
453
454                 /* Copy the data portion over */
455                 ev_len = (RS_MSG_LEN > len) ? len : RS_MSG_LEN;
456                 SSPUT32(&(wr_ev_ptr->ev_len), ev_len);
457                 SSMEMPUT((char*)wr_ev_ptr + rs_ev_hdr_sz, buf, RS_MSG_LEN);
458
459                 /* TODO: Set the timestamp in each event */
460 #if 0
461                 SSPUT32(wr_ev_ptr->_ev_stp, 0x0);
462 #endif  /* 0 */
463                 len -= ev_len;
464                 /* 
465                  * After updating the widx, DO NOT access any field in that 
466                  * event. Though not desirable, the reader is free to alter 
467                  * fields in the event.
468                  */
469                 SSGET32(ch_ptr->ch_widx, tmpwx);
470                 SSPUT32(ch_ptr->ch_widx, tmpwx + 1);
471                 set_chan_tx_state(ch_ptr);
472
473                 /* Let L0 know an ev is available */
474                 send_intr_to_l0(ch_ptr);
475
476                 if (0 == len)
477                         break;
478
479                 buf = (void *)(((char *)buf) + RS_MSG_LEN);
480
481                 SSGET32(ch_ptr->ch_widx, tmpwx);
482                 SSGET32(ch_ptr->ch_ridx, tmprx);
483         }       /* End of while */
484         return len;     /* bytes remaining, if any */
485 }
486
487 /* 
488  * Function:    ch_send_event
489  * 
490  * Description: Sends an event to L0. An event with zero length data portion
491  *              is supported.
492  * 
493  * Arguments: int ch_num IN: channel number on which to send the event
494  *            const rs_event_t *evp  IN: EVent to send
495  *
496  * Returns: -EINVAL - if no user registered on the channel (Debug only)
497  *          -EFAULT - if evp is NULL (Debug only)
498  *          zero -    SUCCESS, event sent.
499  *          +EBUSY -  Event not sent. Sender should retry.
500  *
501  * Notes: The event will be copied to the channel buffer, therfore, upon
502  *        return, user may free the space associated with the event
503  */
504 int ch_send_event(int ch_num, const rs_event_t *evp)
505 {
506         int ret = 0;
507         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
508         volatile uint32_t tmpwx, tmprx;
509
510 #ifdef CONFIG_CRAY_RS_DEBUG
511         if (NULL == evp)
512         {
513                 return -EFAULT;
514         }
515
516         if ((NUM_L0RCA_CHANNELS <= ch_num) ||
517             (L0RCA_INITVAL != l0rca_early_cfg.initialized) ||
518             (0 == ch_ptr->reg_count))
519         {
520                 return -EINVAL;
521         }
522 #endif /* CONFIG_CRAY_RS_DEBUG */
523
524         /* Optimize for circular buffer not full */
525
526         /* 
527          * Masking of indexes is not needed for the check in while() below.
528          * Both widx & ridx are unsigned and increase monotonically such that
529          * ridx cannot lag behind widx by more than the circular buf size i.e.
530          * num_obj. widx will overflow before ridx.
531          * 'widx - ridx' will always yield the difference between the two 
532          * even if widx has overflowed and ridx has not yet overflowed.
533          */
534         SSGET32(ch_ptr->ch_widx,tmpwx);
535         SSGET32(ch_ptr->ch_ridx,tmprx);
536         if((tmpwx - tmprx) < ch_ptr->num_obj)
537         {
538                 rs_event_t *wr_ev_ptr = 
539                   &ch_ptr->ch_buf_ptr[tmpwx & (ch_ptr->num_obj - 1)];
540
541                 /* Copy header & data length for the event */
542                 SSMEMPUT(wr_ev_ptr, (uint32_t*)evp, rs_ev_hdr_sz + evp->ev_len);
543
544                 SSGET32(ch_ptr->ch_widx, tmpwx);
545                 SSPUT32(ch_ptr->ch_widx, tmpwx + 1);
546                 set_chan_tx_state(ch_ptr);
547
548                 /* Let L0 know an ev is available */
549                 send_intr_to_l0(ch_ptr);
550         } else
551         {
552                 ret = EBUSY;
553         }
554
555         return ret;
556 }
557
558 /* 
559  * Function:    l0rca_ch_get_event
560  * 
561  * Description: Read an event from L0 (if any). If an event is availabe then 
562  *              the read pointer is advanced.
563  *              NB: Reflect any changes to l0rca_ch_get_event in gdb_l0rca_ch_get_event
564  * 
565  * Arguments: int ch_num IN: channel number from which to read the event
566  *            rs_event_t *evp  IN: Buffer to place the event
567  *
568  * Returns: -EINVAL - if no user registered on the channel (Debug only)
569  *          -EFAULT - if evp is NULL (Debug only)
570  *          zero -    no event to receive at this time
571  *          > 0 -     Event received
572  *
573  */
574 int l0rca_ch_get_event(int ch_num, rs_event_t *evp)
575 {
576         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
577         int ret = 0;
578         uint32_t nbytes;
579         volatile uint32_t tmpwx, tmprx;
580
581 #ifdef CONFIG_CRAY_RS_DEBUG
582         if (NULL == evp)
583                 return -EFAULT;
584
585         if ((NUM_L0RCA_CHANNELS <= ch_num) ||
586             (L0RCA_INITVAL != l0rca_early_cfg.initialized) ||
587             (0 == ch_ptr->reg_count))
588                 return -EINVAL;
589 #endif /* CONFIG_CRAY_RS_DEBUG */
590
591         SSGET32(ch_ptr->ch_widx,tmpwx);
592         SSGET32(ch_ptr->ch_ridx,tmprx);
593         if(tmpwx != tmprx)
594         {
595                 rs_event_t *wr_ev_ptr = 
596                   &ch_ptr->ch_buf_ptr[tmprx & (ch_ptr->num_obj - 1)];
597
598                 /* Copy over the event */
599                 SSGET32(&(wr_ev_ptr->ev_len), nbytes);
600                 SSMEMGET(evp, (uint32_t*)wr_ev_ptr, nbytes + rs_ev_hdr_sz);
601
602                 /* Update the rd index */
603                 SSGET32(ch_ptr->ch_ridx, tmprx);
604                 SSPUT32(ch_ptr->ch_ridx, tmprx + 1);
605
606                 /* Let L0 know that the  event has been drained */
607                 send_intr_to_l0(ch_ptr);
608
609                 ret = 1;
610         }
611
612         return ret;
613 }
614
615 /* 
616  * Function:    unregister_ch_down
617  * 
618  * Description: Unregister function for the upload channel. Use to indicate
619  * that the channel is no longer to be used. The read & write pointers are 
620  * equalized to make the circ buffer empty.
621  * 
622  * Arguments: int ch_num IN: channel number to unregister
623  *
624  * Returns: -EINVAL - if ch_num is not correct or no user registered
625  *          zero (SUCCESS)
626  */
627 int unregister_ch_down(int ch_num)
628 {
629         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
630         volatile uint32_t tmpwx;
631
632         if (NUM_L0RCA_CHANNELS <= ch_num)
633                 return -EINVAL;
634
635         /* Check if user is using this channel */
636         if (!ch_ptr->reg_count)
637                 return -EINVAL;
638
639         ch_ptr->down_handler = NULL;
640         ch_ptr->reg_count--;
641
642         /* Equalize the read & write pointers i.e. drain the circ buffer */
643         /* NOTE: We cannot really stop the L0 from sending data */
644         SSGET32(ch_ptr->ch_widx, tmpwx);
645         SSPUT32(ch_ptr->ch_ridx, tmpwx);
646
647         return 0;
648 }
649
650 /* 
651  * Function:    unregister_ch_up
652  * 
653  * Description: Unregister function for the download channel. Use to indicate
654  * that the channel is no longer to be used.
655  * 
656  * Arguments: int ch_num IN: channel number to unregister
657  *
658  * Returns: -EINVAL - if ch_num is not correct or no user registered
659  *          zero (SUCCESS)
660  */
661 int unregister_ch_up(int ch_num)
662 {
663         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
664         volatile uint32_t tmpwx, tmprx;
665
666         if (NUM_L0RCA_CHANNELS <= ch_num)
667                 return -EINVAL;
668
669         /* Check if user is using this channel */
670         if (!ch_ptr->reg_count)
671                 return -EINVAL;
672
673         /* Wait for events to be drained by the L0 */
674         SSGET32(ch_ptr->ch_widx,tmpwx);
675         SSGET32(ch_ptr->ch_ridx,tmprx);
676         while(tmpwx != tmprx)
677         {
678                 udelay(1000);
679                 SSGET32(ch_ptr->ch_widx,tmpwx);
680                 SSGET32(ch_ptr->ch_ridx,tmprx);
681         }
682
683         ch_ptr->up_handler = NULL;
684         ch_ptr->reg_count--;
685
686         return 0;
687 }
688
689 /* TODO: If we decide to use the PKT_MODE register to indicate the channels
690  * that need attention then use PKT_MODE instead of looking at each channel.
691  * TODO: Currently the rx_done callback is invoked for each event in the 
692  * incoming channel. Change this to be called with all the pending events.
693  * Note that since the channel is a circular buffer and the pending events
694  * wrap around, then the callback needs to be invoked twice - once with events
695  * upto the "end" of the circular buffer and then with events starting from the
696  * "start" of the circular buffer.
697  * TODO: To prevent thrashing of the tx_done callback in case the circular
698  * buffer is being operated under almost full condition, obey the threshold
699  * specified at the registration. The tx_done callback is only called once the
700  * circular buffer occupancy is below the specified threshold.
701  */
702 /* 
703  * Function:    l0rca_poll_callback
704  * 
705  * Description: Scan the incoming channels and call the receive callback
706  *              (if any) in case an event is pending to be processed.
707  *              Update the read pointer. Next scan the outgoing channels
708  *              and if the channel was full, call the transmit done callback
709  *              so that events may be sent.
710  * 
711  * Arguments: None
712  *
713  * Returns: 0 if no events were processed, else 1.
714  *
715  * Note: It is possible that this routine is called from interrupt
716  *       context. The callbacks invoked *must* not block.
717  */
718
719 int l0rca_poll_callback(void)
720 {
721         int i;
722         int rval = 0;
723         rs_event_t ev, *wr_ev_ptr;
724         volatile uint32_t tmpwx, tmprx;
725
726         /* Loop through all channels with incoming events */
727         for (i = 1; i < NUM_L0RCA_CHANNELS; i+=2)
728         {
729                 l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[i];
730
731                 /* GDB handled separately.
732                  */
733                 if (i == L0RCA_CH_KGDB_DOWN) 
734                     continue;
735
736                 if ((0 == ch_ptr->reg_count) || (NULL == ch_ptr->down_handler))
737                         continue;
738                 
739                 if ((ch_ptr->ch_ridx == 0) || (ch_ptr->ch_widx == 0)) {
740                     continue;
741                 }
742
743                 if (!ch_ptr->num_obj) {
744                     SSGET32(ch_ptr->ch_widx, tmpwx);
745                     SSGET32(ch_ptr->ch_ridx, tmprx);
746                     continue;
747                 }
748
749                 SSGET32(ch_ptr->ch_widx, tmpwx);
750                 SSGET32(ch_ptr->ch_ridx, tmprx);
751                 if (tmpwx != tmprx)
752                 {
753                         wr_ev_ptr = (rs_event_t*)&ch_ptr->ch_buf_ptr[tmprx & (ch_ptr->num_obj - 1)];
754                         /* read the entire event */
755                         SSMEMGET((uint32_t*)&ev, (uint32_t*)wr_ev_ptr, rs_sizeof_event(RS_MSG_LEN));
756
757                         /* Call callback routine with one event */
758                         (ch_ptr->down_handler)(i, &ev, 1);
759
760                         /* We are done with this event */
761                         rval++;
762                         SSGET32(ch_ptr->ch_ridx, tmprx);
763                         SSPUT32(ch_ptr->ch_ridx, tmprx + 1);
764
765                         /* Let L0 know that the  event has been drained */
766                         send_intr_to_l0(ch_ptr);
767                 } /* End of if */
768         } /* End of for incoming channels */
769
770         /* Loop through all channels with outgoing events */
771         for (i = 0; i < NUM_L0RCA_CHANNELS; i+=2)
772         {
773                 l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[i];
774
775                 /* GDB handled separately.
776                  */
777                 if (i == L0RCA_CH_KGDB_UP)
778                         continue;
779
780                 if(NULL != ch_ptr->up_handler)
781                 {
782                         /* Lock needed for mutex with tx routine */
783                         LOCK_CHANNEL(i);
784                         if (CHAN_TX_STATE_FULL == GET_CHAN_STATE(ch_ptr))
785                         {
786                                 /* Call the callback if chan no longer full */
787                                 assert(0 != ch_ptr->reg_count);
788                                 SSGET32(ch_ptr->ch_widx, tmpwx);
789                                 SSGET32(ch_ptr->ch_ridx, tmprx);
790                                 if((tmpwx - tmprx) < ch_ptr->num_obj)
791                                 {
792                                         rval++;
793                                         SET_CHAN_STATE(ch_ptr,CHAN_TX_STATE_AVAIL);
794                                         UNLOCK_CHANNEL(i);
795                                         (ch_ptr->up_handler)(i);
796                                         LOCK_CHANNEL(i);
797                                 }
798                         } /* End of if */
799                         UNLOCK_CHANNEL(i);
800                 }
801         } /* End of for */
802
803         return rval;
804 }
805
806 #if defined(CONFIG_CRAY_XT_KGDB) || defined(CONFIG_CRAY_KGDB)
807 /* Kernel mode GDB via L0 interface routines.
808  *
809  * Note that this code was derived from gdbl0.c,
810  * which was derived from Linux gdbserial.c,
811  * which contains no copyright notice.  Parts
812  * of this may need to be rewritten if a GPL
813  * copyright notice was removed from gdbserial.c
814  *
815  */
816
817 #define LRPRINTF  printk
818
819 #undef  PRNT                            /* define for debug printing */
820
821 #define GDB_BUF_SIZE    512             /* power of 2, please */
822
823 static char     gdb_buf[GDB_BUF_SIZE] ;
824 static int      gdb_buf_in_inx ;
825 static int      gdb_buf_in_cnt ;
826 static int      gdb_buf_out_inx ;
827
828 static int initialized = -1;
829
830 int gdb_store_overflow;
831 int gdb_read_error;
832
833 /* Preset this with constant fields in the event header */
834 static rs_event_t l0rca_gdb_ev_template = {0};
835
836 /*
837  * Function:    rcal0_gdb_template
838  *
839  * Description: Hand craft a event header to be sent with each outgoing event
840  *
841  * Arguments: None.
842  *
843  * Returns: None
844  *
845  * Note: The len & timestamp are not filled in.
846  */
847 static void rcal0_gdb_template(void)
848 {
849         l0rca_gdb_ev_template.ev_id = ec_kgdb_output;
850         l0rca_gdb_ev_template.ev_gen = RCA_MKSVC(RCA_INST_ANY,
851             RCA_SVCTYPE_TEST0, l0rca_get_proc_id());
852         l0rca_gdb_ev_template.ev_src = l0rca_gdb_ev_template.ev_gen;
853         l0rca_gdb_ev_template.ev_priority = RCA_LOG_DEBUG;
854         l0rca_gdb_ev_template.ev_flag = 0;      /* For Debugging */
855
856         /* Timestamp, len & data is filled at the time of sending event */
857 }
858
859 /*
860  * Function:    l0_gdb_init
861  *
862  * Description: Take steps to set things up for early_printk output
863  *
864  * Arguments: struct console *console IN: pointer to console struct
865  *            char *input IN: Not used
866  *
867  * Returns: zero (SUCCESS)
868  */
869 int l0_gdb_init(void)
870 {
871
872         int ret;
873
874         /* RCA already initialized on Q
875          */
876         /* Read the configuration information provided by L0 */
877         l0rca_init_config();
878
879         /* Setup the Event template to use for outgoing events */
880         rcal0_gdb_template();
881
882         /* Set up channel internal state by calling
883          * registration routines.
884          */
885
886         /* Register with the KGDB out channel to send gdb data */
887         ret = register_ch_up (L0RCA_CH_KGDB_UP, NULL, 0, 0);
888
889         if (!ret)
890         {
891                 /* Register with the KGDB in channel to receive gdb commands */
892                 ret = register_ch_down(L0RCA_CH_KGDB_DOWN, NULL, 0);
893         }
894         
895         return ret;
896 }
897
898 extern void breakpoint(void);
899
900
901 int gdb_hook(void)
902 {
903         int retval;
904
905         /*
906          * Call GDB routine to setup the exception vectors for the debugger.
907          */
908         
909         /* Setup both kgdb channels */
910         retval = l0_gdb_init();
911
912         /* TODO: on Linux the call to printk in this
913          * routine no longer generate output.
914          *
915          * Did something change in the setup of the
916          * console channel?
917          */
918         if (retval == 0)
919         {
920                 initialized = 1;
921         } else
922         {
923                 initialized = 0;
924                 LRPRINTF("gdb_hook: l0_gdb_init() failed: %d\n", retval);
925                 return (-1);
926         }
927         return 0;
928
929 } /* gdb_hook */
930
931 /*
932  * Function:   l0rca_kgdb_down_getc()
933  * 
934  * Description: Checks for an event on the KGDB DOWN L0 channel
935  *              and returns the first character, other characters
936  *              are thrown away.  Used to detect control C for
937  *              breakpointing the kernel.  Returns 0 when no
938  *              input is available or on error where gdb_read_error
939  *              is incremented.
940  */
941 int l0rca_kgdb_down_getc(void)
942 {
943         char    *chp;
944         int ret, len;
945         rs_event_t ev = {0};
946
947         if ((ret = l0rca_ch_get_event(L0RCA_CH_KGDB_DOWN, &ev)) <= 0) {
948                 if (ret < 0)
949                      gdb_read_error++;
950                 return 0;
951         }
952         l0rca_event_data(&ev, (void *)&chp, &len);
953         if (len > 0)
954                 return *chp;
955         return 0;
956 } /* l0rca_kgdb_down_getc */
957
958 /* Only routines used by the Kernel trap mode KGDB interface
959  * should follow this point.
960  *
961  * These functions should only call other `gdb_.*' functions.
962  *
963  * This is best done by examining the assembly file and
964  * ensuring that all assembly call statements only call
965  * routines that match `gdb_.*', in all of the routines
966  * that follow.
967  *
968  * NB: SETTING BREAKPOINTS IN THE FOLLOWING ROUTINES MAY
969  * BREAK THE KERNEL DEBUGGER.
970  */
971
972 /* 
973  * Function:    gdb_l0rca_event_data
974  * 
975  * Description: Clone of l0rca_event_data to only be called by kernel GDB.
976  *              data portion of the event.
977  * 
978  * Arguments: rs_event_t *evp IN: Event whose data is of interest
979  *            void **data OUT: Upon return will point to data portion of event
980  *            int32_t *len OUT: Upon return will have the length of the data
981  *                              portion of the event
982  *
983  * Returns: No Return Value.
984  */
985 void gdb_l0rca_event_data(rs_event_t *evp, void **data, int32_t *len)
986 {
987         /* Get length and data portion from the event */
988         *len = evp->ev_len;
989         *data = &evp->ev_data;
990 } /* gdb_l0rca_event_data */
991
992 /*
993  * Function:    gdb_set_chan_tx_state
994  *
995  * Description: Clone of set_chan_tx_state to only be called by kernel GDB.
996  */
997 static inline void gdb_set_chan_tx_state(l0rca_mapped_ch_t *ch_ptr)
998 {
999
1000         int not_full = (*ch_ptr->ch_widx - *ch_ptr->ch_ridx) < ch_ptr->num_obj;
1001
1002         SET_CHAN_STATE(ch_ptr, not_full  ? CHAN_TX_STATE_AVAIL : CHAN_TX_STATE_FULL);
1003 }
1004
1005 static void gdb_memcpy(void *dest, const void *src, int cnt)
1006 {
1007     int i;
1008     char *pd = dest;
1009     const char *ps = src;
1010
1011     for (i = 0; i < cnt; i++)
1012         pd[i] = ps[i];
1013 }
1014
1015 /* 
1016  * Function:    gdb_ch_send_data
1017  *
1018  * Description: Clone of ch_send_data to be only called by kernel GDB.
1019  * 
1020  */
1021 int gdb_ch_send_data(int ch_num, const rs_event_t *ev_hdr, 
1022                  void* buf, unsigned int len)
1023 {
1024         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
1025
1026         /* No registration checks needed.
1027          */
1028
1029         /* Optimize for buf not full and only one event needed to send */
1030
1031         /* 
1032          * Masking of indexes is not needed for the check in while() below.
1033          * Both widx & ridx are unsigned and increase monotonically such that
1034          * ridx cannot lag behind widx by more than the circular buf size i.e.
1035          * num_obj. widx will overflow before ridx.
1036          * 'widx - ridx' will always yield the difference between the two 
1037          * even if widx has overflowed and ridx has not yet overflowed.
1038          */
1039         while((*ch_ptr->ch_widx - *ch_ptr->ch_ridx) < ch_ptr->num_obj)
1040         {
1041                 rs_event_t *wr_ev_ptr = 
1042                   &ch_ptr->ch_buf_ptr[*ch_ptr->ch_widx & (ch_ptr->num_obj - 1)];
1043
1044                 /* Copy same header for each event */
1045                 gdb_memcpy(wr_ev_ptr, (void *) ev_hdr, rs_ev_hdr_sz);
1046
1047                 /* Copy the data portion over */
1048                 wr_ev_ptr->ev_len = (RS_MSG_LEN > len) ? len : RS_MSG_LEN;
1049                 gdb_memcpy((char *)wr_ev_ptr + rs_ev_hdr_sz, buf,
1050                        wr_ev_ptr->ev_len);
1051
1052                 /* TODO: Set the timestamp in each event */
1053 #if 0
1054                 wr_ev_ptr->_ev_stp = 0x0;
1055 #endif  /* 0 */
1056                 
1057                 len -= wr_ev_ptr->ev_len;
1058                 /* 
1059                  * After updating the widx, DO NOT access any field in that 
1060                  * event. Though not desirable, the reader is free to alter 
1061                  * fields in the event.
1062                  */
1063                 (*ch_ptr->ch_widx)++;
1064                 gdb_set_chan_tx_state(ch_ptr);
1065
1066                 /* Let L0 know an ev is available */
1067                 send_intr_to_l0(ch_ptr);
1068
1069                 if (0 == len)
1070                         break;
1071
1072                 buf += RS_MSG_LEN;
1073         }       /* End of while */
1074
1075         return len;     /* bytes remaining, if any */
1076 }
1077
1078 /* 
1079  * Function:    gdb_l0rca_ch_get_event
1080  * 
1081  * Description: Clone of l0rca_ch_get_event to only be called by kernel GDB.
1082  *              the read pointer is advanced.
1083  * 
1084  */
1085 int gdb_l0rca_ch_get_event(int ch_num, rs_event_t *evp)
1086 {
1087         l0rca_mapped_ch_t *ch_ptr = &l0rca_early_cfg.ch_data[ch_num];
1088         int ret = 0;
1089
1090         /* No registration checks needed
1091          */
1092
1093         if(*ch_ptr->ch_widx != *ch_ptr->ch_ridx)
1094         {
1095                 rs_event_t *wr_ev_ptr = 
1096                   &ch_ptr->ch_buf_ptr[*ch_ptr->ch_ridx & (ch_ptr->num_obj - 1)];
1097
1098                 /* Copy over the event */
1099                 gdb_memcpy(evp, (void *)wr_ev_ptr, wr_ev_ptr->ev_len+rs_ev_hdr_sz);
1100
1101                 /* Update the rd index */
1102                 (*ch_ptr->ch_ridx)++;
1103
1104                 /* Let L0 know that the  event has been drained */
1105                 send_intr_to_l0(ch_ptr);
1106
1107                 ret = 1;
1108         }
1109
1110         return ret;
1111 }
1112
1113 /*
1114  * Function:    gdb_store_char_in_buf
1115  *
1116  * Description: Check for overflow and place the incoming character into 
1117  *              the local buffer for later retreival.
1118  *
1119  * Arguments: int ch IN: Incoming character
1120  *
1121  * Returns: zero  - (SUCCESS)
1122  *          -1    - Buffer Overflow
1123  */
1124 static int gdb_store_char_in_buf(char ch)
1125 {
1126         if (gdb_buf_in_cnt >= GDB_BUF_SIZE)
1127         {       /* buffer overflow, clear it */
1128                 gdb_buf_in_inx = 0 ;
1129                 gdb_buf_in_cnt = 0 ;
1130                 gdb_buf_out_inx = 0 ;
1131                 return -1;
1132         }
1133
1134         gdb_buf[gdb_buf_in_inx++] = ch;
1135         gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ;
1136         gdb_buf_in_cnt++;
1137
1138         return 0;
1139 }
1140
1141 /*
1142  * Wait until the interface can accept a char, then write it.
1143  */
1144 static void gdb_write_char(char chr)
1145 {
1146         int ret;
1147
1148         while ((ret = gdb_ch_send_data(L0RCA_CH_KGDB_UP, &l0rca_gdb_ev_template,
1149                (void *)&chr, sizeof(char))) > 0)
1150         {
1151                 /* Buffer full; keep trying.... */
1152                 ;
1153         }       /* End of while */
1154
1155         return;
1156 } /* gdb_write_char */
1157
1158 /*
1159  * gdb_getc
1160  *
1161  * This is a GDB stub routine.  It waits for a character from the
1162  * L0 interface and then returns it.
1163  */
1164 int gdb_getc(int wait)
1165 {
1166         char    *chp, *end_buf;
1167         int ret, len;
1168         rs_event_t ev = {0};
1169
1170 #ifdef PRNT
1171         LRPRINTF("gdb_getc:") ;
1172 #endif
1173         /* First check if the receive callback has any chars pending */
1174         if (gdb_buf_in_cnt == 0)
1175         {
1176                 /* No chars from rx_callback; Loop until a char is available */
1177                 while ((ret = gdb_l0rca_ch_get_event(L0RCA_CH_KGDB_DOWN, &ev)) 
1178                         <= 0)
1179                 {
1180                         if (ret < 0)
1181                         {
1182                                 /* Error!! This is death */
1183                                 gdb_read_error++;
1184                                 return -1;
1185                         }
1186                         if (! wait)
1187                                 return 0;
1188                 } /* End of while */
1189
1190                 /* Get the data in the event */
1191                 gdb_l0rca_event_data(&ev, (void *)&chp, &len);
1192
1193                 /* We have an event; fill the local buffer */
1194                 for (end_buf = chp+len; chp < end_buf; chp++)
1195                 {
1196                         if (gdb_store_char_in_buf(*chp) < 0)
1197                         {
1198                                 gdb_store_overflow++;
1199                         }
1200                 } /* End of for */
1201         } /* End of if */
1202
1203         /* There should be something for us in the local buffer now */
1204         chp = &gdb_buf[gdb_buf_out_inx++] ;
1205         gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ;
1206         gdb_buf_in_cnt--;
1207
1208 #ifdef PRNT
1209         LRPRINTF("%c\n", *chp > ' ' && *chp < 0x7F ? *chp : ' ') ;
1210 #endif
1211         return(*chp) ;
1212
1213 } /* gdb_getc */
1214
1215 /*
1216  * gdb_putc
1217  *
1218  * This is a GDB stub routine.  It waits until the interface is ready
1219  * to transmit a char and then sends it.  If there is no serial
1220  * interface connection then it simply returns to its caller, having
1221  * pretended to send the char.
1222  */
1223 int gdb_putc(char chr)
1224 {
1225 #ifdef PRNT
1226         LRPRINTF("gdb_putc: chr=%02x '%c'\n", chr,
1227                  chr > ' ' && chr < 0x7F ? chr : ' ') ;
1228 #endif
1229
1230         gdb_write_char(chr);    /* this routine will wait */
1231
1232         return 1;
1233
1234 } /* gdb_putc */
1235
1236 int     putDebugPacket(char *buf, int n)
1237 {
1238         int ret = -1;
1239
1240         /* Loop sending the data */
1241         while (n)
1242         {
1243                 if ((ret = gdb_ch_send_data(L0RCA_CH_KGDB_UP, &l0rca_gdb_ev_template,
1244                     (void *)buf, n)) <= 0) {
1245                         /* Either error or we are done */
1246                         break;
1247                 }
1248
1249                 if (n > ret) {
1250                         /* Some bytes were sent, point to the remaining data */
1251                         buf += (n - ret);
1252                         n = ret;
1253                 }
1254         }       
1255
1256         return ret;
1257 }
1258 #endif /* CONFIG_CRAY_KGDB */