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>
23 using namespace lightOS
;
24 using namespace server
;
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);
46 if (libarch::in8(command_block_port
+ port_status
) != 0xFF)
49 // Select the master device
50 libarch::out8(command_block_port
+ port_device_lba3
, 0xA0 | (1 << 4));
55 if (libarch::in8(command_block_port
+ port_status
) != 0xFF)
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
,
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);
77 libarch::out8(mControlBase
+ port_control
, 0x00);
79 // Probe for a master device
80 if (check_device_presence(mCommandBase
,
87 // Probe for a slave device
88 if (check_device_presence(mCommandBase
,
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;
104 /*if (software_reset(false) == false)
106 cerr << "ide[" << miController << ":1]: failed to reset the device" << endl;
110 // Execute a NOP-Command
113 device_identification did
;
114 if (mDevice
[0] == unknown
)
115 if (identify_device(true, did
) == false)
117 if (mDevice
[1] == unknown
)
118 if (identify_device(false, did
) == false)
123 void controller::loop()
127 bool controller::check_device_presence(uint16_t command_block_port
,
128 uint16_t control_block_port
,
132 libarch::out8(command_block_port
+ port_device_lba3
, 0xA0 | ((master_dev
) ? 0 : (1 << 4)));
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)
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
)
165 bool controller::wait_irq()
167 // TODO: multiple wait messages not yet supported by the kernel
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
)
182 mPort
.unregister_event(libkernel::event::timer
);
183 mPort
.acknoledge_irq(mIntVector
);
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
)
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
205 // Clear SRST bit in the device control register
206 libarch::out8(mControlBase
+ port_control
, 0x00);
212 if (wait_status(BSY
, 0) == 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
)));
225 bool controller::identify_device(bool master_dev
,
226 device_identification
&id
)
228 return command_pio_in(master_dev
,
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
,
243 CMD_NO_SECTOR_COUNT
| CMD_NO_SECTOR_NUMBER
,
244 reinterpret_cast<void*>(&id
));
248 bool controller::write_command(bool master_dev
,
250 uint8_t sector_count
,
251 uint64_t sector_number
,
255 if (wait_status(BSY
, 0) == false)
257 DEVICE_ERROR("device busy");
265 // NOTE: We wait for 1ms
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
);
285 // TODO Does not, at least not with NOP on qemu
286 bool controller::command_no_data(bool master_dev
,
288 uint8_t sector_count
,
289 uint64_t sector_number
,
292 if (write_command(master_dev
,
299 // Wait for interrupt
300 if (wait_irq() == false)
302 DEVICE_ERROR("no interrupt");
307 if (wait_status(BSY
, 0) == false)
309 DEVICE_ERROR("device still busy");
314 uint8_t errCode
= read_errors();
317 DEVICE_ERROR("error register = 0x" << static_cast<size_t>(errCode
));
324 bool controller::command_pio_in(bool master_dev
,
326 uint8_t sector_count
,
327 uint64_t sector_number
,
331 if (write_command(master_dev
,
338 cout
<< "HERE" << endl
;
339 // Wait for interrupt
340 if (wait_irq() == false)
342 DEVICE_ERROR("no interrupt");
345 cout
<< "THERE" << endl
;
348 if (wait_status(BSY
, 0) == false)
350 DEVICE_ERROR("device still busy");
355 uint8_t errCode
= read_errors();
358 DEVICE_ERROR("error register = 0x" << static_cast<size_t>(errCode
));
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,
382 for (size_t i = 0;i < 4;i++)
384 if (mDevice[i] == unknown)
387 unsigned short port = mCommandBase[ctrl];
388 unsigned short port2 = mControlBase[ctrl];
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);
396 out8(port2 + reg_control, 0x08);
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;
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;
429 executePACKET(i, 12, Packet, 96, buffer, true);
431 else if (lba1 == 0 && lba2 == 0 && stat != 0)
433 cout << "ide[" << i << "]: ata" << endl;
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);
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);
466 bool ide::executePIO( size_t device,
475 size_t ctrl = device / 2;
476 unsigned short port = mCommandBase[ctrl];
477 //unsigned short port2 = mControlBase[ctrl];
480 if (waitBusy(device, false) == false)
482 cout << "ide[" << device << "]: device busy" << endl;
486 // Write device/head register (DEV bit only)
487 out8(port + reg_device_lba3, (device % 2) << 4);
491 // BSY = 0 && DRY = 1?
492 if ((waitBusy(device, false) || waitReady(device, true)) == false)
494 cout << "ide[" << device << "]: device not ready" << endl;
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
520 // Read the data (only if PIO in)
524 for (;i < (size / 2);i++)
527 if (getData(device, data) == false)
529 cout << "ide[" << device << "]: could not get the data (" << i << ")" << endl;
532 reinterpret_cast<unsigned short*>(buffer)[i] = data;
537 bool ide::executePACKET(size_t device,
545 size_t ctrl = device / 2;
546 unsigned short port = mCommandBase[ctrl];
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);
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);
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;
576 in8(port + reg_status);
579 for (size_t i=0;i < (packetsize / 2);i++)
582 data = reinterpret_cast<unsigned short*>(packet)[i];
583 if (sendData(device, data) == false)return false;
591 mPort[ctrl].wait(irq);
592 cout << "second irq fired" << endl;
595 in8(port + reg_status);
599 //TODO: Read the number of bytes from the ATAPI register?
600 for (size_t i=0;i < (size / 2);i++)
603 if (getData(device, data) == false)return false;
604 reinterpret_cast<unsigned short*>(buffer)[i] = data;
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
627 bool ide::read( size_t device,
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;