source: trunk/kernel/devices/dev_nic.c@ 8

Last change on this file since 8 was 3, checked in by alain, 9 years ago

Introduce dev_fbf, dev dma, dev_iob

File size: 7.9 KB
RevLine 
[1]1/*
2 * dev_nic.c - NIC (Network Controler) generic device API implementation.
3 *
4 * Author Alain Greiner (2016)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_types.h>
25#include <hal_special.h>
26#include <printk.h>
[3]27#include <chdev.h>
[1]28#include <thread.h>
29#include <soclib_nic.h>
30#include <dev_nic.h>
31
32/////////////////////////////////////////////////////////////////////////////////////////
33// Extern global variables
34/////////////////////////////////////////////////////////////////////////////////////////
35
[3]36extern chdev_directory_t chdev_dir; // allocated in kernel_init.c
[1]37
[3]38extern chdev_pic_input_t chdev_pic_input; // allocated in kernel_init.c
[1]39
[3]40////////////////////////////////////
41void dev_nic_init( chdev_t * chdev )
[1]42{
[3]43 // the local ICU chdev must be initialized before the NIC chdev, because
44 // the NIC chdevs initialisation requires allocation of a WTI from local ICU
45 xptr_t icu_xp = chdev_dir.icu[local_cxy];
46 assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before NIC" );
[1]47
[3]48 // get "impl" , "channel" , "is_rx" fields from chdev descriptor
49 uint32_t impl = chdev->impl;
50 uint32_t is_rx = chdev->is_rx;
51 uint32_t channel = chdev->channel;
[1]52
[3]53 // set driver specific fields in chdev descriptor and call driver init function
[1]54 if( impl == IMPL_NIC_SOC )
55 {
[3]56 chdev->cmd = &soclib_nic_cmd;
57 chdev->isr = &soclib_nic_isr;
58 soclib_nic_init( chdev );
[1]59 }
60 else
61 {
[3]62 assert( false , __FUNCTION__ , "undefined NIC device implementation" );
[1]63 }
64
[3]65 // get a WTI mailbox from local ICU
66 uint32_t wti_id = dev_icu_wti_alloc();
[1]67
[3]68 assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" );
[1]69
[3]70 // select a core
71 lid_t lid = cluster_select_local_core();
[1]72
[3]73 // enable WTI IRQ and update WTI interrupt vector
74 dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev );
75
[1]76 // link NIC IRQ to WTI mailbox in PIC component
77 uint32_t irq_id;
[3]78 if( is_rx ) irq_id = chdev_pic_input.nic_rx[channel];
79 else irq_id = chdev_pic_input.nic_tx[channel];
[1]80 dev_pic_bind_irq( irq_id , local_cxy , wti_id );
81
82 // create server thread
[3]83 thread_t * new_thread;
[1]84 error_t error;
85
[3]86 error = thread_kernel_create( &new_thread,
87 THREAD_DEV,
88 &chdev_sequencial_server,
89 chdev,
90 lid );
[1]91
[3]92 assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
[1]93
[3]94 // set "server" field in chdev descriptor
95 chdev->server = new_thread;
[1]96
97 // start server thread
[3]98 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
[1]99
100} // end dev_nic_init()
101
102///////////////////////////////////
103error_t dev_nic_read( pkd_t * pkd )
104{
105 error_t error;
106
107 // get pointers on this NIC-RX kernel thread
108 thread_t * thread_ptr = CURRENT_THREAD;
109 xptr_t thread_xp = XPTR( local_cxy , thread_ptr );
110
111 // get local pointer on core running this kernel thead
112 core_t * core = thread_ptr->core;
113
114 nic_dmsg("\n[INFO] %s enters for NIC-RX thread on core %d in cluster %x\n",
115 __FUNCTION__ , core->lid , local_cxy );
116
[3]117 // get pointer on NIC-RX chdev descriptor
[1]118 uint32_t channel = thread_ptr->dev_channel;
[3]119 xptr_t dev_xp = chdev_dir.nic_rx[channel];
[1]120 cxy_t dev_cxy = GET_CXY( dev_xp );
[3]121 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
[1]122
[3]123 assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined NIC chdev descriptor" );
[1]124
[3]125 assert( (dev_cxy == local_cxy) , __FUNCTION__ , " chdev must be local" );
[1]126
127 // initialize command in thread descriptor
[3]128 thread_ptr->command.nic.dev_xp = dev_xp;
[1]129
130 // call driver to test readable
[3]131 thread_ptr->command.nic.cmd = NIC_CMD_READABLE;
[1]132 dev_ptr->cmd( thread_xp );
133
134 // check error
[3]135 error = thread_ptr->command.nic.error;
[1]136 if( error ) return error;
137
138 // block and deschedule if queue non readable
[3]139 if( thread_ptr->command.nic.status == false )
[1]140 {
141 // get NIC-RX IRQ index and type
142 uint32_t irq_type = dev_ptr->irq_type;
143 uint32_t irq_id = dev_ptr->irq_id;
144
145 // enable NIC-RX IRQ
[3]146 dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
[1]147
148 // block on THREAD_BLOCKED I/O condition and deschedule
149 thread_block( thread_ptr , THREAD_BLOCKED_IO );
150 sched_yield();
151
152 // disable NIC-RX channel IRQ
[3]153 dev_icu_disable_irq( core->lid , irq_type , irq_id );
[1]154 }
155
156 // call driver for actual read
[3]157 thread_ptr->command.nic.cmd = NIC_CMD_READ;
158 thread_ptr->command.nic.buffer = pkd->buffer;
[1]159 dev_ptr->cmd( thread_xp );
160
161 // check error
[3]162 error = thread_ptr->command.nic.error;
[1]163 if( error ) return error;
164
165 // returns packet length
[3]166 pkd->length = thread_ptr->command.nic.length;
[1]167
168 nic_dmsg("\n[INFO] %s exit for NIC-RX thread on core %d in cluster %x\n",
169 __FUNCTION__ , core->lid , local_cxy );
170
171 return 0;
172
173} // end dev_nic_read()
174
175
176////////////////////////////////////
177error_t dev_nic_write( pkd_t * pkd )
178{
179 error_t error;
180
181 // get pointers on the NIC-TX kernel tread
182 thread_t * thread_ptr = CURRENT_THREAD;
183 xptr_t thread_xp = XPTR( local_cxy , thread_ptr );
184
185 // get local pointer on core running this kernel thead
186 core_t * core = thread_ptr->core;
187
188 nic_dmsg("\n[INFO] %s enters for NIC-RX thread on core %d in cluster %x\n",
189 __FUNCTION__ , core->lid , local_cxy );
190
[3]191 // get pointer on NIC-TX chdev descriptor
[1]192 uint32_t channel = thread_ptr->dev_channel;
[3]193 xptr_t dev_xp = chdev_dir.nic_tx[channel];
[1]194 cxy_t dev_cxy = GET_CXY( dev_xp );
[3]195 chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
[1]196
[3]197 assert ( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined NIC chdev descriptor" );
[1]198
[3]199 assert( (dev_cxy == local_cxy) , __FUNCTION__ , " chdev must be local" );
[1]200
201 // initialize command in thread descriptor
[3]202 thread_ptr->command.nic.dev_xp = dev_xp;
[1]203
204 // call driver to test writable
[3]205 thread_ptr->command.nic.cmd = NIC_CMD_WRITABLE;
[1]206 dev_ptr->cmd( thread_xp );
207
208 // check error
[3]209 error = thread_ptr->command.nic.error;
[1]210 if( error ) return error;
211
212 // block and deschedule if queue non writable
[3]213 if( thread_ptr->command.nic.status == false )
[1]214 {
215 // get NIC-TX IRQ index and type
216 uint32_t irq_type = dev_ptr->irq_type;
217 uint32_t irq_id = dev_ptr->irq_id;
218
219 // enable NIC-TX IRQ
[3]220 dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
[1]221
222 // block on THREAD_BLOCKED I/O condition and deschedule
223 thread_block( thread_ptr , THREAD_BLOCKED_IO );
224 sched_yield();
225
226 // disable NIC-TX IRQ
[3]227 dev_icu_disable_irq( core->lid , irq_type , irq_id );
[1]228 }
229
230 // call driver for actual write
[3]231 thread_ptr->command.nic.cmd = NIC_CMD_WRITE;
232 thread_ptr->command.nic.buffer = pkd->buffer;
233 thread_ptr->command.nic.length = pkd->length;
[1]234 dev_ptr->cmd( thread_xp );
235
236 // check error
[3]237 error = thread_ptr->command.nic.error;
[1]238 if( error ) return error;
239
240 nic_dmsg("\n[INFO] %s exit for NIC-TX thread on core %d in cluster %x\n",
241 __FUNCTION__ , core->lid , local_cxy );
242
243 return 0;
244} // end dev_nic_write()
245
246
247
Note: See TracBrowser for help on using the repository browser.