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

Last change on this file since 2 was 1, checked in by alain, 8 years ago

First import

File size: 9.8 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>
27#include <device.h>
28#include <thread.h>
29#include <soclib_nic.h>
30#include <dev_nic.h>
31
32/////////////////////////////////////////////////////////////////////////////////////////
33// Extern global variables
34/////////////////////////////////////////////////////////////////////////////////////////
35
36extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
37
38extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
39
40
41//////////////////////////////////
42void dev_nic_init( xptr_t dev_xp )
43{
44    // get device descriptor cluster and local pointer
45    cxy_t      dev_cxy = GET_CXY( dev_xp );
46    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
47
48    // get "impl" , "channel" , "is_rx" fields from device descriptor
49    uint32_t  impl    = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
50    uint32_t  is_rx   = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->is_rx ) );
51    uint32_t  channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) );
52
53    // set driver specific fields in device descriptor
54    // and call driver init function
55    if( impl == IMPL_NIC_SOC )
56    {
57        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_nic_cmd );
58        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_nic_isr );
59        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
60                           XPTR( local_cxy , "NIC_SOC" ) , 16 );
61        soclib_nic_init( dev_xp );
62    }
63//    else if( impl == IMPL_NIC_I86)
64//    {
65//        hal_remote_spt( XPTR( cxy , &ptr->cmd ) , &i86_nic_cmd );
66//        hal_remote_spt( XPTR( cxy , &ptr->isr ) , &i86_nic_isr );
67//        hal_remote_memcpy( XPTR( cxy , &ptr->name ),
68//                           XPTR( local_cxy , "NIC_I86" ) , 16 );
69//        i86_nic_init( dev );
70//    }
71    else
72    {
73        printk("\n[PANIC] in %s : undefined NIC device implementation\n", __FUNCTION__ );
74        hal_core_sleep();
75    }
76
77    // get a free WTI mailbox for this NIC device
78    uint32_t wti_id;
79    if( dev_cxy == local_cxy )                       // NIC device cluster is local
80    {
81        wti_id = dev_icu_wti_alloc();
82    }
83    else                                             // NIC device cluster is remote
84    {
85        rpc_icu_wti_alloc_client( dev_cxy , &wti_id ); 
86    }
87
88    if( wti_id == -1 )
89    {
90        printk("\n[PANIC] in %s : cannot allocate WTI mailbox\n", __FUNCTION__ );
91        hal_core_sleep();
92    }
93
94    // enable WTI IRQ in remote ICU and update WTI interrupt vector
95    dev_icu_enable_irq( dev_cxy, 0 , WTI_TYPE , wti_id , dev_xp );
96
97    // link NIC IRQ to WTI mailbox in PIC component
98    uint32_t irq_id; 
99    if( is_rx ) irq_id = devices_input_irq.nic_rx[channel];
100    else        irq_id = devices_input_irq.nic_tx[channel];
101    dev_pic_bind_irq( irq_id , local_cxy , wti_id );
102
103    // create server thread
104    thread_t * new_thread_ptr;
105    xptr_t     new_thread_xp;
106    error_t    error;
107
108    if( dev_cxy == local_cxy )                        // device cluster is local
109    {
110        error = thread_kernel_create( &new_thread_ptr,
111                                      THREAD_DEV,
112                                      &dev_ioc_server,
113                                      dev_ptr,
114                                      cluster_select_local_core() ); 
115
116        new_thread_xp = XPTR( local_cxy , new_thread_ptr );
117    }
118    else                                              // device cluster is remote
119    {
120        rpc_thread_kernel_create_client( dev_cxy,
121                                         THREAD_DEV,
122                                         &dev_ioc_server,
123                                         dev_ptr,
124                                         &new_thread_xp,
125                                         &error );
126
127        new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp );
128    }
129    if( error )
130    {
131        printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ );
132        hal_core_sleep();
133    }
134
135    // set "server" field in device descriptor
136    hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr );
137   
138    // start server thread
139    thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
140
141}  // end dev_nic_init()
142
143///////////////////////////////////
144error_t dev_nic_read( pkd_t * pkd )
145{
146    error_t  error;
147
148    // get pointers on this NIC-RX kernel thread
149    thread_t * thread_ptr = CURRENT_THREAD;
150    xptr_t     thread_xp  = XPTR( local_cxy , thread_ptr );
151
152    // get local pointer on core running this kernel thead
153    core_t * core = thread_ptr->core;
154
155    nic_dmsg("\n[INFO] %s enters for NIC-RX thread on core %d in cluster %x\n", 
156                 __FUNCTION__ , core->lid , local_cxy );
157
158    // get pointer on NIC-RX device descriptor
159    uint32_t   channel = thread_ptr->dev_channel; 
160    xptr_t     dev_xp  = devices_dir.nic_rx[channel];
161    cxy_t      dev_cxy = GET_CXY( dev_xp );
162    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
163
164    if ( dev_xp == XPTR_NULL )
165    {
166        printk("\n[PANIC] in %s : undefined NIC device descriptor\n", __FUNCTION__ );
167        hal_core_sleep();
168    }
169
170    if ( dev_cxy != local_cxy )
171    {
172        printk("\n[PANIC] in %s : device descriptor must be local\n", __FUNCTION__ );
173        hal_core_sleep();
174    }
175
176    // initialize command in thread descriptor
177    thread_ptr->dev.nic.dev_xp = dev_xp;
178
179    // call driver to test readable
180    thread_ptr->dev.nic.cmd = NIC_CMD_READABLE;
181    dev_ptr->cmd( thread_xp );
182
183    // check error
184    error = thread_ptr->dev.nic.error;
185    if( error ) return error;
186
187    // block and deschedule if queue non readable
188    if( thread_ptr->dev.nic.status == false ) 
189    {
190        // get NIC-RX IRQ index and type
191        uint32_t   irq_type = dev_ptr->irq_type;
192        uint32_t   irq_id   = dev_ptr->irq_id;
193
194        // enable NIC-RX IRQ
195        dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp );
196
197        // block on THREAD_BLOCKED I/O condition and deschedule
198        thread_block( thread_ptr , THREAD_BLOCKED_IO );
199        sched_yield();
200
201        // disable NIC-RX channel IRQ
202        dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id );
203    }
204
205    // call driver for actual read
206    thread_ptr->dev.nic.cmd     = NIC_CMD_READ;
207    thread_ptr->dev.nic.buffer  = pkd->buffer;
208    dev_ptr->cmd( thread_xp );
209
210    // check error
211    error = thread_ptr->dev.nic.error;
212    if( error ) return error;
213
214    // returns packet length   
215    pkd->length = thread_ptr->dev.nic.length;
216
217    nic_dmsg("\n[INFO] %s exit for NIC-RX thread on core %d in cluster %x\n", 
218             __FUNCTION__ , core->lid , local_cxy );
219
220    return 0;
221
222}   // end dev_nic_read()
223
224
225////////////////////////////////////
226error_t dev_nic_write( pkd_t * pkd )
227{
228    error_t error;
229
230    // get pointers on the NIC-TX kernel tread
231    thread_t * thread_ptr = CURRENT_THREAD;
232    xptr_t     thread_xp  = XPTR( local_cxy , thread_ptr );
233
234    // get local pointer on core running this kernel thead
235    core_t * core = thread_ptr->core;
236
237    nic_dmsg("\n[INFO] %s enters for NIC-RX thread on core %d in cluster %x\n", 
238                 __FUNCTION__ , core->lid , local_cxy );
239
240    // get pointer on NIC-TX device descriptor
241    uint32_t   channel = thread_ptr->dev_channel; 
242    xptr_t     dev_xp  = devices_dir.nic_tx[channel];
243    cxy_t      dev_cxy = GET_CXY( dev_xp );
244    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
245
246    if ( dev_xp == XPTR_NULL )
247    {
248        printk("\n[PANIC] in %s : undefined NIC device descriptor\n", __FUNCTION__ );
249        hal_core_sleep();
250    }
251
252    if ( dev_cxy != local_cxy )
253    {
254        printk("\n[PANIC] in %s : device descriptor must be local\n", __FUNCTION__ );
255        hal_core_sleep();
256    }
257
258    // initialize command in thread descriptor
259    thread_ptr->dev.nic.dev_xp = dev_xp;
260
261    // call driver to test writable
262    thread_ptr->dev.nic.cmd    = NIC_CMD_WRITABLE;
263    dev_ptr->cmd( thread_xp );
264
265    // check error
266    error = thread_ptr->dev.nic.error;
267    if( error ) return error;
268
269    // block and deschedule if queue non writable
270    if( thread_ptr->dev.nic.status == false ) 
271    {
272        // get NIC-TX IRQ index and type
273        uint32_t   irq_type = dev_ptr->irq_type;
274        uint32_t   irq_id   = dev_ptr->irq_id;
275
276        // enable NIC-TX IRQ
277        dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp );
278
279        // block on THREAD_BLOCKED I/O condition and deschedule
280        thread_block( thread_ptr , THREAD_BLOCKED_IO );
281        sched_yield();
282
283        // disable NIC-TX IRQ
284        dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id );
285    }
286
287    // call driver for actual write
288    thread_ptr->dev.nic.cmd    = NIC_CMD_WRITE;
289    thread_ptr->dev.nic.buffer = pkd->buffer;
290    thread_ptr->dev.nic.length = pkd->length;
291    dev_ptr->cmd( thread_xp );
292
293    // check error
294    error = thread_ptr->dev.nic.error;
295    if( error ) return error;
296
297    nic_dmsg("\n[INFO] %s exit for NIC-TX thread on core %d in cluster %x\n", 
298             __FUNCTION__ , core->lid , local_cxy );
299
300    return 0;
301}  // end dev_nic_write()
302
303
304
Note: See TracBrowser for help on using the repository browser.