source: trunk/kernel/kern/chdev.c @ 176

Last change on this file since 176 was 23, checked in by alain, 8 years ago

Introduce syscalls.

File size: 6.2 KB
Line 
1/*
2 * chdev.c - channel device descriptor operations implementation.
3 *
4 * Authors  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 <kernel_config.h>
25#include <hal_types.h>
26#include <hal_special.h>
27#include <printk.h>
28#include <boot_info.h>
29#include <xlist.h>
30#include <kmem.h>
31#include <thread.h>
32#include <rpc.h>
33#include <chdev.h>
34#include <devfs.h>
35
36////////////////////////////////////////////
37char * chdev_func_str( uint32_t func_type ) 
38{
39        if     ( func_type == DEV_FUNC_RAM ) return "RAM";
40        else if( func_type == DEV_FUNC_ROM ) return "ROM";
41        else if( func_type == DEV_FUNC_FBF ) return "FBF";
42        else if( func_type == DEV_FUNC_IOB ) return "IOB";
43        else if( func_type == DEV_FUNC_IOC ) return "IOC";
44        else if( func_type == DEV_FUNC_MMC ) return "MMC";
45        else if( func_type == DEV_FUNC_DMA ) return "DMA";
46        else if( func_type == DEV_FUNC_NIC ) return "NIC";
47        else if( func_type == DEV_FUNC_TIM ) return "TIM";
48        else if( func_type == DEV_FUNC_TXT ) return "TXT";
49        else if( func_type == DEV_FUNC_ICU ) return "ICU";
50        else if( func_type == DEV_FUNC_PIC ) return "PIC";
51    else                                 return "undefined";
52}
53
54/////////////////////////////////////////
55chdev_t * chdev_create( uint32_t    func,
56                        uint32_t    impl,
57                        uint32_t    channel,
58                        uint32_t    is_rx,
59                        xptr_t      base )
60{
61    chdev_t    * chdev;
62    kmem_req_t   req;
63
64    // allocate memory for chdev
65    req.type   = KMEM_DEVICE;
66    req.flags  = AF_ZERO;
67    chdev      = (chdev_t *)kmem_alloc( &req );
68
69    if( chdev == NULL ) return NULL;
70
71    // initialize waiting threads queue and associated lock
72    remote_spinlock_init( XPTR( local_cxy , &chdev->wait_lock ) );
73    xlist_root_init( XPTR( local_cxy , &chdev->wait_root ) );
74
75    // initialize attributes
76    chdev->func    =  func;
77    chdev->impl    =  impl;
78    chdev->channel =  channel;
79    chdev->is_rx   =  is_rx;
80    chdev->base    =  base; 
81
82    return chdev;
83
84}  // end chdev_create()
85
86///////////////////////////////////
87void chdev_print( chdev_t * chdev )
88{
89    printk("\n - func      = %s"
90           "\n - channel   = %d"
91           "\n - base      = %l"
92           "\n - cmd       = %x"
93           "\n - isr       = %x"
94           "\n - chdev     = %x\n",
95           chdev_func_str(chdev->func),
96           chdev->channel,
97           chdev->base,
98           chdev->cmd,
99           chdev->isr,
100           chdev );
101}
102
103////////////////////////////////////////////////
104void chdev_register_command( xptr_t     chdev_xp,
105                             thread_t * thread )
106{
107    thread_t * thread_ptr = CURRENT_THREAD;
108
109    // get device descriptor cluster and local pointer
110    cxy_t     chdev_cxy = GET_CXY( chdev_xp );
111    chdev_t * chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
112
113    // build extended pointers on client thread xlist and device root
114    xptr_t  xp_list = XPTR( local_cxy , &thread_ptr->wait_list );
115    xptr_t  xp_root = XPTR( chdev_cxy , &chdev_ptr->wait_root );
116
117    // get lock protecting queue
118    remote_spinlock_lock( XPTR( chdev_cxy , &chdev_ptr->wait_lock ) );
119
120    // register client thread in waiting queue
121    xlist_add_last( xp_root , xp_list );
122
123    // unblock server thread
124    thread_unblock( XPTR( chdev_cxy , &chdev_ptr->server ) , THREAD_BLOCKED_DEV_QUEUE );
125
126    // release lock
127    remote_spinlock_unlock( XPTR( chdev_cxy , &chdev_ptr->wait_lock ) );
128
129    // client thread goes to blocked state and deschedule
130    thread_block( thread_ptr , THREAD_BLOCKED_IO );
131    sched_yield();
132
133}  // end chdev_register_command()
134
135///////////////////////////////////////////////
136void chdev_sequencial_server( chdev_t * chdev )
137{
138    xptr_t          client_xp;    // extended pointer on waiting thread
139    cxy_t           client_cxy;   // cluster of client thread
140    thread_t      * client_ptr;   // local pointer on client thread
141    thread_t      * server;       // local pointer on this thread
142    xptr_t          root_xp;      // extended pointer on device waiting queue root
143
144    server = CURRENT_THREAD;
145
146    root_xp = XPTR( local_cxy , &chdev->wait_root );
147
148    // take the lock protecting the chdev waiting queue, before entering the
149        // infinite loop handling commands registered in this queue.
150    // In the loop, the lock is released during the handling of one command.
151
152    remote_spinlock_lock( XPTR( local_cxy , &chdev->wait_lock ) );
153
154    while( 1 )
155    {
156        // check waiting queue state
157        if( xlist_is_empty( root_xp ) ) // block and deschedule if waiting queue empty
158        {
159            // release lock
160            remote_spinlock_unlock( XPTR( local_cxy , &chdev->wait_lock ) );
161
162            // block and deschedule
163            thread_block( server , THREAD_BLOCKED_DEV_QUEUE );
164            sched_yield();
165        } 
166        else
167        {
168            // release lock
169            remote_spinlock_unlock( XPTR( local_cxy , &chdev->wait_lock ) );
170        }
171
172        // get extended pointer on first client thread
173        client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
174
175        // call driver command function to execute I/O operation
176        chdev->cmd( client_xp );
177       
178        // get client thread cluster and local pointer
179        client_cxy = GET_CXY( client_xp );
180        client_ptr = (thread_t *)GET_PTR( client_xp );
181
182        // take the lock, and remove the client thread from waiting queue
183        remote_spinlock_lock( XPTR( local_cxy , &chdev->wait_lock ) );
184        xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );
185
186    }  // end while
187
188}  // end chdev_sequencial_server()
189
Note: See TracBrowser for help on using the repository browser.