* renamed libkernel::port to libkernel::message_port
[lightOS.git] / server / ide / ide.cpp
blobe8bf596389a722874bed6c615f60e919e30d98c2
1 /*
2 lightOS server
3 Copyright (C) 2006-2009 Jörg Pfähler
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <libarch/ioport.hpp>
20 #include <lightOS/lightOS.hpp>
21 #include <iostream>
22 #include "ide.hpp"
23 using namespace lightOS;
24 using namespace server;
25 using namespace ide;
26 using namespace std;
28 using libkernel::message;
30 #define DEVICE_ERROR(x) cerr << "ide[" << miController << ":" << (master_dev ? "0" : "1") << "]: " << x << endl;
32 #define CMD_NO_SECTOR_NUMBER 0
33 #define CMD_SECTOR_NUMBER 1
34 #define CMD_NO_SECTOR_COUNT 0
35 #define CMD_SECTOR_COUNT 2
37 bool controller::is_present(uint16_t command_block_port,
38 uint16_t control_block_port)
40 // Select the master device
41 libarch::out8(command_block_port + port_device_lba3, 0xA0);
43 // TODO: Delay
45 // Floating Bus
46 if (libarch::in8(command_block_port + port_status) != 0xFF)
47 return true;
49 // Select the master device
50 libarch::out8(command_block_port + port_device_lba3, 0xA0 | (1 << 4));
52 // TODO: Delay
54 // Floating Bus
55 if (libarch::in8(command_block_port + port_status) != 0xFF)
56 return true;
57 return false;
60 bool controller::has_device(uint16_t command_block_port,
61 uint16_t control_block_port)
63 return check_device_presence(command_block_port, control_block_port, true) ||
64 check_device_presence(command_block_port, control_block_port, false);
67 controller::controller(size_t iController,
68 uint16_t command_block_port,
69 uint16_t control_block_port,
70 uint8_t irq)
71 : miController(iController), mCommandBase(command_block_port), mControlBase(control_block_port), mIrq(irq)
73 // Request the IRQ line
74 mIntVector = mPort.register_isa_irq(mIrq, 0);
76 // Enable interrupts
77 libarch::out8(mControlBase + port_control, 0x00);
79 // Probe for a master device
80 if (check_device_presence(mCommandBase,
81 mControlBase,
82 true) == true)
83 mDevice[0] = unknown;
84 else
85 mDevice[0] = none;
87 // Probe for a slave device
88 if (check_device_presence(mCommandBase,
89 mControlBase,
90 false) == true)
91 mDevice[1] = unknown;
92 else
93 mDevice[1] = none;
96 bool controller::init_devices()
98 // TODO Soft reset the devices
99 /*if (software_reset(true) == false)
101 cerr << "ide[" << miController << ":0]: failed to reset the device" << endl;
102 mDevice[0] = none;
104 /*if (software_reset(false) == false)
106 cerr << "ide[" << miController << ":1]: failed to reset the device" << endl;
107 mDevice[1] = none;
110 // Execute a NOP-Command
111 // TODO: Remove
113 device_identification did;
114 if (mDevice[0] == unknown)
115 if (identify_device(true, did) == false)
116 mDevice[0] = none;
117 if (mDevice[1] == unknown)
118 if (identify_device(false, did) == false)
119 mDevice[1] = none;
120 return true;
123 void controller::loop()
127 bool controller::check_device_presence(uint16_t command_block_port,
128 uint16_t control_block_port,
129 bool master_dev)
131 // Select the device
132 libarch::out8(command_block_port + port_device_lba3, 0xA0 | ((master_dev) ? 0 : (1 << 4)));
134 // TODO: Delay
136 // Put some values in the sector-count & the LBA0 register
137 libarch::out8(command_block_port + port_sector_count, 0x55);
138 libarch::out8(command_block_port + port_lba0, 0xAA);
140 // Read the values back
141 uint8_t sectorCount = libarch::in8(command_block_port + port_sector_count);
142 uint8_t sector = libarch::in8(command_block_port + port_lba0);
144 // Check for inconsistencies
145 if (sectorCount != 0x55 || sector != 0xAA)
146 return false;
147 return true;
150 // TODO: currently unused
152 void controller::select(bool master_dev)
154 // Set/Reset the DEV bit in the Device I/O register
155 libarch::out8(mCommandBase + port_device_lba3, 0xA0 | (master_dev ? 0x00 : 0x10));
158 bool controller::wait_status(uint8_t mask, uint8_t state)
160 while ((libarch::in8(mCommandBase + port_status) & mask) != state)
162 return true;
165 bool controller::wait_irq()
167 // TODO: multiple wait messages not yet supported by the kernel
168 // Register timer
169 mPort.register_event(libkernel::event::timer, 500);
170 message irq(libkernel::message_port::kernel, libkernel::message::event, libkernel::event::irq, mIntVector);
171 message msg(libkernel::message_port::kernel, libkernel::message::event, libkernel::event::timer);
173 // Wait for timer or irq
174 mPort.wait(msg, irq);
175 cout << msg.port() << ", " << msg.param1() << ", " << msg.param2() << ", " << msg.param3() << endl;
177 // timer elapsed first
178 if (msg.param1() == libkernel::event::timer)
179 return false;
181 // irq
182 mPort.unregister_event(libkernel::event::timer);
183 mPort.acknoledge_irq(mIntVector);
184 return true;
187 uint8_t controller::read_errors()
189 if ((libarch::in8(mCommandBase + port_status) & ERR_CHK) == 0)return 0;
190 return libarch::in8(mCommandBase + port_error);
193 // TODO: Does not work on other controllers than ide0
194 bool controller::software_reset(bool master_dev)
196 select(master_dev);
198 // Set the SRST bit in the device control register
199 libarch::out8(mControlBase + port_control, SRST);
201 // Wait for at least 5µs
202 // NOTE: We wait for 1ms
203 wait(1);
205 // Clear SRST bit in the device control register
206 libarch::out8(mControlBase + port_control, 0x00);
208 // Wait for 2ms
209 wait(2);
211 // Wait for BSY = 0
212 if (wait_status(BSY, 0) == false)
213 return false;
215 // Check the error register
216 if ((libarch::in8(mControlBase + port_status) & ERR_CHK) == ERR_CHK)
218 DEVICE_ERROR("error register = 0x" << hex << static_cast<size_t>(libarch::in8(mControlBase + port_error)));
219 return false;
222 return true;
225 bool controller::identify_device(bool master_dev,
226 device_identification &id)
228 return command_pio_in(master_dev,
229 0xEC,
232 CMD_NO_SECTOR_COUNT | CMD_NO_SECTOR_NUMBER,
233 reinterpret_cast<void*>(&id));
236 bool controller::identify_packet_device(bool master_dev,
237 device_identification &id)
239 return command_pio_in(master_dev,
240 0xA1,
243 CMD_NO_SECTOR_COUNT | CMD_NO_SECTOR_NUMBER,
244 reinterpret_cast<void*>(&id));
248 bool controller::write_command(bool master_dev,
249 uint8_t command,
250 uint8_t sector_count,
251 uint64_t sector_number,
252 uint8_t flags)
254 // Wait for BSY = 0
255 if (wait_status(BSY, 0) == false)
257 DEVICE_ERROR("device busy");
258 return false;
261 // Select the device
262 select(master_dev);
264 // Wait 400ns
265 // NOTE: We wait for 1ms
266 wait(1);
268 // Write sector count/number & device/head register
269 if ((flags & CMD_SECTOR_NUMBER) == CMD_SECTOR_NUMBER)
271 libarch::out8(mCommandBase + port_lba0, sector_number & 0xFF);
272 libarch::out8(mCommandBase + port_lba1, (sector_number >> 8) & 0xFF);
273 libarch::out8(mCommandBase + port_lba2, (sector_number >> 16) & 0xFF);
275 if ((flags & CMD_SECTOR_COUNT) == CMD_SECTOR_COUNT)
276 libarch::out8(mCommandBase + port_sector_count, sector_count);
277 if ((flags & CMD_SECTOR_NUMBER) == CMD_SECTOR_NUMBER)
278 libarch::out8(mCommandBase + port_device_lba3, 0xE0 | (master_dev ? 0x00 : 0x10) | ((sector_number >> 24) & 0x0F));
280 // Write the command code
281 libarch::out8(mCommandBase + port_command, command);
282 return true;
285 // TODO Does not, at least not with NOP on qemu
286 bool controller::command_no_data(bool master_dev,
287 uint8_t command,
288 uint8_t sector_count,
289 uint64_t sector_number,
290 uint8_t flags)
292 if (write_command(master_dev,
293 command,
294 sector_count,
295 sector_number,
296 flags) == false)
297 return false;
299 // Wait for interrupt
300 if (wait_irq() == false)
302 DEVICE_ERROR("no interrupt");
303 return false;
306 // BSY = 0?
307 if (wait_status(BSY, 0) == false)
309 DEVICE_ERROR("device still busy");
310 return false;
313 // Any errors?
314 uint8_t errCode = read_errors();
315 if (errCode != 0)
317 DEVICE_ERROR("error register = 0x" << static_cast<size_t>(errCode));
318 return false;
321 return true;
324 bool controller::command_pio_in(bool master_dev,
325 uint8_t command,
326 uint8_t sector_count,
327 uint64_t sector_number,
328 uint8_t flags,
329 void *data)
331 if (write_command(master_dev,
332 command,
333 sector_count,
334 sector_number,
335 flags) == false)
336 return false;
338 cout << "HERE" << endl;
339 // Wait for interrupt
340 if (wait_irq() == false)
342 DEVICE_ERROR("no interrupt");
343 return false;
345 cout << "THERE" << endl;
347 // BSY = 0?
348 if (wait_status(BSY, 0) == false)
350 DEVICE_ERROR("device still busy");
351 return false;
354 // Any errors?
355 uint8_t errCode = read_errors();
356 if (errCode != 0)
358 DEVICE_ERROR("error register = 0x" << static_cast<size_t>(errCode));
359 return false;
362 return true;
365 // TODO: command_PIO_in() chapter 11.5
366 // TODO: command_PIO_out() chapter 11.6
367 // TODO: command_packet() chapter 11.8
368 // TODO: identify_device() chapter 6.17
369 // TODO: identify_packet_decice() chapter 6.18
370 // TODO: ata_read_sector() chapter 6.36
371 // TODO: add LBA48 extension
372 // TODO: ata_write_sector() sector 6.68
373 // TODO: add LBA48 extension
375 /*ide::ide( unsigned short commandBase0,
376 unsigned short commandBase1,
377 unsigned short controlBase0,
378 unsigned short controlBase1,
379 unsigned char irq0,
380 unsigned char irq1)
382 for (size_t i = 0;i < 4;i++)
384 if (mDevice[i] == unknown)
386 size_t ctrl = i / 2;
387 unsigned short port = mCommandBase[ctrl];
388 unsigned short port2 = mControlBase[ctrl];
390 // Software reset
391 // TODO: some select_device function
392 if ((i % 2) == 0)out8(port + reg_device_lba3, 0);
393 else out8(port + reg_device_lba3, 1 << 4);
394 out8(port2 + reg_control, 0x0E);
395 //TODO: wait 400ns
396 out8(port2 + reg_control, 0x08);
397 //TODO: wait 400ns
399 if (waitBusy(i, false) == false)continue;
401 // No device present (master)?
402 // TODO: select_device again
403 if ((i % 2) == 0)out8(port + reg_device_lba3, 0);
404 else out8(port + reg_device_lba3, 1 << 4);
405 uint8_t sectorCount = in8(port + reg_sector_count);
406 uint8_t sector = in8(port + reg_lba0);
407 if (sectorCount == 0x01 && sector == 0x01)
409 unsigned char lba1 = in8(port + reg_lba1);
410 unsigned char lba2 = in8(port + reg_lba2);
411 unsigned char stat = in8(port + reg_status);
413 if (lba1 == 0x14 && lba2 == 0xEB)
415 cout << "ide[" << i << "]: atapi" << endl;
416 mDevice[i] = atapi;
417 executePIO(i, packet_identify, 0, 0, 512, reinterpret_cast<void*>(&mDeviceId[i]), true);
418 cout << "ide[" << i << "]: 0x" << hex << mDeviceId[i].atapi.config << endl;
420 uint8_t Packet[12];
421 uint8_t buffer[96];
422 Packet[0] = 0x12;
423 Packet[1] = 0;
424 Packet[2] = 0;
425 Packet[3] = 0;
426 Packet[4] = 0;
427 Packet[5] = 0;
429 executePACKET(i, 12, Packet, 96, buffer, true);
431 else if (lba1 == 0 && lba2 == 0 && stat != 0)
433 cout << "ide[" << i << "]: ata" << endl;
434 mDevice[i] = ata;
435 executePIO(i, identify, 0, 0, 512, reinterpret_cast<void*>(&mDeviceId[i]), true);
441 bool ide::getData(size_t device, unsigned short &buffer)
443 for (size_t i=0;i < timeout_data_ready;i++)
445 if ((in8(mControlBase[device / 2] + reg_alternative_status) & status_data_ready) == status_data_ready)
447 buffer = in16(mCommandBase[device / 2] + reg_data);
448 return true;
451 return false;
453 bool ide::sendData( size_t device,
454 unsigned short buffer)
456 for (size_t i=0;i < timeout_data_ready;i++)
458 if ((in8(mControlBase[device / 2] + reg_alternative_status) & status_data_ready) == status_data_ready)
460 out16(mCommandBase[device / 2] + reg_data, buffer);
461 return true;
464 return false;
466 bool ide::executePIO( size_t device,
467 command cmd,
468 size_t count,
469 size_t lba,
470 size_t size,
471 void *buffer,
472 bool in)
474 //TODO: PIO out
475 size_t ctrl = device / 2;
476 unsigned short port = mCommandBase[ctrl];
477 //unsigned short port2 = mControlBase[ctrl];
479 // BSY = 0?
480 if (waitBusy(device, false) == false)
482 cout << "ide[" << device << "]: device busy" << endl;
483 return false;
486 // Write device/head register (DEV bit only)
487 out8(port + reg_device_lba3, (device % 2) << 4);
489 //TODO: wait 400ns
491 // BSY = 0 && DRY = 1?
492 if ((waitBusy(device, false) || waitReady(device, true)) == false)
494 cout << "ide[" << device << "]: device not ready" << endl;
495 return false;
498 // Write sector count/number & device/head register
499 out8(port + reg_lba0, lba & 0xFF);
500 out8(port + reg_lba1, (lba >> 8) & 0xFF);
501 out8(port + reg_lba2, (lba >> 16) & 0xFF);
502 out8(port + reg_sector_count, count);
503 out8(port + reg_device_lba3, 0xE0 | ((device % 2) << 4) | ((lba >> 24) & 0x0F));
505 // Write the command code
506 out8(port + reg_command, cmd);
508 // Wait for interrupt
509 message irq(port::kernel, message::event, event::irq, mIrq[ctrl]);
510 mPort[ctrl].wait(irq);
512 // Read status register (Negate INTRQ)
513 if ((in8(port + reg_status) & status_error) == status_error)
515 cout << "ide[" << device << "]: error 0x" << hex << (unsigned int)in8(port + reg_error) << endl;
516 // TODO: Inspect the errorcode
517 return false;
520 // Read the data (only if PIO in)
521 if (in)
523 size_t i = 0;
524 for (;i < (size / 2);i++)
526 unsigned short data;
527 if (getData(device, data) == false)
529 cout << "ide[" << device << "]: could not get the data (" << i << ")" << endl;
530 return false;
532 reinterpret_cast<unsigned short*>(buffer)[i] = data;
535 return true;
537 bool ide::executePACKET(size_t device,
538 size_t packetsize,
539 void *packet,
540 size_t size,
541 void *buffer,
542 bool in)
544 //TODO: PIO out
545 size_t ctrl = device / 2;
546 unsigned short port = mCommandBase[ctrl];
548 // BSY = 0?
549 if (waitBusy(device, false) == false)return false;
551 // Write device/head register (DEV bit only)
552 out8(port + reg_device_lba3, (device % 2) << 4);
554 //TODO: wait 400ns
556 // BSY = 0 && DRY = 1?
557 if ((waitBusy(device, false) || waitReady(device, true)) == false)return false;
559 // Write sector count/number & device/head register
560 out8(port + reg_atapi_feature, 0); // Disable DMA & OVERLAP
561 out8(port + reg_atapi_bytecount0, size & 0xFF);
562 out8(port + reg_atapi_bytecount1, (size >> 8) & 0xFF);
563 out8(port + reg_device_lba3, ((device % 2) << 4));
565 // Write the command code
566 out8(port + reg_command, ide::packet);
568 // Wait for irq
569 cout << "waiting" << endl;
570 message irq(port::kernel, message::event, event::irq, mIrq[ctrl]);
571 mPort[ctrl].wait(irq);
573 cout << "first irq fired" << endl;
575 // Negate INTRQ
576 in8(port + reg_status);
578 // Send Packet
579 for (size_t i=0;i < (packetsize / 2);i++)
581 unsigned short data;
582 data = reinterpret_cast<unsigned short*>(packet)[i];
583 if (sendData(device, data) == false)return false;
586 //TODO: wait 400ns
588 if (size != 0)
590 // Wait for irq
591 mPort[ctrl].wait(irq);
592 cout << "second irq fired" << endl;
594 // Negate INTRQ
595 in8(port + reg_status);
597 if (in)
599 //TODO: Read the number of bytes from the ATAPI register?
600 for (size_t i=0;i < (size / 2);i++)
602 unsigned short data;
603 if (getData(device, data) == false)return false;
604 reinterpret_cast<unsigned short*>(buffer)[i] = data;
607 else
609 //TODO: write data
613 // Wait for irq
614 mPort[ctrl].wait(irq);
615 cout << "third irq fired" << endl;
617 // Read status register (Negate INTRQ)
618 if ((in8(port + reg_status) & status_error) == status_error)
620 //cout << "ide[" << device << "]: error 0x" << hex << (unsigned int)in8(mControlBase[ctrl] + reg_error) << endl;
621 // TODO: Inspect the errorcode
622 return false;
625 return true;
627 bool ide::read( size_t device,
628 size_t blocknumber,
629 size_t blockcount,
630 void *buffer)
632 if (mDevice[device] == ata)
634 return executePIO(device, read_sector, blockcount, blocknumber, blockcount * 512, buffer, true);
636 cerr << "ide: read not supported for this device type" << endl;
637 return false;
639 ide::~ide()