1/**
2 * \file
3 * \brief "Serial" driver on host side
4 */
5
6/*
7 * Copyright (c) 2014 ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <stdio.h>
16#include <string.h>
17#include <barrelfish/barrelfish.h>
18
19
20
21#include "xeon_phi_internal.h"
22
23#define XEON_PHI_BUFFER_LENGTH 0x400
24#define XEON_PHI_POLL_GIVEUP   0x100
25
26
27#define ANSI_COLOR_RED     "\x1b[31m"
28#define ANSI_COLOR_GREEN   "\x1b[32m"
29#define ANSI_COLOR_YELLOW  "\x1b[33m"
30#define ANSI_COLOR_BLUE    "\x1b[34m"
31#define ANSI_COLOR_MAGENTA "\x1b[35m"
32#define ANSI_COLOR_CYAN    "\x1b[36m"
33#define ANSI_COLOR_RESET   "\x1b[0m"
34
35static inline void xprintf(uint8_t xid,
36                           char *fmt)
37{
38    switch (xid) {
39        case 0:
40            printf(ANSI_COLOR_YELLOW">> XEON_PHI.%u"ANSI_COLOR_RESET": %s\n", xid, fmt);
41            break;
42        case 1:
43            printf(ANSI_COLOR_MAGENTA">> XEON_PHI.%u"ANSI_COLOR_RESET": %s\n", xid, fmt);
44            break;
45        default:
46            printf("\x1b[32m>> XEON_PHI \033[31m%u\033[0m: %s\n", xid, fmt);
47            break;
48    }
49}
50
51uint32_t xeon_phi_serial_handle_recv(struct xeon_phi *phi)
52{
53    xeon_phi_serial_ctrl_t sctrl = xeon_phi_serial_reset;
54    xeon_phi_serial_data_t sdata = xeon_phi_serial_reset;
55
56    sctrl = xeon_phi_serial_ctrl_rd(&phi->serial_base);
57
58    if (!sctrl) {
59        return 0;
60    }
61
62    uint32_t i = 0;
63    sdata = xeon_phi_serial_data_rd(&phi->serial_base);
64    uint8_t has_data = 0;
65    uint8_t value = 0;
66    while (i < 4) {
67        switch (i) {
68            case 0:
69                has_data = xeon_phi_serial_ctrl_value0_extract(sctrl);
70                value = xeon_phi_serial_data_value0_extract(sdata);
71                break;
72            case 1:
73                has_data = xeon_phi_serial_ctrl_value1_extract(sctrl);
74                value = xeon_phi_serial_data_value1_extract(sdata);
75                break;
76            case 2:
77                has_data = xeon_phi_serial_ctrl_value2_extract(sctrl);
78                value = xeon_phi_serial_data_value2_extract(sdata);
79                break;
80            case 3:
81                has_data = xeon_phi_serial_ctrl_value3_extract(sctrl);
82                value = xeon_phi_serial_data_value3_extract(sdata);
83                break;
84        }
85
86        if ((has_data & 0x80) || !has_data) {
87            i++;
88            continue;
89        }
90        if (has_data != xeon_phi_serial_data) {
91            debug_printf("[xeon phi %d] : ERROR invalid ctrl value.%x\n",
92                         phi->id,
93                         has_data);
94        }
95        /* always issue a new line */
96        if (value == '\n') {
97            phi->serial_buffer[phi->serial_buffer_idx] = '\0';
98            xprintf(phi->id, phi->serial_buffer);
99            phi->serial_buffer_idx = 0;
100            /* there was a "flush" so flush buffer to log */
101        } else if (value == 0x4) {
102            phi->serial_buffer[phi->serial_buffer_idx] = '\0';
103            xprintf(phi->id, phi->serial_buffer);
104            phi->serial_buffer_idx = 0;
105            /* buffer is full, flush buffer */
106        } else if (phi->serial_buffer_idx == XEON_PHI_BUFFER_LENGTH) {
107            phi->serial_buffer[phi->serial_buffer_idx] = '\0';
108            xprintf(phi->id, phi->serial_buffer);
109            phi->serial_buffer[0] = value;
110            phi->serial_buffer_idx = 1;
111            /* just store the char */
112        } else {
113            phi->serial_buffer[phi->serial_buffer_idx] = value;
114            phi->serial_buffer_idx++;
115        }
116        i++;
117    }
118    /* acknowledge the data receive */
119    xeon_phi_serial_ctrl_rawwr(&phi->serial_base, xeon_phi_serial_reset);
120
121    return 1;
122}
123
124static int xeon_phi_recv_handler(void *arg)
125{
126    uint32_t nodata;
127
128    struct xeon_phi *phi = arg;
129
130    debug_printf("[xeon phi %d] :  receive handler started.\n", phi->id);
131
132    nodata = XEON_PHI_POLL_GIVEUP;
133
134
135
136    while (1) {
137        if (!xeon_phi_serial_handle_recv(arg)) {
138            if (--nodata) {
139                continue;
140            }
141
142            // reset counter
143            nodata = XEON_PHI_POLL_GIVEUP;
144
145            thread_yield();
146
147            continue;
148        }
149    }
150
151    debug_printf("[xeon phi %d] : thread terminated.\n ", phi->id);
152
153    return 0;
154}
155
156/**
157 * \brief initializes a new thread for receiving the serial out of the card
158 *
159 * The sbox memory region has already been mapped
160 */
161errval_t xeon_phi_serial_start_recv_thread(struct xeon_phi *phi)
162{
163    if (phi->serial_base.base == NULL) {
164        xeon_phi_serial_init(phi);
165    }
166
167    xeon_phi_recv_handler(phi);
168    //thread_create(xeon_phi_recv_handler, xarg);
169
170    return SYS_ERR_OK;
171}
172
173/**
174 * \brief initializes the serial receiver
175 *
176 * \param phi   pointer to the card information
177 */
178errval_t xeon_phi_serial_init(struct xeon_phi *phi)
179{
180
181    xeon_phi_serial_initialize(&phi->serial_base, XEON_PHI_MMIO_TO_SBOX(phi));
182
183    xeon_phi_serial_ctrl_rawwr(&phi->serial_base, xeon_phi_serial_reset);
184
185    phi->serial_buffer_idx = 0;
186    memset(phi->serial_buffer, 0, sizeof(phi->serial_buffer));
187
188    return SYS_ERR_OK;
189}
190