Kernel 0.6.3; ZNFS filesystem is able to create file, directories, change directory...
[ZeXOS.git] / kernel / drivers / block / drive.c
bloba12f0ddf0705974e32e69d775f7790cd8c20808a
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <config.h>
23 #include <build.h>
25 #ifdef ARCH_i386
27 #include <system.h>
28 #include <mytypes.h>
29 #include <partition.h>
30 #include <dev.h>
31 #include <vfs.h>
32 #include <fs.h>
33 #include <arch/io.h>
36 int lba28_drive_detect (int id)
38 int tmpword;
40 switch (id) {
41 case 0:
42 outb (0x1F6, 0xA0); // use 0xB0 instead of 0xA0 to test the second drive on the controller
44 delay (200); // wait 1/250th of a second
46 tmpword = inb (0x1F7); // read the status port
47 if (tmpword & 0x40) // see if the busy bit is set
48 return 1;
50 return 0;
51 case 1:
52 outb (0x1F6, 0xB0); // use 0xB0 instead of 0xA0 to test the second drive on the controller
54 delay (200); // wait 1/250th of a second
56 tmpword = inb (0x1F7); // read the status port
57 if (tmpword & 0x40) // see if the busy bit is set
58 return 1;
60 return 0;
64 int lba28_drive_read (partition_t *p, unsigned addr, unsigned char *buffer)
66 outb (0x1F1, 0x00);
67 outb (0x1F2, (unsigned char) 0x01);
68 outb (0x1F3, (unsigned) addr);
69 outb (0x1F4, (unsigned) (addr >> 8));
70 outb (0x1F5, (unsigned) (addr >> 16));
71 outb (0x1F6, 0xE0 | (p->id << 4) | ((addr >> 24) & 0x0F));
72 outb (0x1F7, 0x20);
74 int ret = inb (0x1F7);
75 //kprintf ("lba28: %x\n", ret);
76 while (!(ret & 0x08)) {
77 //kprintf ("lba28: %x\n", ret);
78 ret = inb (0x1F7);
79 schedule ();
82 unsigned short tmpword;
83 // for read:
84 int idx;
85 for (idx = 0; idx < 256; idx ++) {
86 tmpword = inw (0x1F0);
87 buffer[idx * 2] = (unsigned char)tmpword;
88 buffer[idx * 2 + 1] = (unsigned char) (tmpword >> 8);
91 return 1;
94 /* NOTE: this code is buggy, because you need everytime go from 0 to 256 indexes (512 bytes) */
95 int lba28_drive_read_len (partition_t *p, unsigned addr, unsigned char *buffer, unsigned len)
97 outb (0x1F1, 0x00);
98 outb (0x1F2, (unsigned char) 0x01);
99 outb (0x1F3, (unsigned) addr);
100 outb (0x1F4, (unsigned) (addr >> 8));
101 outb (0x1F5, (unsigned) (addr >> 16));
102 outb (0x1F6, 0xE0 | (p->id << 4) | ((addr >> 24) & 0x0F));
103 outb (0x1F7, 0x20);
105 //usleep (1000);
107 while (!(inb (0x1F7) & 0x08)) // 0x08
108 schedule ();
110 unsigned short tmpword;
111 // for read:
112 int idx;
113 int i;
114 for (idx = 0; idx < len; idx ++) {
115 tmpword = inw (0x1F0);
116 i = (idx * 2);
118 if (i < len)
119 buffer[i] = (unsigned char) tmpword;
120 if (i+1 < len)
121 buffer[i + 1] = (unsigned char) (tmpword >> 8);
124 return 1;
127 int lba28_drive_write (partition_t *p, unsigned addr, unsigned char *buffer)
129 /* p->id = 0 for master device */
130 outb (0x1F1, 0x00);
131 outb (0x1F2, (unsigned char) 0x01);
132 outb (0x1F3, (unsigned) addr);
133 outb (0x1F4, (unsigned char) (addr >> 8));
134 outb (0x1F5, (unsigned char) (addr >> 16));
135 outb (0x1F6, 0xE0 | (p->id << 4) | ((addr >> 24) & 0x0F));
136 outb (0x1F7, 0x30);
138 while (!(inb (0x1F7) & 0x08))
139 schedule ();
141 unsigned short tmpword;
142 // for write:
143 int idx;
144 for (idx = 0; idx < 256; idx ++) {
145 tmpword = buffer[idx * 2] | (buffer[idx * 2 + 1] << 8);
146 outw (0x1F0, tmpword);
149 return 1;
152 /* NOTE: this code is buggy, because you need everytime go from 0 to 256 indexes (512 bytes) */
153 int lba28_drive_write_len (partition_t *p, unsigned addr, unsigned char *buffer, unsigned len)
155 outb (0x1F1, 0x00);
156 outb (0x1F2, (unsigned char) 0x01);
157 outb (0x1F3, (unsigned) addr);
158 outb (0x1F4, (unsigned char) (addr >> 8));
159 outb (0x1F5, (unsigned char) (addr >> 16));
160 outb (0x1F6, 0xE0 | (p->id << 4) | ((addr >> 24) & 0x0F));
161 outb (0x1F7, 0x30);
163 while (!(inb (0x1F7) & 0x08))
164 schedule ();
166 unsigned short tmpword;
167 unsigned short l = 0;
168 unsigned short h = 0;
169 // for write:
171 int idx;
172 for (idx = 0; idx < 256; idx ++) {
173 l = 0;
174 h = 0;
176 if ((idx*2) < len)
177 l = buffer[idx * 2];
179 if ((idx*2+1) < len)
180 h = (buffer[idx * 2 + 1] << 8);
182 tmpword = l | h;
183 outw (0x1F0, tmpword);
186 return 1;
189 int lba28_drive_write_spec (partition_t *p, unsigned addr, unsigned char *buffer, unsigned len, unsigned offset)
191 outb (0x1F1, 0x00);
192 outb (0x1F2, (unsigned char) 0x01);
193 outb (0x1F3, (unsigned) addr);
194 outb (0x1F4, (unsigned char) (addr >> 8));
195 outb (0x1F5, (unsigned char) (addr >> 16));
196 outb (0x1F6, 0xE0 | (p->id << 4) | ((addr >> 24) & 0x0F));
197 outb (0x1F7, 0x30);
199 while (!(inb (0x1F7) & 0x08))
200 schedule ();
202 unsigned short tmpword;
203 unsigned short l = 0;
204 unsigned short h = 0;
205 // for write:
207 int idx;
208 int i = 0;
209 for (idx = 0; idx < 256; idx ++) {
210 l = 0;
211 h = 0 << 8;
212 i = (idx*2);
214 if (i >= offset)
215 if (i < len+offset)
216 l = buffer[i-offset];
218 if ((i+1) >= offset)
219 if ((i+1) < len+offset)
220 h = buffer[i-offset+1] << 8;
223 tmpword = l | h;
224 outw (0x1F0, tmpword);
227 return 1;
230 int lba48_drive_write (partition_t *p, unsigned long long addr, unsigned char *buffer)
232 outb (0x1F1, 0x00);
233 outb (0x1F1, 0x00);
235 outb (0x1F2, 0x00);
236 outb (0x1F2, 0x01);
238 outb (0x1F3, (unsigned char) (addr >> 24));
239 outb (0x1F3, (unsigned char) addr);
240 outb (0x1F4, (unsigned char) (addr >> 32));
241 outb (0x1F4, (unsigned char) (addr >> 8));
242 outb (0x1F5, (unsigned char) (addr >> 40));
243 outb (0x1F5, (unsigned char) (addr >> 16));
245 outb (0x1F6, 0x40 | (p->id << 4));
247 outb (0x1F7, 0x34);
249 while (!(inb (0x1F7) & 0x08)) // 0x08
250 schedule ();
252 unsigned short tmpword;
253 // for write:
254 int idx;
255 for (idx = 0; idx < 256; idx ++) {
256 tmpword = buffer[idx * 2] | (buffer[idx * 2 + 1] << 8);
257 outw (0x1F0, tmpword);
260 return 1;
263 bool ide_acthandler (unsigned act, partition_t *p, char *block, char *more, int n)
265 switch (act) {
266 case DEV_ACT_INIT:
268 /* nothing */
269 return 1;
271 break;
272 case DEV_ACT_READ:
274 lba28_drive_read (p, n, block);
275 return 1;
277 break;
278 case DEV_ACT_WRITE:
280 lba28_drive_write (p, n, block);
281 return 1;
283 break;
284 case DEV_ACT_MOUNT:
286 //fs_t *fs = fs_detect (p);
287 int f = 0, t = 0;
289 curr_part = p;
291 unsigned l = strlen (more);
293 if (!l)
294 if (!p->fs->handler (FS_ACT_CHDIR, more, -1, 0))
295 return 0;
297 unsigned x = 0;
298 while (dir[x].name[0] != '\0') {
299 printf ("slozka: '%s'\n", dir[x].name);
300 x ++;
303 if (l) {
304 if (!strcmp (more, "."))
305 return p->fs->handler (FS_ACT_CHDIR, more, 0, l);
307 if (!strcmp (more, ".."))
308 return p->fs->handler (FS_ACT_CHDIR, more, 1, l);
310 while (strlen (dir[f].name)) {
311 //printf ("drive__: '%s' : %d | '%s'\n", dir[f].name, f, more);
312 if (!strncmp (dir[f].name, more, l)) {
313 if (!p->fs->handler (FS_ACT_CHDIR, more, f, l))
314 return 0;
316 t = 1;
317 break;
320 f ++;
323 if (!t)
324 return 0;
327 f = 0;
328 unsigned fl = strlen (dir[f].name);
330 while (fl) {
331 unsigned attrib = VFS_FILEATTR_MOUNTED;
333 /*unsigned x = fl;
334 while (x) {
335 if (dir[f].name[x] != ' ')
337 x --;
340 #define VFS_FILEATTR_FILE 0x1
341 #define VFS_FILEATTR_DIR 0x2
342 #define VFS_FILEATTR_HIDDEN 0x4
343 #define VFS_FILEATTR_SYSTEM 0x8
344 #define VFS_FILEATTR_BIN 0x10
345 #define VFS_FILEATTR_READ 0x20
346 #define VFS_FILEATTR_WRITE 0x40
348 case 0: dir[y].read=1; break;
349 case 1: dir[y].hidden=1; break;
350 case 2: dir[y].system=1; break;
351 case 3: dir[y].volume=1; break;
352 case 4: dir[y].dir=1; break;
353 case 5: dir[y].bin=1; break;
356 if (dir[f].read) {
357 attrib |= VFS_FILEATTR_READ;
358 attrib |= VFS_FILEATTR_WRITE;
360 if (dir[f].hidden)
361 attrib |= VFS_FILEATTR_HIDDEN;
362 if (dir[f].system)
363 attrib |= VFS_FILEATTR_SYSTEM;
364 if (dir[f].dir)
365 attrib |= VFS_FILEATTR_DIR;
366 else
367 attrib |= VFS_FILEATTR_FILE;
368 if (dir[f].bin)
369 attrib |= VFS_FILEATTR_BIN;
371 int i = 10;
372 while (i) {
373 if (dir[f].name[i] == ' ')
374 dir[f].name[i] = '\0';
375 else
376 break;
378 i --;
381 vfs_list_add (dir[f].name, attrib, block);
383 dir[y].read=0;
384 dir[y].hidden=0;
385 dir[y].system=0;
386 dir[y].volume=0;
387 dir[y].dir=0;
388 dir[y].bin=0;
391 //printf ("add: %s to %s | %d%d%d%d%d\n", dir[f].name, block, dir[f].read, dir[f].hidden, dir[f].system, dir[f].volume, dir[f].dir, dir[f].bin);
393 f ++;
394 fl = strlen (dir[f].name);
397 return 1;
399 break;
402 return 0;
405 bool ata_acthandler (unsigned act, char drive, char *block)
407 switch (act) {
408 case DEV_ACT_INIT:
410 //if (dev_find ("/dev/hda") || dev_find ("/dev/hdb"))
411 // return;
412 if (kernel_attr & KERNEL_NOATA)
413 return 0;
415 int res = 0;
417 if (lba28_drive_detect(0)) {
418 printf ("ATA controller found at 0x1F7, 0xA0\n");
419 dev_t *dev = (dev_t *) dev_register ("hda", "Drive controller", DEV_ATTR_BLOCK, (dev_handler_t *) &ide_acthandler);
421 outb (0x70, 0x1b);
422 unsigned char c = inb (0x71);
423 if (c != 255)
424 partition_add (dev, 0);
426 res ++;
429 if (lba28_drive_detect(1)) {
431 printf ("ATA controller found at 0x1F7, 0xB0\n");
432 dev_t *dev = (dev_t *) dev_register ("hdb", "Drive controller", DEV_ATTR_BLOCK, (dev_handler_t *) &ide_acthandler);
433 res ++;
435 outb (0x70, 0x24);
436 unsigned char c = inb (0x71);
438 if (c != 255)
439 partition_add (dev, 0);
441 res ++;
444 return res;
446 break;
447 /*case DEV_ACT_READ:
449 lba28_drive_read (drive, 0x01, n, block);
450 return 1;
452 break;
453 case DEV_ACT_WRITE:
455 lba28_drive_write (drive, 0x01, n, block);
456 return 1;
460 return 0;
462 #endif