[176f133] | 1 | /*===============================================================*\ |
---|
| 2 | | Project: RTEMS PC386 IDE harddisc driver | |
---|
| 3 | +-----------------------------------------------------------------+ |
---|
| 4 | | File: ide.c | |
---|
| 5 | +-----------------------------------------------------------------+ |
---|
| 6 | | Copyright (c) 2003 IMD | |
---|
| 7 | | Ingenieurbuero fuer Microcomputertechnik Th. Doerfler | |
---|
| 8 | | <Thomas.Doerfler@imd-systems.de> | |
---|
| 9 | | all rights reserved | |
---|
| 10 | +-----------------------------------------------------------------+ |
---|
| 11 | | this file contains the BSP layer for IDE access below the | |
---|
| 12 | | libchip IDE harddisc driver | |
---|
| 13 | | based on a board specific driver from | |
---|
| 14 | | Eugeny S. Mints, Oktet | |
---|
| 15 | | | |
---|
| 16 | | The license and distribution terms for this file may be | |
---|
| 17 | | found in the file LICENSE in this distribution or at | |
---|
[c499856] | 18 | | http://www.rtems.org/license/LICENSE. | |
---|
[176f133] | 19 | | | |
---|
| 20 | +-----------------------------------------------------------------+ |
---|
| 21 | | date history ID | |
---|
| 22 | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
---|
| 23 | | 01.14.03 creation doe | |
---|
| 24 | \*===============================================================*/ |
---|
| 25 | |
---|
| 26 | #include <rtems.h> |
---|
| 27 | #include <bsp.h> |
---|
| 28 | #include <libchip/ide_ctrl.h> |
---|
| 29 | #include <libchip/ide_ctrl_cfg.h> |
---|
| 30 | #include <libchip/ide_ctrl_io.h> |
---|
| 31 | |
---|
[c1fc5d4] | 32 | #define ATA_SECTOR_SIZE (512) |
---|
| 33 | |
---|
| 34 | /* |
---|
| 35 | * Use during initialisation. |
---|
| 36 | */ |
---|
| 37 | extern void Wait_X_ms(unsigned int msecs); |
---|
| 38 | |
---|
[57be444e] | 39 | bool pc386_ide_show; |
---|
[c1fc5d4] | 40 | uint32_t pc386_ide_timeout; |
---|
| 41 | |
---|
| 42 | #define PC386_IDE_DEBUG_OUT 0 |
---|
| 43 | |
---|
| 44 | #if PC386_IDE_DEBUG_OUT |
---|
| 45 | bool pc386_ide_trace; |
---|
| 46 | #define pc386_ide_printk if (pc386_ide_trace) printk |
---|
| 47 | #endif |
---|
| 48 | |
---|
| 49 | #define PC386_IDE_PROBE_TIMEOUT (500) |
---|
| 50 | #define PC386_IDE_PRESTART_TIMEOUT (1000) |
---|
| 51 | #define PC386_IDE_TASKING_TIMEOUT (2000) |
---|
| 52 | |
---|
| 53 | /* |
---|
| 54 | * Prestart sleep using a calibrated timing loop. |
---|
| 55 | */ |
---|
| 56 | static void pc386_ide_prestart_sleep (void) |
---|
| 57 | { |
---|
| 58 | Wait_X_ms (10); |
---|
| 59 | } |
---|
| 60 | |
---|
| 61 | /* |
---|
| 62 | * Once tasking has started we use a task sleep. |
---|
| 63 | */ |
---|
| 64 | static void pc386_ide_tasking_sleep (void) |
---|
| 65 | { |
---|
[88c74ab] | 66 | rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (10000) ? |
---|
| 67 | RTEMS_MICROSECONDS_TO_TICKS (10000) : 1); |
---|
[c1fc5d4] | 68 | } |
---|
| 69 | |
---|
| 70 | typedef void (*pc386_ide_sleeper)(void); |
---|
| 71 | |
---|
| 72 | static void pc386_ide_sleep (pc386_ide_sleeper sleeper) |
---|
| 73 | { |
---|
| 74 | sleeper (); |
---|
| 75 | } |
---|
[57be444e] | 76 | |
---|
[c1fc5d4] | 77 | static void wait(volatile uint32_t loops) |
---|
| 78 | { |
---|
| 79 | while (loops) |
---|
| 80 | loops--; |
---|
| 81 | } |
---|
[1c5ebc5] | 82 | |
---|
[c1fc5d4] | 83 | static bool pc386_ide_status_busy (uint32_t port, |
---|
| 84 | volatile uint32_t timeout, |
---|
| 85 | uint8_t* status_val, |
---|
| 86 | pc386_ide_sleeper sleeper) |
---|
[1c5ebc5] | 87 | { |
---|
[c1fc5d4] | 88 | volatile uint8_t status; |
---|
| 89 | int polls; |
---|
[359e537] | 90 | |
---|
[1c5ebc5] | 91 | do |
---|
| 92 | { |
---|
[c1fc5d4] | 93 | polls = 500; |
---|
| 94 | while (polls) |
---|
| 95 | { |
---|
| 96 | inport_byte (port + IDE_REGISTER_STATUS, status); |
---|
| 97 | if ((status & IDE_REGISTER_STATUS_BSY) == 0) |
---|
| 98 | { |
---|
| 99 | *status_val = status; |
---|
| 100 | return true; |
---|
| 101 | } |
---|
| 102 | polls--; |
---|
| 103 | } |
---|
[1c5ebc5] | 104 | |
---|
| 105 | if (timeout) |
---|
| 106 | { |
---|
| 107 | timeout--; |
---|
[c1fc5d4] | 108 | pc386_ide_sleep (sleeper); |
---|
[1c5ebc5] | 109 | } |
---|
| 110 | } |
---|
| 111 | while (timeout); |
---|
| 112 | |
---|
[c1fc5d4] | 113 | *status_val = status; |
---|
[1c5ebc5] | 114 | return false; |
---|
| 115 | } |
---|
| 116 | |
---|
[c1fc5d4] | 117 | static bool pc386_ide_status_data_ready (uint32_t port, |
---|
| 118 | volatile uint32_t timeout, |
---|
| 119 | uint8_t* status_val, |
---|
| 120 | pc386_ide_sleeper sleeper) |
---|
[1c5ebc5] | 121 | { |
---|
[c1fc5d4] | 122 | volatile uint8_t status; |
---|
| 123 | int polls; |
---|
[359e537] | 124 | |
---|
[1c5ebc5] | 125 | do |
---|
| 126 | { |
---|
[c1fc5d4] | 127 | polls = 1000; |
---|
| 128 | while (polls) |
---|
| 129 | { |
---|
| 130 | inport_byte (port + IDE_REGISTER_STATUS, status); |
---|
[359e537] | 131 | |
---|
[c1fc5d4] | 132 | if (((status & IDE_REGISTER_STATUS_BSY) == 0) && |
---|
| 133 | (status & IDE_REGISTER_STATUS_DRQ)) |
---|
| 134 | { |
---|
| 135 | *status_val = status; |
---|
| 136 | return true; |
---|
| 137 | } |
---|
| 138 | |
---|
| 139 | polls--; |
---|
| 140 | } |
---|
[1c5ebc5] | 141 | |
---|
| 142 | if (timeout) |
---|
| 143 | { |
---|
| 144 | timeout--; |
---|
[c1fc5d4] | 145 | pc386_ide_sleep (sleeper); |
---|
[1c5ebc5] | 146 | } |
---|
| 147 | } |
---|
| 148 | while (timeout); |
---|
| 149 | |
---|
[c1fc5d4] | 150 | *status_val = status; |
---|
[1c5ebc5] | 151 | return false; |
---|
| 152 | } |
---|
| 153 | |
---|
[176f133] | 154 | /* |
---|
| 155 | * support functions for IDE harddisk IF |
---|
| 156 | */ |
---|
| 157 | /*=========================================================================*\ |
---|
| 158 | | Function: | |
---|
| 159 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 160 | static bool pc386_ide_probe |
---|
[176f133] | 161 | ( |
---|
| 162 | /*-------------------------------------------------------------------------*\ |
---|
| 163 | | Purpose: | |
---|
| 164 | | This function should probe, whether a IDE disk is available | |
---|
| 165 | +---------------------------------------------------------------------------+ |
---|
| 166 | | Input Parameters: | |
---|
| 167 | \*-------------------------------------------------------------------------*/ |
---|
| 168 | int minor |
---|
| 169 | ) |
---|
| 170 | /*-------------------------------------------------------------------------*\ |
---|
| 171 | | Return Value: | |
---|
[39d08d55] | 172 | | true, when flash disk available | |
---|
[176f133] | 173 | \*=========================================================================*/ |
---|
| 174 | { |
---|
[39d08d55] | 175 | bool ide_card_plugged = true; /* assume: we have a disk here */ |
---|
[176f133] | 176 | |
---|
| 177 | return ide_card_plugged; |
---|
| 178 | } |
---|
| 179 | |
---|
| 180 | /*=========================================================================*\ |
---|
| 181 | | Function: | |
---|
| 182 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 183 | static void pc386_ide_initialize |
---|
[176f133] | 184 | ( |
---|
| 185 | /*-------------------------------------------------------------------------*\ |
---|
[4c39764] | 186 | | Purpose: | |
---|
| 187 | | initialize IDE access | |
---|
| 188 | +---------------------------------------------------------------------------+ |
---|
| 189 | | Input Parameters: | |
---|
| 190 | \*-------------------------------------------------------------------------*/ |
---|
| 191 | int minor /* controller minor number */ |
---|
[176f133] | 192 | ) |
---|
| 193 | /*-------------------------------------------------------------------------*\ |
---|
[4c39764] | 194 | | Return Value: | |
---|
| 195 | | <none> | |
---|
| 196 | \*=========================================================================*/ |
---|
[176f133] | 197 | { |
---|
[57be444e] | 198 | uint32_t port = IDE_Controller_Table[minor].port1; |
---|
| 199 | uint8_t dev = 0; |
---|
| 200 | |
---|
| 201 | if (pc386_ide_show) |
---|
| 202 | printk("IDE%d: port base: %04x\n", minor, port); |
---|
| 203 | |
---|
| 204 | outport_byte(port+IDE_REGISTER_DEVICE_HEAD, |
---|
| 205 | (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0); |
---|
| 206 | wait(10000); |
---|
| 207 | outport_byte(port+IDE_REGISTER_DEVICE_CONTROL, |
---|
| 208 | IDE_REGISTER_DEVICE_CONTROL_SRST | IDE_REGISTER_DEVICE_CONTROL_nIEN); |
---|
| 209 | wait(10000); |
---|
| 210 | outport_byte(port+IDE_REGISTER_DEVICE_CONTROL, |
---|
| 211 | IDE_REGISTER_DEVICE_CONTROL_nIEN); |
---|
| 212 | wait(10000); |
---|
| 213 | |
---|
| 214 | for (dev = 0; dev < 2; dev++) |
---|
| 215 | { |
---|
[4c39764] | 216 | uint16_t capabilities = 0; |
---|
[57be444e] | 217 | uint32_t byte; |
---|
| 218 | uint8_t status; |
---|
| 219 | uint8_t error; |
---|
| 220 | uint8_t cyllsb; |
---|
| 221 | uint8_t cylmsb; |
---|
| 222 | const char* label = dev ? " slave" : "master"; |
---|
[c1fc5d4] | 223 | int max_multiple_sectors = 0; |
---|
| 224 | int cur_multiple_sectors = 0; |
---|
| 225 | uint32_t cylinders = 0; |
---|
| 226 | uint32_t heads = 0; |
---|
| 227 | uint32_t sectors = 0; |
---|
[4c39764] | 228 | uint32_t lba_sectors = 0; |
---|
[57be444e] | 229 | char model_number[41]; |
---|
| 230 | char* p = &model_number[0]; |
---|
[4c39764] | 231 | bool data_ready; |
---|
[359e537] | 232 | |
---|
[4977f07e] | 233 | (void) cur_multiple_sectors; /* avoid set but not used warning */ |
---|
| 234 | |
---|
[57be444e] | 235 | memset(model_number, 0, sizeof(model_number)); |
---|
| 236 | |
---|
| 237 | outport_byte(port+IDE_REGISTER_DEVICE_HEAD, |
---|
| 238 | (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0); |
---|
| 239 | /* |
---|
[4c39764] | 240 | outport_byte(port+IDE_REGISTER_SECTOR_NUMBER, |
---|
| 241 | (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | IDE_REGISTER_LBA3_L); |
---|
[57be444e] | 242 | */ |
---|
| 243 | |
---|
| 244 | outport_byte(port+IDE_REGISTER_COMMAND, 0x00); |
---|
[359e537] | 245 | |
---|
[c1fc5d4] | 246 | if (!pc386_ide_status_busy (port, PC386_IDE_PROBE_TIMEOUT, |
---|
| 247 | &status, pc386_ide_prestart_sleep)) |
---|
[57be444e] | 248 | continue; |
---|
[359e537] | 249 | |
---|
[57be444e] | 250 | inport_byte(port+IDE_REGISTER_STATUS, status); |
---|
| 251 | inport_byte(port+IDE_REGISTER_ERROR, error); |
---|
| 252 | inport_byte(port+IDE_REGISTER_CYLINDER_LOW, cyllsb); |
---|
| 253 | inport_byte(port+IDE_REGISTER_CYLINDER_HIGH, cylmsb); |
---|
| 254 | |
---|
| 255 | if (pc386_ide_show) |
---|
| 256 | { |
---|
| 257 | printk("IDE%d:%s: status=%02x\n", minor, label, status); |
---|
| 258 | printk("IDE%d:%s: error=%02x\n", minor, label, error); |
---|
| 259 | printk("IDE%d:%s: cylinder-low=%02x\n", minor, label, cyllsb); |
---|
| 260 | printk("IDE%d:%s: cylinder-high=%02x\n", minor, label, cylmsb); |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | outport_byte(port+IDE_REGISTER_COMMAND, 0xec); |
---|
| 264 | |
---|
[c1fc5d4] | 265 | if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT, |
---|
| 266 | &status, pc386_ide_prestart_sleep)) |
---|
[57be444e] | 267 | { |
---|
| 268 | if (pc386_ide_show) |
---|
| 269 | printk("IDE%d:%s: device busy: %02x\n", minor, label, status); |
---|
| 270 | continue; |
---|
| 271 | } |
---|
[c1fc5d4] | 272 | |
---|
[4c39764] | 273 | data_ready = pc386_ide_status_data_ready (port, |
---|
| 274 | 250, |
---|
| 275 | &status, |
---|
| 276 | pc386_ide_prestart_sleep); |
---|
[57be444e] | 277 | |
---|
[4c39764] | 278 | if (status & IDE_REGISTER_STATUS_ERR) |
---|
| 279 | { |
---|
| 280 | inport_byte(port+IDE_REGISTER_ERROR, error); |
---|
| 281 | if (error != 4) |
---|
| 282 | { |
---|
| 283 | if (pc386_ide_show) |
---|
| 284 | printk("IDE%d:%s: error=%04x\n", minor, label, error); |
---|
| 285 | continue; |
---|
| 286 | } |
---|
| 287 | /* |
---|
| 288 | * The device is an ATAPI device. |
---|
| 289 | */ |
---|
| 290 | outport_byte(port+IDE_REGISTER_COMMAND, 0xa1); |
---|
[c1fc5d4] | 291 | data_ready = pc386_ide_status_data_ready (port, |
---|
| 292 | 250, |
---|
| 293 | &status, |
---|
| 294 | pc386_ide_prestart_sleep); |
---|
[4c39764] | 295 | } |
---|
[57be444e] | 296 | |
---|
[4c39764] | 297 | if (!data_ready) |
---|
| 298 | continue; |
---|
[359e537] | 299 | |
---|
[4c39764] | 300 | byte = 0; |
---|
| 301 | while (byte < 512) |
---|
| 302 | { |
---|
| 303 | uint16_t word; |
---|
[359e537] | 304 | |
---|
[c1fc5d4] | 305 | if (pc386_ide_show && ((byte % 16) == 0)) |
---|
| 306 | printk("\n %04x : ", byte); |
---|
[359e537] | 307 | |
---|
[57be444e] | 308 | inport_word(port+IDE_REGISTER_DATA, word); |
---|
| 309 | |
---|
| 310 | if (pc386_ide_show) |
---|
| 311 | printk ("%04x ", word); |
---|
| 312 | |
---|
[c1fc5d4] | 313 | if (byte == 2) |
---|
| 314 | cylinders = word; |
---|
| 315 | if (byte == 6) |
---|
| 316 | heads = word; |
---|
| 317 | if (byte == 12) |
---|
| 318 | sectors = word; |
---|
[359e537] | 319 | |
---|
[57be444e] | 320 | if (byte >= 54 && byte < (54 + 40)) |
---|
| 321 | { |
---|
| 322 | *p = word >> 8; |
---|
| 323 | p++; |
---|
| 324 | *p = word; |
---|
| 325 | p++; |
---|
| 326 | } |
---|
[c1fc5d4] | 327 | |
---|
| 328 | if (byte == (47 * 2)) |
---|
| 329 | max_multiple_sectors = word & 0xff; |
---|
[359e537] | 330 | |
---|
[4c39764] | 331 | if (byte == (49 * 2)) |
---|
| 332 | capabilities = word; |
---|
[359e537] | 333 | |
---|
[c1fc5d4] | 334 | if (byte == (59 * 2)) |
---|
| 335 | { |
---|
| 336 | if (word & (1 << 8)) |
---|
| 337 | cur_multiple_sectors = word & 0xff; |
---|
| 338 | } |
---|
[4c39764] | 339 | |
---|
| 340 | if (byte == (60 * 2)) |
---|
| 341 | lba_sectors = word; |
---|
| 342 | if (byte == (61 * 2)) |
---|
| 343 | lba_sectors |= word << 16; |
---|
[359e537] | 344 | |
---|
[57be444e] | 345 | byte += 2; |
---|
| 346 | } |
---|
[359e537] | 347 | |
---|
[57be444e] | 348 | if (pc386_ide_show) |
---|
| 349 | printk("\nbytes read = %d\n", byte); |
---|
| 350 | |
---|
| 351 | if (p != &model_number[0]) |
---|
[c1fc5d4] | 352 | { |
---|
| 353 | uint32_t size; |
---|
| 354 | uint32_t left; |
---|
| 355 | uint32_t right; |
---|
| 356 | char units; |
---|
| 357 | |
---|
[4c39764] | 358 | if (capabilities & (1 << 9)) |
---|
| 359 | size = lba_sectors; |
---|
| 360 | else |
---|
| 361 | size = cylinders * heads * sectors; |
---|
| 362 | |
---|
| 363 | size /= 2; |
---|
[359e537] | 364 | |
---|
[c1fc5d4] | 365 | if (size > (1024 * 1024)) |
---|
| 366 | { |
---|
| 367 | size = (size * 10) / (1000 * 1000); |
---|
| 368 | units = 'G'; |
---|
| 369 | } |
---|
| 370 | else if (size > 1024) |
---|
| 371 | { |
---|
| 372 | size = (size * 10) / 1000; |
---|
| 373 | units = 'M'; |
---|
| 374 | } |
---|
| 375 | else |
---|
| 376 | { |
---|
| 377 | size = size * 10; |
---|
| 378 | units = 'K'; |
---|
| 379 | } |
---|
| 380 | |
---|
| 381 | left = size / 10; |
---|
| 382 | right = size % 10; |
---|
[359e537] | 383 | |
---|
[c1fc5d4] | 384 | p--; |
---|
| 385 | while (*p == ' ') |
---|
| 386 | { |
---|
| 387 | *p = '\0'; |
---|
| 388 | p--; |
---|
| 389 | } |
---|
| 390 | |
---|
| 391 | printk("IDE%d:%s:%s, %u.%u%c (%u/%u/%u), max blk size:%d\n", |
---|
| 392 | minor, label, model_number, left, right, units, |
---|
| 393 | heads, cylinders, sectors, max_multiple_sectors * 512); |
---|
| 394 | } |
---|
[359e537] | 395 | |
---|
[c1fc5d4] | 396 | #if IDE_CLEAR_MULTI_SECTOR_COUNT |
---|
| 397 | if (max_multiple_sectors) |
---|
| 398 | { |
---|
| 399 | outport_byte(port+IDE_REGISTER_SECTOR_COUNT, 0); |
---|
| 400 | outport_byte(port+IDE_REGISTER_COMMAND, 0xc6); |
---|
| 401 | |
---|
| 402 | if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT, |
---|
| 403 | &status, pc386_ide_prestart_sleep)) |
---|
| 404 | { |
---|
| 405 | if (pc386_ide_show) |
---|
| 406 | printk("IDE%d:%s: device busy: %02x\n", minor, label, status); |
---|
| 407 | continue; |
---|
| 408 | } |
---|
| 409 | |
---|
| 410 | inport_byte(port+IDE_REGISTER_STATUS, status); |
---|
| 411 | if (status & IDE_REGISTER_STATUS_ERR) |
---|
| 412 | { |
---|
| 413 | inport_byte(port+IDE_REGISTER_ERROR, error); |
---|
| 414 | if (error & IDE_REGISTER_ERROR_ABRT) |
---|
| 415 | printk("IDE%d:%s: disable multiple failed\n", minor, label); |
---|
| 416 | else |
---|
| 417 | printk("IDE%d:%s: unknown error on disable multiple: %02x\n", |
---|
| 418 | minor, label, error); |
---|
| 419 | } |
---|
| 420 | } |
---|
| 421 | #endif |
---|
[359e537] | 422 | |
---|
[c1fc5d4] | 423 | outport_byte(port+IDE_REGISTER_DEVICE_CONTROL, |
---|
| 424 | IDE_REGISTER_DEVICE_CONTROL_nIEN); |
---|
| 425 | wait(10000); |
---|
[57be444e] | 426 | } |
---|
[c1fc5d4] | 427 | |
---|
| 428 | pc386_ide_timeout = PC386_IDE_TASKING_TIMEOUT; |
---|
[359e537] | 429 | |
---|
[176f133] | 430 | /* |
---|
| 431 | * FIXME: enable interrupts, if needed |
---|
| 432 | */ |
---|
| 433 | } |
---|
| 434 | |
---|
| 435 | /*=========================================================================*\ |
---|
| 436 | | Function: | |
---|
| 437 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 438 | static void pc386_ide_read_reg |
---|
[176f133] | 439 | ( |
---|
| 440 | /*-------------------------------------------------------------------------*\ |
---|
| 441 | | Purpose: | |
---|
| 442 | | read a IDE controller register | |
---|
| 443 | +---------------------------------------------------------------------------+ |
---|
| 444 | | Input Parameters: | |
---|
| 445 | \*-------------------------------------------------------------------------*/ |
---|
| 446 | int minor, /* controller minor number */ |
---|
| 447 | int reg, /* register index to access */ |
---|
| 448 | uint16_t *value /* ptr to return value location */ |
---|
| 449 | ) |
---|
| 450 | /*-------------------------------------------------------------------------*\ |
---|
| 451 | | Return Value: | |
---|
| 452 | | <none> | |
---|
| 453 | \*=========================================================================*/ |
---|
| 454 | { |
---|
| 455 | uint32_t port = IDE_Controller_Table[minor].port1; |
---|
| 456 | uint8_t bval1,bval2; |
---|
| 457 | |
---|
| 458 | if (reg == IDE_REGISTER_DATA_WORD) { |
---|
| 459 | inport_byte(port+reg, bval1); |
---|
| 460 | inport_byte(port+reg+1, bval2); |
---|
| 461 | *value = bval1 + (bval2 << 8); |
---|
| 462 | } |
---|
| 463 | else { |
---|
| 464 | inport_byte(port+reg, bval1); |
---|
| 465 | *value = bval1; |
---|
| 466 | } |
---|
[c1fc5d4] | 467 | #if PC386_IDE_DEBUG_OUT |
---|
| 468 | pc386_ide_printk("pc386_ide_read_reg (0x%x)=0x%x\r\n",reg,*value & 0xff); |
---|
[176f133] | 469 | #endif |
---|
| 470 | } |
---|
| 471 | |
---|
| 472 | /*=========================================================================*\ |
---|
| 473 | | Function: | |
---|
| 474 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 475 | static void pc386_ide_write_reg |
---|
[176f133] | 476 | ( |
---|
| 477 | /*-------------------------------------------------------------------------*\ |
---|
| 478 | | Purpose: | |
---|
| 479 | | write a IDE controller register | |
---|
| 480 | +---------------------------------------------------------------------------+ |
---|
| 481 | | Input Parameters: | |
---|
| 482 | \*-------------------------------------------------------------------------*/ |
---|
| 483 | int minor, /* controller minor number */ |
---|
| 484 | int reg, /* register index to access */ |
---|
| 485 | uint16_t value /* value to write */ |
---|
| 486 | ) |
---|
| 487 | /*-------------------------------------------------------------------------*\ |
---|
| 488 | | Return Value: | |
---|
| 489 | | <none> | |
---|
| 490 | \*=========================================================================*/ |
---|
| 491 | { |
---|
| 492 | uint32_t port = IDE_Controller_Table[minor].port1; |
---|
| 493 | |
---|
[c1fc5d4] | 494 | #if PC386_IDE_DEBUG_OUT |
---|
| 495 | pc386_ide_printk("pc386_ide_write_reg(0x%x,0x%x)\r\n",reg,value & 0xff); |
---|
[176f133] | 496 | #endif |
---|
| 497 | if (reg == IDE_REGISTER_DATA_WORD) { |
---|
| 498 | outport_word(port+reg,value); |
---|
| 499 | } |
---|
| 500 | else { |
---|
| 501 | outport_byte(port+reg,value); |
---|
| 502 | } |
---|
| 503 | } |
---|
| 504 | |
---|
| 505 | /*=========================================================================*\ |
---|
| 506 | | Function: | |
---|
| 507 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 508 | static void pc386_ide_read_block |
---|
[176f133] | 509 | ( |
---|
| 510 | /*-------------------------------------------------------------------------*\ |
---|
| 511 | | Purpose: | |
---|
| 512 | | read a IDE controller data block | |
---|
| 513 | +---------------------------------------------------------------------------+ |
---|
| 514 | | Input Parameters: | |
---|
| 515 | \*-------------------------------------------------------------------------*/ |
---|
[c1fc5d4] | 516 | int minor, |
---|
| 517 | uint32_t block_size, |
---|
[176f133] | 518 | rtems_blkdev_sg_buffer *bufs, |
---|
| 519 | uint32_t *cbuf, |
---|
| 520 | uint32_t *pos |
---|
| 521 | ) |
---|
| 522 | /*-------------------------------------------------------------------------*\ |
---|
| 523 | | Return Value: | |
---|
| 524 | | <none> | |
---|
| 525 | \*=========================================================================*/ |
---|
| 526 | { |
---|
[c1fc5d4] | 527 | uint32_t port = IDE_Controller_Table[minor].port1; |
---|
| 528 | uint32_t cnt = 0; |
---|
| 529 | #if PC386_IDE_DEBUG_OUT |
---|
[be72045] | 530 | int i32 = 0; |
---|
[c1fc5d4] | 531 | pc386_ide_printk("pc386_ide_read_block(bs=%u,bn=%u,bl=%u,cb=%d,p=%d)\n", |
---|
| 532 | block_size, bufs[(*cbuf)].block, llength, *cbuf, *pos); |
---|
[be72045] | 533 | #endif |
---|
[c1fc5d4] | 534 | |
---|
[1c5ebc5] | 535 | while (cnt < block_size) |
---|
| 536 | { |
---|
[c1fc5d4] | 537 | uint16_t *lbuf; |
---|
| 538 | uint8_t status_val; |
---|
| 539 | int b; |
---|
[359e537] | 540 | |
---|
[c1fc5d4] | 541 | if (!pc386_ide_status_data_ready (port, pc386_ide_timeout, |
---|
| 542 | &status_val, pc386_ide_tasking_sleep)) |
---|
[1c5ebc5] | 543 | { |
---|
[c1fc5d4] | 544 | printk ("pc386_ide_read_block: block=%u cbuf=%u status=%02x, cnt=%d bs=%d\n", |
---|
| 545 | bufs[*cbuf].block, *cbuf, status_val, cnt, block_size); |
---|
[1c5ebc5] | 546 | /* FIXME: add an error here. */ |
---|
| 547 | return; |
---|
| 548 | } |
---|
[359e537] | 549 | |
---|
[1c5ebc5] | 550 | if (status_val & IDE_REGISTER_STATUS_ERR) |
---|
[c1fc5d4] | 551 | { |
---|
| 552 | inport_byte(port+IDE_REGISTER_ERROR, status_val); |
---|
[1c5ebc5] | 553 | printk("pc386_ide_read_block: error: %02x\n", status_val); |
---|
[c1fc5d4] | 554 | return; |
---|
| 555 | } |
---|
[176f133] | 556 | |
---|
[c1fc5d4] | 557 | lbuf = (uint16_t*)((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos)); |
---|
[359e537] | 558 | |
---|
[c1fc5d4] | 559 | for (b = 0; b < (ATA_SECTOR_SIZE / 2); b++) |
---|
[be72045] | 560 | { |
---|
[c1fc5d4] | 561 | inport_word(port+IDE_REGISTER_DATA,*lbuf); |
---|
| 562 | |
---|
| 563 | #if PC386_IDE_DEBUG_OUT |
---|
| 564 | pc386_ide_printk("%04x ",*lbuf); |
---|
| 565 | i32++; |
---|
| 566 | if (i32 >= 16) |
---|
| 567 | { |
---|
| 568 | pc386_ide_printk("\n"); |
---|
| 569 | i32 = 0; |
---|
| 570 | } |
---|
[176f133] | 571 | #endif |
---|
[c1fc5d4] | 572 | lbuf++; |
---|
| 573 | } |
---|
| 574 | cnt += ATA_SECTOR_SIZE; |
---|
| 575 | (*pos) += ATA_SECTOR_SIZE; |
---|
| 576 | if ((*pos) == bufs[(*cbuf)].length) { |
---|
[176f133] | 577 | (*pos) = 0; |
---|
| 578 | (*cbuf)++; |
---|
| 579 | lbuf = bufs[(*cbuf)].buffer; |
---|
| 580 | } |
---|
| 581 | } |
---|
| 582 | } |
---|
| 583 | |
---|
| 584 | /*=========================================================================*\ |
---|
| 585 | | Function: | |
---|
| 586 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 587 | static void pc386_ide_write_block |
---|
[176f133] | 588 | ( |
---|
| 589 | /*-------------------------------------------------------------------------*\ |
---|
| 590 | | Purpose: | |
---|
| 591 | | write a IDE controller data block | |
---|
| 592 | +---------------------------------------------------------------------------+ |
---|
| 593 | | Input Parameters: | |
---|
| 594 | \*-------------------------------------------------------------------------*/ |
---|
| 595 | int minor, |
---|
[c1fc5d4] | 596 | uint32_t block_size, |
---|
[176f133] | 597 | rtems_blkdev_sg_buffer *bufs, |
---|
| 598 | uint32_t *cbuf, |
---|
| 599 | uint32_t *pos |
---|
| 600 | ) |
---|
| 601 | /*-------------------------------------------------------------------------*\ |
---|
| 602 | | Return Value: | |
---|
| 603 | | <none> | |
---|
| 604 | \*=========================================================================*/ |
---|
| 605 | { |
---|
[c1fc5d4] | 606 | uint32_t port = IDE_Controller_Table[minor].port1; |
---|
| 607 | uint32_t cnt = 0; |
---|
| 608 | #if PC386_IDE_DEBUG_OUT |
---|
| 609 | int i32 = 0; |
---|
| 610 | pc386_ide_printk("pc386_ide_write_block(bs=%u,bn=%u,bl=%u,cb=%d,p=%d)\n", |
---|
| 611 | block_size, bufs[(*cbuf)].block, llength, *cbuf, *pos); |
---|
[176f133] | 612 | #endif |
---|
[1c5ebc5] | 613 | |
---|
| 614 | while (cnt < block_size) |
---|
| 615 | { |
---|
[c1fc5d4] | 616 | uint16_t *lbuf; |
---|
| 617 | uint8_t status_val; |
---|
| 618 | int b; |
---|
[359e537] | 619 | |
---|
[c1fc5d4] | 620 | if (!pc386_ide_status_data_ready (port, pc386_ide_timeout, |
---|
| 621 | &status_val, pc386_ide_tasking_sleep)) |
---|
[1c5ebc5] | 622 | { |
---|
[c1fc5d4] | 623 | printk ("pc386_ide_write_block: block=%u status=%02x, cnt=%d bs=%d\n", |
---|
| 624 | bufs[*cbuf].block, status_val, cnt, block_size); |
---|
[1c5ebc5] | 625 | /* FIXME: add an error here. */ |
---|
| 626 | return; |
---|
| 627 | } |
---|
[359e537] | 628 | |
---|
[1c5ebc5] | 629 | if (status_val & IDE_REGISTER_STATUS_ERR) |
---|
[c1fc5d4] | 630 | { |
---|
| 631 | inport_byte(port+IDE_REGISTER_ERROR, status_val); |
---|
| 632 | printk ("pc386_ide_write_block: error: %02x\n", status_val); |
---|
| 633 | return; |
---|
| 634 | } |
---|
[359e537] | 635 | |
---|
[c1fc5d4] | 636 | lbuf = (uint16_t*)(((uint8_t*)bufs[*cbuf].buffer) + (*pos)); |
---|
[359e537] | 637 | |
---|
[c1fc5d4] | 638 | for (b = 0; b < (ATA_SECTOR_SIZE / 2); b++) |
---|
| 639 | { |
---|
| 640 | #if PC386_IDE_DEBUG_OUT |
---|
| 641 | pc386_ide_printk("%04x ",*lbuf); |
---|
| 642 | i32++; |
---|
| 643 | if (i32 >= 16) |
---|
| 644 | { |
---|
| 645 | pc386_ide_printk("\n"); |
---|
| 646 | i32 = 0; |
---|
| 647 | } |
---|
[176f133] | 648 | #endif |
---|
[c1fc5d4] | 649 | outport_word(port+IDE_REGISTER_DATA,*lbuf); |
---|
| 650 | lbuf++; |
---|
| 651 | } |
---|
| 652 | cnt += ATA_SECTOR_SIZE; |
---|
| 653 | (*pos) += ATA_SECTOR_SIZE; |
---|
| 654 | if ((*pos) == bufs[(*cbuf)].length) { |
---|
[176f133] | 655 | (*pos) = 0; |
---|
| 656 | (*cbuf)++; |
---|
| 657 | lbuf = bufs[(*cbuf)].buffer; |
---|
| 658 | } |
---|
| 659 | } |
---|
| 660 | } |
---|
| 661 | |
---|
| 662 | /*=========================================================================*\ |
---|
| 663 | | Function: | |
---|
| 664 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 665 | static int pc386_ide_control |
---|
[176f133] | 666 | ( |
---|
| 667 | /*-------------------------------------------------------------------------*\ |
---|
| 668 | | Purpose: | |
---|
| 669 | | control interface for controller | |
---|
| 670 | +---------------------------------------------------------------------------+ |
---|
| 671 | | Input Parameters: | |
---|
| 672 | \*-------------------------------------------------------------------------*/ |
---|
| 673 | int minor, /* controller minor number */ |
---|
| 674 | uint32_t cmd, /* command to send */ |
---|
| 675 | void * arg /* optional argument */ |
---|
| 676 | ) |
---|
| 677 | /*-------------------------------------------------------------------------*\ |
---|
| 678 | | Return Value: | |
---|
| 679 | | <none> | |
---|
| 680 | \*=========================================================================*/ |
---|
| 681 | { |
---|
| 682 | return 0; |
---|
| 683 | } |
---|
| 684 | |
---|
| 685 | /*=========================================================================*\ |
---|
| 686 | | Function: | |
---|
| 687 | \*-------------------------------------------------------------------------*/ |
---|
[bf5d715] | 688 | static rtems_status_code pc386_ide_config_io_speed |
---|
[176f133] | 689 | ( |
---|
| 690 | /*-------------------------------------------------------------------------*\ |
---|
| 691 | | Purpose: | |
---|
| 692 | | set up transfer speed, if possible | |
---|
| 693 | +---------------------------------------------------------------------------+ |
---|
| 694 | | Input Parameters: | |
---|
| 695 | \*-------------------------------------------------------------------------*/ |
---|
| 696 | int minor, /* controller minor number */ |
---|
| 697 | uint16_t modes_avail /* optional argument */ |
---|
| 698 | ) |
---|
| 699 | /*-------------------------------------------------------------------------*\ |
---|
| 700 | | Return Value: | |
---|
| 701 | | rtems_status_code | |
---|
| 702 | \*=========================================================================*/ |
---|
| 703 | { |
---|
| 704 | return RTEMS_SUCCESSFUL; |
---|
| 705 | } |
---|
| 706 | |
---|
| 707 | /* |
---|
| 708 | * The following table configures the functions used for IDE drivers |
---|
| 709 | * in this BSP. |
---|
| 710 | */ |
---|
| 711 | |
---|
| 712 | ide_ctrl_fns_t pc386_ide_ctrl_fns = { |
---|
| 713 | pc386_ide_probe, |
---|
| 714 | pc386_ide_initialize, |
---|
| 715 | pc386_ide_control, |
---|
| 716 | pc386_ide_read_reg, |
---|
| 717 | pc386_ide_write_reg, |
---|
| 718 | pc386_ide_read_block, |
---|
| 719 | pc386_ide_write_block, |
---|
| 720 | pc386_ide_config_io_speed |
---|
| 721 | }; |
---|