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