]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dde/fbsd/examples/l4ata/src/reqloop.c
Inital import
[l4.git] / l4 / pkg / dde / fbsd / examples / l4ata / src / reqloop.c
1 #include <l4/dde/fbsd/dde.h>
2 #include <l4/dde/fbsd/bsd_dde.h>
3 #include <l4/dde/fbsd/ata.h>
4 #include <l4/bddf/timebase.h>
5 #include <l4/log/l4log.h>
6 #ifdef RTMON
7 #include <l4/rt_mon/histogram.h>
8 #endif
9
10 #include "types.h"
11
12 #define dbg_this 0
13
14 /**
15  * Helper function for registering a new physical device at bddf.
16  * Called after bddf disk initialization and before reading the partition
17  * tables. Should release the request loop running.
18  */
19 int l4ata_start_request_loop(device_handle_t device, void *arg) {
20         dad_disk_t *dsk = (dad_disk_t*) arg;
21         l4ata_disk_info_t *di = dad_l4ata_di(dsk);
22
23         // initialize l4ata_disk structure part 2
24         di->bddf_device = device;
25
26         // now request loop can start running
27         l4semaphore_up(&di->reqloop_start);
28
29         return 0;
30 }
31
32 /**
33  * Request loop function waiting for and handling bddf requests.
34  */
35 void l4ata_request_loop(void *arg) {
36         dad_disk_t *dsk = (dad_disk_t *)arg;
37         l4ata_disk_info_t *di = dad_l4ata_di(dsk);
38         bus_request_t *req;
39         unsigned bufsize;
40         struct ds_list_element *ds;
41         int dsi;
42
43         bsd_dde_prepare_thread("reqloop");
44
45         // wait until start_request_loop is called
46         l4semaphore_down(&di->reqloop_start);
47         
48         // enter loop
49         while (1) {
50                 char *typename;
51                 
52                 LOGd(dbg_this, "requesting next disk i/o task");
53
54                 req = bus_get_next_req(di->bddf_device);
55                 switch (req->type) {
56                         case REQ_TYPE_READ:
57                                 typename = "read";
58                                 break;
59                         case REQ_TYPE_WRITE:
60                                 typename = "write";
61                                 break;
62                         case REQ_TYPE_BARRIER:
63                                 typename = "barrier";
64                                 break;
65                         default:
66                                 typename = "unknown";
67                                 break;
68                 }
69
70                 // mark request handling start time for bddf
71                 req->start_time = bddf_get_timestamp();
72
73 #ifdef RTMON
74                 rt_mon_hist_start(rtm_request_setup_cpu);
75                 rt_mon_hist_start(rtm_request_setup_wall);
76 #endif
77
78                 // reject invalid requests
79                 if (req->start_sect < 0) {
80                         LOG("error: invalid request (start_sect=%d) for %s", req->start_sect, dsk->name);
81                         req->end_time = bddf_get_timestamp();
82                 bus_completed_req(di->bddf_device, req, 1);
83                         continue;
84                 }
85                 if ( (req->type!=REQ_TYPE_READ) && (req->type!=REQ_TYPE_WRITE) ) {
86                         LOG("error: unknown request type (type=%d) for %s", req->type, dsk->name);
87                         req->end_time = bddf_get_timestamp();
88                 bus_completed_req(di->bddf_device, req, 1);
89                         continue;
90                 }
91
92                 // test if sum(buffers) is big enough
93                 bufsize = 0;
94                 ds = (struct ds_list_element *)req->ds_list;
95                 for (dsi = req->ds_list_count; dsi; dsi--, ds++)
96                         bufsize += ds->ds_size;
97                 if (bufsize < req->sect_num*dsk->sectsize) {
98                         LOG("error: buffer too small (%d)\nfor request (%d=%d sects of %d bytes) for %s",
99                                         bufsize, req->sect_num*dsk->sectsize, req->sect_num, dsk->sectsize, dsk->name);
100                         req->end_time = bddf_get_timestamp();
101                 bus_completed_req(di->bddf_device, req, 1);
102                         continue;
103                 }
104
105                 // handle request
106                 l4ata_handle_request(dsk, req);
107
108 #ifdef RTMON
109                 rt_mon_hist_end(rtm_request_setup_cpu);
110                 rt_mon_hist_end(rtm_request_setup_wall);
111 #endif
112         }
113 }
114