1 /* 2 * Copyright 2002/03, Thomas Kurschel. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 /* 7 IDE ISA controller driver 8 9 This is a testing-only driver. In reality, you want to use 10 the IDE PCI controller driver, but at least under Bochs, there's not 11 much choice as PCI support is very limited there. 12 */ 13 14 15 #include <KernelExport.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include <ata_adapter.h> 20 #include <bus/ISA.h> 21 22 23 //#define TRACE_IDE_ISA 24 #ifdef TRACE_IDE_ISA 25 # define TRACE(x...) dprintf("ide_isa: " x) 26 #else 27 # define TRACE(x...) ; 28 #endif 29 30 31 #define ATA_ISA_MODULE_NAME "busses/ata/ide_isa/driver_v1" 32 33 // private node item: 34 // io address of command block 35 #define ATA_ISA_COMMAND_BLOCK_BASE "ide_isa/command_block_base" 36 // io address of control block 37 #define ATA_ISA_CONTROL_BLOCK_BASE "ide_isa/control_block_base" 38 // interrupt number 39 #define ATA_ISA_INTNUM "ide_isa/irq" 40 41 42 ata_for_controller_interface *sATA; 43 device_manager_info *sDeviceManager; 44 45 46 // info about one channel 47 typedef struct channel_info { 48 isa2_module_info *isa; 49 uint16 command_block_base; // io address command block 50 uint16 control_block_base; // io address control block 51 int intnum; // interrupt number 52 53 uint32 lost; // != 0 if device got removed, i.e. if it must not 54 // be accessed anymore 55 56 ata_channel ataChannel; 57 device_node *node; 58 } channel_info; 59 60 61 /*! publish node of an ata channel */ 62 static status_t 63 publish_channel(device_node *parent, uint16 command_block_base, 64 uint16 control_block_base, uint8 intnum, const char *name) 65 { 66 device_attr attrs[] = { 67 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, { .string = ATA_FOR_CONTROLLER_MODULE_NAME }}, 68 69 // properties of this controller for ata bus manager 70 { ATA_CONTROLLER_MAX_DEVICES_ITEM, B_UINT8_TYPE, { .ui8 = 2 }}, 71 { ATA_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { .ui8 = 0 }}, 72 { ATA_CONTROLLER_CONTROLLER_NAME_ITEM, B_STRING_TYPE, { .string = name }}, 73 74 // DMA properties; the 16 bit alignment is not necessary as 75 // the ata bus manager handles that very efficiently, but why 76 // not use the block device manager for doing that? 77 { B_DMA_ALIGNMENT, B_UINT32_TYPE, { .ui32 = 1 }}, 78 { B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { .ui64 = 0x100000000LL }}, 79 80 // private data to identify device 81 { ATA_ISA_COMMAND_BLOCK_BASE, B_UINT16_TYPE, { .ui16 = command_block_base }}, 82 { ATA_ISA_CONTROL_BLOCK_BASE, B_UINT16_TYPE, { .ui16 = control_block_base }}, 83 { ATA_ISA_INTNUM, B_UINT8_TYPE, { .ui8 = intnum }}, 84 { NULL } 85 }; 86 io_resource resources[3] = { 87 { B_IO_PORT, command_block_base, 8 }, 88 { B_IO_PORT, control_block_base, 1 }, 89 {} 90 }; 91 92 TRACE("publishing %s, resources %#x %#x %d\n", 93 name, command_block_base, control_block_base, intnum); 94 95 return sDeviceManager->register_node(parent, ATA_ISA_MODULE_NAME, attrs, resources, 96 NULL); 97 } 98 99 100 // #pragma mark - 101 102 103 static void 104 set_channel(void *cookie, ata_channel ataChannel) 105 { 106 channel_info *channel = cookie; 107 channel->ataChannel = ataChannel; 108 } 109 110 111 static status_t 112 write_command_block_regs(void *channel_cookie, ata_task_file *tf, 113 ata_reg_mask mask) 114 { 115 channel_info *channel = channel_cookie; 116 uint16 ioaddr = channel->command_block_base; 117 int i; 118 119 if (channel->lost) 120 return B_ERROR; 121 122 for (i = 0; i < 7; i++) { 123 if (((1 << (i + 7)) & mask) != 0) { 124 TRACE("write_command_block_regs(): %x->HI(%x)\n", 125 tf->raw.r[i + 7], i); 126 channel->isa->write_io_8(ioaddr + 1 + i, tf->raw.r[i + 7]); 127 } 128 129 if (((1 << i) & mask) != 0 ) { 130 TRACE("write_comamnd_block_regs(): %x->LO(%x)\n", tf->raw.r[i], i); 131 channel->isa->write_io_8(ioaddr + 1 + i, tf->raw.r[i]); 132 } 133 } 134 135 return B_OK; 136 } 137 138 139 static status_t 140 read_command_block_regs(void *channel_cookie, ata_task_file *tf, 141 ata_reg_mask mask) 142 { 143 channel_info *channel = channel_cookie; 144 uint16 ioaddr = channel->command_block_base; 145 int i; 146 147 if (channel->lost) 148 return B_ERROR; 149 150 for (i = 0; i < 7; i++) { 151 if (((1 << i) & mask) != 0) { 152 tf->raw.r[i] = channel->isa->read_io_8(ioaddr + 1 + i); 153 TRACE("read_command_block_regs(%x): %x\n", i, (int)tf->raw.r[i]); 154 } 155 } 156 157 return B_OK; 158 } 159 160 161 static uint8 162 get_altstatus(void *channel_cookie) 163 { 164 channel_info *channel = channel_cookie; 165 uint16 altstatusaddr = channel->control_block_base; 166 167 if (channel->lost) 168 return B_ERROR; 169 170 return channel->isa->read_io_8(altstatusaddr); 171 } 172 173 174 static status_t 175 write_device_control(void *channel_cookie, uint8 val) 176 { 177 channel_info *channel = channel_cookie; 178 uint16 device_control_addr = channel->control_block_base; 179 180 TRACE("write_device_control(%x)\n", (int)val); 181 182 if (channel->lost) 183 return B_ERROR; 184 185 channel->isa->write_io_8(device_control_addr, val); 186 187 return B_OK; 188 } 189 190 191 static status_t 192 write_pio_16(void *channel_cookie, uint16 *data, int count, bool force_16bit) 193 { 194 channel_info *channel = channel_cookie; 195 uint16 ioaddr = channel->command_block_base; 196 197 if (channel->lost) 198 return B_ERROR; 199 200 // Bochs doesn't support 32 bit accesses; 201 // no real performance impact as this driver is for Bochs only anyway 202 force_16bit = true; 203 204 if ((count & 1) != 0 || force_16bit) { 205 for (; count > 0; --count) 206 channel->isa->write_io_16(ioaddr, *(data++)); 207 } else { 208 uint32 *cur_data = (uint32 *)data; 209 210 for (; count > 0; count -= 2) 211 channel->isa->write_io_32(ioaddr, *(cur_data++)); 212 } 213 214 return B_OK; 215 } 216 217 218 static status_t 219 read_pio_16(void *channel_cookie, uint16 *data, int count, bool force_16bit) 220 { 221 channel_info *channel = channel_cookie; 222 uint16 ioaddr = channel->command_block_base; 223 224 if (channel->lost) 225 return B_ERROR; 226 227 force_16bit = true; 228 229 if ((count & 1) != 0 || force_16bit) { 230 for (; count > 0; --count) 231 *(data++) = channel->isa->read_io_16(ioaddr); 232 } else { 233 uint32 *cur_data = (uint32 *)data; 234 235 for (; count > 0; count -= 2) 236 *(cur_data++) = channel->isa->read_io_32(ioaddr); 237 } 238 239 return B_OK; 240 } 241 242 243 static int32 244 inthand(void *arg) 245 { 246 channel_info *channel = (channel_info *)arg; 247 uint8 status; 248 249 TRACE("interrupt handler()\n"); 250 251 if (channel->lost) 252 return B_UNHANDLED_INTERRUPT; 253 254 // acknowledge IRQ 255 status = channel->isa->read_io_8(channel->command_block_base + 7); 256 257 return sATA->interrupt_handler(channel->ataChannel, status); 258 } 259 260 261 static status_t 262 prepare_dma(void *channel_cookie, const physical_entry *sg_list, 263 size_t sg_list_count, bool write) 264 { 265 return B_NOT_ALLOWED; 266 } 267 268 269 static status_t 270 start_dma(void *channel_cookie) 271 { 272 return B_NOT_ALLOWED; 273 } 274 275 276 static status_t 277 finish_dma(void *channel_cookie) 278 { 279 return B_NOT_ALLOWED; 280 } 281 282 283 // #pragma mark - 284 285 286 static float 287 supports_device(device_node *parent) 288 { 289 const char *bus; 290 291 // make sure parent is really the ISA bus manager 292 if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 293 return B_ERROR; 294 295 if (strcmp(bus, "isa")) 296 return 0.0; 297 298 // we assume that every modern PC has an IDE controller, so no 299 // further testing is done (well - I don't really know how to detect the 300 // controller, but who cares ;) 301 302 return 0.6; 303 } 304 305 306 static status_t 307 init_channel(device_node *node, void **_cookie) 308 { 309 channel_info *channel; 310 device_node *parent; 311 isa2_module_info *isa; 312 uint16 command_block_base, control_block_base; 313 uint8 irq; 314 status_t res; 315 316 TRACE("ISA-IDE: channel init\n"); 317 318 // get device data 319 if (sDeviceManager->get_attr_uint16(node, ATA_ISA_COMMAND_BLOCK_BASE, &command_block_base, false) != B_OK 320 || sDeviceManager->get_attr_uint16(node, ATA_ISA_CONTROL_BLOCK_BASE, &control_block_base, false) != B_OK 321 || sDeviceManager->get_attr_uint8(node, ATA_ISA_INTNUM, &irq, false) != B_OK) 322 return B_ERROR; 323 324 parent = sDeviceManager->get_parent_node(node); 325 sDeviceManager->get_driver(parent, (driver_module_info **)&isa, NULL); 326 sDeviceManager->put_node(parent); 327 328 channel = (channel_info *)malloc(sizeof(channel_info)); 329 if (channel == NULL) 330 return B_NO_MEMORY; 331 332 TRACE("ISA-IDE: channel init, resources %#x %#x %d\n", 333 command_block_base, control_block_base, irq); 334 335 channel->isa = isa; 336 channel->node = node; 337 channel->lost = false; 338 channel->command_block_base = command_block_base; 339 channel->control_block_base = control_block_base; 340 channel->intnum = irq; 341 channel->ataChannel = NULL; 342 343 res = install_io_interrupt_handler(channel->intnum, 344 inthand, channel, 0); 345 346 if (res < 0) { 347 TRACE("ISA-IDE: couldn't install irq handler for int %d\n", irq); 348 goto err; 349 } 350 351 // enable interrupts so the channel is ready to run 352 write_device_control(channel, ATA_DEVICE_CONTROL_BIT3); 353 354 *_cookie = channel; 355 return B_OK; 356 357 err: 358 free(channel); 359 return res; 360 } 361 362 363 static void 364 uninit_channel(void *channel_cookie) 365 { 366 channel_info *channel = channel_cookie; 367 368 TRACE("ISA-IDE: channel uninit\n"); 369 370 // disable IRQs 371 write_device_control(channel, ATA_DEVICE_CONTROL_BIT3 | ATA_DEVICE_CONTROL_DISABLE_INTS); 372 373 // catch spurious interrupt 374 // (some controllers generate an IRQ when you _disable_ interrupts, 375 // they are delayed by less then 40 µs, so 1 ms is safe) 376 snooze(1000); 377 378 remove_io_interrupt_handler(channel->intnum, inthand, channel); 379 380 free(channel); 381 } 382 383 384 static status_t 385 register_device(device_node *parent) 386 { 387 status_t primaryStatus; 388 status_t secondaryStatus; 389 TRACE("register_device()\n"); 390 391 // our parent device is the isa bus and all device drivers are Universal, 392 // so the pnp_manager tries each ISA driver in turn 393 primaryStatus = publish_channel(parent, 0x1f0, 0x3f6, 14, 394 "primary IDE channel"); 395 secondaryStatus = publish_channel(parent, 0x170, 0x376, 15, 396 "secondary IDE channel"); 397 398 if (primaryStatus == B_OK || secondaryStatus == B_OK) 399 return B_OK; 400 401 return primaryStatus; 402 } 403 404 405 static void 406 channel_removed(void *cookie) 407 { 408 channel_info *channel = cookie; 409 TRACE("channel_removed()\n"); 410 411 // disable access instantly 412 atomic_or((int32*)&channel->lost, 1); 413 } 414 415 416 module_dependency module_dependencies[] = { 417 { ATA_FOR_CONTROLLER_MODULE_NAME, (module_info **)&sATA }, 418 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager }, 419 {} 420 }; 421 422 // exported interface 423 static ata_controller_interface sISAControllerInterface = { 424 { 425 { 426 ATA_ISA_MODULE_NAME, 427 0, 428 NULL 429 }, 430 431 supports_device, 432 register_device, 433 init_channel, 434 uninit_channel, 435 NULL, // register child devices 436 NULL, // rescan 437 channel_removed, 438 }, 439 440 &set_channel, 441 442 &write_command_block_regs, 443 &read_command_block_regs, 444 445 &get_altstatus, 446 &write_device_control, 447 448 &write_pio_16, 449 &read_pio_16, 450 451 &prepare_dma, 452 &start_dma, 453 &finish_dma, 454 }; 455 456 module_info *modules[] = { 457 (module_info *)&sISAControllerInterface, 458 NULL 459 }; 460