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/>.
29 #include <partition.h>
36 int lba28_drive_detect (int id
)
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
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
64 int lba28_drive_read (partition_t
*p
, unsigned addr
, unsigned char *buffer
)
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));
74 int ret
= inb (0x1F7);
75 //kprintf ("lba28: %x\n", ret);
76 while (!(ret
& 0x08)) {
77 //kprintf ("lba28: %x\n", ret);
82 unsigned short tmpword
;
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);
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
)
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));
107 while (!(inb (0x1F7) & 0x08)) // 0x08
110 unsigned short tmpword
;
114 for (idx
= 0; idx
< len
; idx
++) {
115 tmpword
= inw (0x1F0);
119 buffer
[i
] = (unsigned char) tmpword
;
121 buffer
[i
+ 1] = (unsigned char) (tmpword
>> 8);
127 int lba28_drive_write (partition_t
*p
, unsigned addr
, unsigned char *buffer
)
129 /* p->id = 0 for master device */
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));
138 while (!(inb (0x1F7) & 0x08))
141 unsigned short tmpword
;
144 for (idx
= 0; idx
< 256; idx
++) {
145 tmpword
= buffer
[idx
* 2] | (buffer
[idx
* 2 + 1] << 8);
146 outw (0x1F0, tmpword
);
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
)
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));
163 while (!(inb (0x1F7) & 0x08))
166 unsigned short tmpword
;
167 unsigned short l
= 0;
168 unsigned short h
= 0;
172 for (idx
= 0; idx
< 256; idx
++) {
180 h
= (buffer
[idx
* 2 + 1] << 8);
183 outw (0x1F0, tmpword
);
189 int lba28_drive_write_spec (partition_t
*p
, unsigned addr
, unsigned char *buffer
, unsigned len
, unsigned offset
)
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));
199 while (!(inb (0x1F7) & 0x08))
202 unsigned short tmpword
;
203 unsigned short l
= 0;
204 unsigned short h
= 0;
209 for (idx
= 0; idx
< 256; idx
++) {
216 l
= buffer
[i
-offset
];
219 if ((i
+1) < len
+offset
)
220 h
= buffer
[i
-offset
+1] << 8;
224 outw (0x1F0, tmpword
);
230 int lba48_drive_write (partition_t
*p
, unsigned long long addr
, unsigned char *buffer
)
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));
249 while (!(inb (0x1F7) & 0x08)) // 0x08
252 unsigned short tmpword
;
255 for (idx
= 0; idx
< 256; idx
++) {
256 tmpword
= buffer
[idx
* 2] | (buffer
[idx
* 2 + 1] << 8);
257 outw (0x1F0, tmpword
);
263 bool ide_acthandler (unsigned act
, partition_t
*p
, char *block
, char *more
, int n
)
274 lba28_drive_read (p
, n
, block
);
280 lba28_drive_write (p
, n
, block
);
286 //fs_t *fs = fs_detect (p);
291 unsigned l
= strlen (more
);
294 if (!p
->fs
->handler (FS_ACT_CHDIR
, more
, -1, 0))
298 while (dir[x].name[0] != '\0') {
299 printf ("slozka: '%s'\n", dir[x].name);
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
))
328 unsigned fl
= strlen (dir
[f
].name
);
331 unsigned attrib
= VFS_FILEATTR_MOUNTED
;
335 if (dir[f].name[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;
357 attrib
|= VFS_FILEATTR_READ
;
358 attrib
|= VFS_FILEATTR_WRITE
;
361 attrib
|= VFS_FILEATTR_HIDDEN
;
363 attrib
|= VFS_FILEATTR_SYSTEM
;
365 attrib
|= VFS_FILEATTR_DIR
;
367 attrib
|= VFS_FILEATTR_FILE
;
369 attrib
|= VFS_FILEATTR_BIN
;
373 if (dir
[f
].name
[i
] == ' ')
374 dir
[f
].name
[i
] = '\0';
381 vfs_list_add (dir
[f
].name
, attrib
, block
);
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);
394 fl
= strlen (dir
[f
].name
);
405 bool ata_acthandler (unsigned act
, char drive
, char *block
)
410 //if (dev_find ("/dev/hda") || dev_find ("/dev/hdb"))
412 if (kernel_attr
& KERNEL_NOATA
)
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
);
422 unsigned char c
= inb (0x71);
424 partition_add (dev
, 0);
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
);
436 unsigned char c
= inb (0x71);
439 partition_add (dev
, 0);
449 lba28_drive_read (drive, 0x01, n, block);
455 lba28_drive_write (drive, 0x01, n, block);