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

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

Introduce the chdev_t structure in place of the device_t structure.

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