summaryrefslogtreecommitdiffstats
path: root/src/kernel/blk_drv/ll_rw_blk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/blk_drv/ll_rw_blk.c')
-rw-r--r--src/kernel/blk_drv/ll_rw_blk.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/kernel/blk_drv/ll_rw_blk.c b/src/kernel/blk_drv/ll_rw_blk.c
new file mode 100644
index 0000000..8931a81
--- /dev/null
+++ b/src/kernel/blk_drv/ll_rw_blk.c
@@ -0,0 +1,165 @@
1/*
2 * linux/kernel/blk_dev/ll_rw.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7/*
8 * This handles all read/write requests to block devices
9 */
10#include <errno.h>
11#include <linux/sched.h>
12#include <linux/kernel.h>
13#include <asm/system.h>
14
15#include "blk.h"
16
17/*
18 * The request-struct contains all necessary data
19 * to load a nr of sectors into memory
20 */
21struct request request[NR_REQUEST];
22
23/*
24 * used to wait on when there are no free requests
25 */
26struct task_struct * wait_for_request = NULL;
27
28/* blk_dev_struct is:
29 * do_request-address
30 * next-request
31 */
32struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
33 { NULL, NULL }, /* no_dev */
34 { NULL, NULL }, /* dev mem */
35 { NULL, NULL }, /* dev fd */
36 { NULL, NULL }, /* dev hd */
37 { NULL, NULL }, /* dev ttyx */
38 { NULL, NULL }, /* dev tty */
39 { NULL, NULL } /* dev lp */
40};
41
42static inline void lock_buffer(struct buffer_head * bh)
43{
44 cli();
45 while (bh->b_lock)
46 sleep_on(&bh->b_wait);
47 bh->b_lock=1;
48 sti();
49}
50
51static inline void unlock_buffer(struct buffer_head * bh)
52{
53 if (!bh->b_lock)
54 printk("ll_rw_block.c: buffer not locked\n\r");
55 bh->b_lock = 0;
56 wake_up(&bh->b_wait);
57}
58
59/*
60 * add-request adds a request to the linked list.
61 * It disables interrupts so that it can muck with the
62 * request-lists in peace.
63 */
64static void add_request(struct blk_dev_struct * dev, struct request * req)
65{
66 struct request * tmp;
67
68 req->next = NULL;
69 cli();
70 if (req->bh)
71 req->bh->b_dirt = 0;
72 if (!(tmp = dev->current_request)) {
73 dev->current_request = req;
74 sti();
75 (dev->request_fn)();
76 return;
77 }
78 for ( ; tmp->next ; tmp=tmp->next)
79 if ((IN_ORDER(tmp,req) ||
80 !IN_ORDER(tmp,tmp->next)) &&
81 IN_ORDER(req,tmp->next))
82 break;
83 req->next=tmp->next;
84 tmp->next=req;
85 sti();
86}
87
88static void make_request(int major,int rw, struct buffer_head * bh)
89{
90 struct request * req;
91 int rw_ahead;
92
93/* WRITEA/READA is special case - it is not really needed, so if the */
94/* buffer is locked, we just forget about it, else it's a normal read */
95 if ((rw_ahead = (rw == READA || rw == WRITEA))) {
96 if (bh->b_lock)
97 return;
98 if (rw == READA)
99 rw = READ;
100 else
101 rw = WRITE;
102 }
103 if (rw!=READ && rw!=WRITE)
104 panic("Bad block dev command, must be R/W/RA/WA");
105 lock_buffer(bh);
106 if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
107 unlock_buffer(bh);
108 return;
109 }
110repeat:
111/* we don't allow the write-requests to fill up the queue completely:
112 * we want some room for reads: they take precedence. The last third
113 * of the requests are only for reads.
114 */
115 if (rw == READ)
116 req = request+NR_REQUEST;
117 else
118 req = request+((NR_REQUEST*2)/3);
119/* find an empty request */
120 while (--req >= request)
121 if (req->dev<0)
122 break;
123/* if none found, sleep on new requests: check for rw_ahead */
124 if (req < request) {
125 if (rw_ahead) {
126 unlock_buffer(bh);
127 return;
128 }
129 sleep_on(&wait_for_request);
130 goto repeat;
131 }
132/* fill up the request-info, and add it to the queue */
133 req->dev = bh->b_dev;
134 req->cmd = rw;
135 req->errors=0;
136 req->sector = bh->b_blocknr<<1;
137 req->nr_sectors = 2;
138 req->buffer = bh->b_data;
139 req->waiting = NULL;
140 req->bh = bh;
141 req->next = NULL;
142 add_request(major+blk_dev,req);
143}
144
145void ll_rw_block(int rw, struct buffer_head * bh)
146{
147 unsigned int major;
148
149 if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
150 !(blk_dev[major].request_fn)) {
151 printk("Trying to read nonexistent block-device\n\r");
152 return;
153 }
154 make_request(major,rw,bh);
155}
156
157void blk_dev_init(void)
158{
159 int i;
160
161 for (i=0 ; i<NR_REQUEST ; i++) {
162 request[i].dev = -1;
163 request[i].next = NULL;
164 }
165}