1/* ps2esdi driver based on assembler code by Arindam Banerji, 2 written by Peter De Schrijver */ 3/* Reassuring note to IBM : This driver was NOT developed by vice-versa 4 engineering the PS/2's BIOS */ 5/* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those 6 other lovely fish out there... */ 7/* This code was written during the long and boring WINA 8 elections 1994 */ 9/* Thanks to Arindam Banerij for giving me the source of his driver */ 10/* This code may be freely distributed and modified in any way, 11 as long as these notes remain intact */ 12 13/* Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */ 14/* Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be) 15 Thanks to Arindam Banerij for sending me the docs of the adapter */ 16 17/* BA Modified for ThinkPad 720 by Boris Ashkinazi */ 18/* (bash@vnet.ibm.com) 08/08/95 */ 19 20/* Modified further for ThinkPad-720C by Uri Blumenthal */ 21/* (uri@watson.ibm.com) Sep 11, 1995 */ 22 23/* TODO : 24 + Timeouts 25 + Get disk parameters 26 + DMA above 16MB 27 + reset after read/write error 28 */ 29 30#define DEVICE_NAME "PS/2 ESDI" 31 32#include <linux/major.h> 33#include <linux/errno.h> 34#include <linux/wait.h> 35#include <linux/interrupt.h> 36#include <linux/fs.h> 37#include <linux/kernel.h> 38#include <linux/genhd.h> 39#include <linux/ps2esdi.h> 40#include <linux/blkdev.h> 41#include <linux/mca-legacy.h> 42#include <linux/init.h> 43#include <linux/ioport.h> 44#include <linux/module.h> 45#include <linux/hdreg.h> 46 47#include <asm/system.h> 48#include <asm/io.h> 49#include <asm/dma.h> 50#include <asm/mca_dma.h> 51#include <asm/uaccess.h> 52 53#define PS2ESDI_IRQ 14 54#define MAX_HD 2 55#define MAX_RETRIES 5 56#define MAX_16BIT 65536 57#define ESDI_TIMEOUT 0xf000 58#define ESDI_STAT_TIMEOUT 4 59 60#define TYPE_0_CMD_BLK_LENGTH 2 61#define TYPE_1_CMD_BLK_LENGTH 4 62 63static void reset_ctrl(void); 64 65static int ps2esdi_geninit(void); 66 67static void do_ps2esdi_request(request_queue_t * q); 68 69static void ps2esdi_readwrite(int cmd, struct request *req); 70 71static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, 72u_short cyl, u_short head, u_short sector, u_short length, u_char drive); 73 74static int ps2esdi_out_cmd_blk(u_short * cmd_blk); 75 76static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode); 77 78static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id); 79static void (*current_int_handler) (u_int) = NULL; 80static void ps2esdi_normal_interrupt_handler(u_int); 81static void ps2esdi_initial_reset_int_handler(u_int); 82static void ps2esdi_geometry_int_handler(u_int); 83static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo); 84 85static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); 86 87static void dump_cmd_complete_status(u_int int_ret_code); 88 89static void ps2esdi_get_device_cfg(void); 90 91static void ps2esdi_reset_timer(unsigned long unused); 92 93static u_int dma_arb_level; /* DMA arbitration level */ 94 95static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); 96 97static int no_int_yet; 98static int ps2esdi_drives; 99static u_short io_base; 100static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0); 101static int reset_status; 102static int ps2esdi_slot = -1; 103static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ 104static int intg_esdi = 0; /* If integrated adapter */ 105struct ps2esdi_i_struct { 106 unsigned int head, sect, cyl, wpcom, lzone, ctl; 107}; 108static DEFINE_SPINLOCK(ps2esdi_lock); 109static struct request_queue *ps2esdi_queue; 110static struct request *current_req; 111 112static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = 113{ 114 {0, 0, 0, 0, 0, 0}, 115 {0, 0, 0, 0, 0, 0}}; 116 117static struct block_device_operations ps2esdi_fops = 118{ 119 .owner = THIS_MODULE, 120 .getgeo = ps2esdi_getgeo, 121}; 122 123static struct gendisk *ps2esdi_gendisk[2]; 124 125/* initialization routine called by ll_rw_blk.c */ 126static int __init ps2esdi_init(void) 127{ 128 129 int error = 0; 130 131 /* register the device - pass the name and major number */ 132 if (register_blkdev(PS2ESDI_MAJOR, "ed")) 133 return -EBUSY; 134 135 /* set up some global information - indicating device specific info */ 136 ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock); 137 if (!ps2esdi_queue) { 138 unregister_blkdev(PS2ESDI_MAJOR, "ed"); 139 return -ENOMEM; 140 } 141 142 /* some minor housekeeping - setup the global gendisk structure */ 143 error = ps2esdi_geninit(); 144 if (error) { 145 printk(KERN_WARNING "PS2ESDI: error initialising" 146 " device, releasing resources\n"); 147 unregister_blkdev(PS2ESDI_MAJOR, "ed"); 148 blk_cleanup_queue(ps2esdi_queue); 149 return error; 150 } 151 return 0; 152} /* ps2esdi_init */ 153 154#ifndef MODULE 155 156module_init(ps2esdi_init); 157 158#else 159 160static int cyl[MAX_HD] = {-1,-1}; 161static int head[MAX_HD] = {-1, -1}; 162static int sect[MAX_HD] = {-1, -1}; 163 164module_param(tp720esdi, bool, 0); 165module_param_array(cyl, int, NULL, 0); 166module_param_array(head, int, NULL, 0); 167module_param_array(sect, int, NULL, 0); 168MODULE_LICENSE("GPL"); 169 170int init_module(void) { 171 int drive; 172 173 for(drive = 0; drive < MAX_HD; drive++) { 174 struct ps2esdi_i_struct *info = &ps2esdi_info[drive]; 175 176 if (cyl[drive] != -1) { 177 info->cyl = info->lzone = cyl[drive]; 178 info->wpcom = 0; 179 } 180 if (head[drive] != -1) { 181 info->head = head[drive]; 182 info->ctl = (head[drive] > 8 ? 8 : 0); 183 } 184 if (sect[drive] != -1) info->sect = sect[drive]; 185 } 186 return ps2esdi_init(); 187} 188 189void 190cleanup_module(void) { 191 int i; 192 if(ps2esdi_slot) { 193 mca_mark_as_unused(ps2esdi_slot); 194 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); 195 } 196 release_region(io_base, 4); 197 free_dma(dma_arb_level); 198 free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); 199 unregister_blkdev(PS2ESDI_MAJOR, "ed"); 200 blk_cleanup_queue(ps2esdi_queue); 201 for (i = 0; i < ps2esdi_drives; i++) { 202 del_gendisk(ps2esdi_gendisk[i]); 203 put_disk(ps2esdi_gendisk[i]); 204 } 205} 206#endif /* MODULE */ 207 208/* handles boot time command line parameters */ 209void __init tp720_setup(char *str, int *ints) 210{ 211 /* no params, just sets the tp720esdi flag if it exists */ 212 213 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME); 214 tp720esdi = 1; 215} 216 217void __init ed_setup(char *str, int *ints) 218{ 219 int hdind = 0; 220 221 /* handles 3 parameters only - corresponding to 222 1. Number of cylinders 223 2. Number of heads 224 3. Sectors/track 225 */ 226 227 if (ints[0] != 3) 228 return; 229 230 /* print out the information - seen at boot time */ 231 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n", 232 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]); 233 234 /* set the index into device specific information table */ 235 if (ps2esdi_info[0].head != 0) 236 hdind = 1; 237 238 /* set up all the device information */ 239 ps2esdi_info[hdind].head = ints[2]; 240 ps2esdi_info[hdind].sect = ints[3]; 241 ps2esdi_info[hdind].cyl = ints[1]; 242 ps2esdi_info[hdind].wpcom = 0; 243 ps2esdi_info[hdind].lzone = ints[1]; 244 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); 245} /* ed_setup */ 246 247static int ps2esdi_getinfo(char *buf, int slot, void *d) 248{ 249 int len = 0; 250 251 len += sprintf(buf + len, "DMA Arbitration Level: %d\n", 252 dma_arb_level); 253 len += sprintf(buf + len, "IO Port: %x\n", io_base); 254 len += sprintf(buf + len, "IRQ: 14\n"); 255 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives); 256 257 return len; 258} 259 260/* ps2 esdi specific initialization - called thru the gendisk chain */ 261static int __init ps2esdi_geninit(void) 262{ 263 /* 264 The first part contains the initialization code 265 for the ESDI disk subsystem. All we really do 266 is search for the POS registers of the controller 267 to do some simple setup operations. First, we 268 must ensure that the controller is installed, 269 enabled, and configured as PRIMARY. Then we must 270 determine the DMA arbitration level being used by 271 the controller so we can handle data transfer 272 operations properly. If all of this works, then 273 we will set the INIT_FLAG to a non-zero value. 274 */ 275 276 int slot = 0, i, reset_start, reset_end; 277 u_char status; 278 unsigned short adapterID; 279 int error = 0; 280 281 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) { 282 adapterID = INTG_ESDI_ID; 283 printk("%s: integrated ESDI adapter found in slot %d\n", 284 DEVICE_NAME, slot+1); 285#ifndef MODULE 286 mca_set_adapter_name(slot, "PS/2 Integrated ESDI"); 287#endif 288 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) { 289 adapterID = NRML_ESDI_ID; 290 printk("%s: normal ESDI adapter found in slot %d\n", 291 DEVICE_NAME, slot+1); 292 mca_set_adapter_name(slot, "PS/2 ESDI"); 293 } else { 294 return -ENODEV; 295 } 296 297 ps2esdi_slot = slot; 298 mca_mark_as_used(slot); 299 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL); 300 301 /* Found the slot - read the POS register 2 to get the necessary 302 configuration and status information. POS register 2 has the 303 following information : 304 Bit Function 305 7 reserved = 0 306 6 arbitration method 307 0 - fairness enabled 308 1 - fairness disabled, linear priority assignment 309 5-2 arbitration level 310 1 alternate address 311 1 alternate address 312 0 - use addresses 0x3510 - 0x3517 313 0 adapter enable 314 */ 315 316 status = mca_read_stored_pos(slot, 2); 317 /* is it enabled ? */ 318 if (!(status & STATUS_ENABLED)) { 319 printk("%s: ESDI adapter disabled\n", DEVICE_NAME); 320 error = -ENODEV; 321 goto err_out1; 322 } 323 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can 324 share with the SCSI driver */ 325 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, 326 IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) 327 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, 328 IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) 329 ) { 330 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ); 331 error = -EBUSY; 332 goto err_out1; 333 } 334 if (status & STATUS_ALTERNATE) 335 io_base = ALT_IO_BASE; 336 else 337 io_base = PRIMARY_IO_BASE; 338 339 if (!request_region(io_base, 4, "ed")) { 340 printk(KERN_WARNING"Unable to request region 0x%x\n", io_base); 341 error = -EBUSY; 342 goto err_out2; 343 } 344 /* get the dma arbitration level */ 345 dma_arb_level = (status >> 2) & 0xf; 346 347 /* BA */ 348 printk("%s: DMA arbitration level : %d\n", 349 DEVICE_NAME, dma_arb_level); 350 351 LITE_ON; 352 current_int_handler = ps2esdi_initial_reset_int_handler; 353 reset_ctrl(); 354 reset_status = 0; 355 reset_start = jiffies; 356 while (!reset_status) { 357 init_timer(&esdi_timer); 358 esdi_timer.expires = jiffies + HZ; 359 esdi_timer.data = 0; 360 add_timer(&esdi_timer); 361 sleep_on(&ps2esdi_int); 362 } 363 reset_end = jiffies; 364 LITE_OFF; 365 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n", 366 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ, 367 (reset_end - reset_start) % HZ); 368 369 370 /* Integrated ESDI Disk and Controller has only one drive! */ 371 if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */ 372 ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1; 373 } 374 375 376 377 /* finally this part sets up some global data structures etc. */ 378 379 ps2esdi_get_device_cfg(); 380 381 /* some annoyance in the above routine returns TWO drives? 382 Is something else happining in the background? 383 Regaurdless we fix the # of drives again. AJK */ 384 /* Integrated ESDI Disk and Controller has only one drive! */ 385 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */ 386 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */ 387 388 current_int_handler = ps2esdi_normal_interrupt_handler; 389 390 if (request_dma(dma_arb_level, "ed") !=0) { 391 printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n" 392 ,(int) dma_arb_level); 393 error = -EBUSY; 394 goto err_out3; 395 } 396 blk_queue_max_sectors(ps2esdi_queue, 128); 397 398 error = -ENOMEM; 399 for (i = 0; i < ps2esdi_drives; i++) { 400 struct gendisk *disk = alloc_disk(64); 401 if (!disk) 402 goto err_out4; 403 disk->major = PS2ESDI_MAJOR; 404 disk->first_minor = i<<6; 405 sprintf(disk->disk_name, "ed%c", 'a'+i); 406 disk->fops = &ps2esdi_fops; 407 ps2esdi_gendisk[i] = disk; 408 } 409 410 for (i = 0; i < ps2esdi_drives; i++) { 411 struct gendisk *disk = ps2esdi_gendisk[i]; 412 set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect * 413 ps2esdi_info[i].cyl); 414 disk->queue = ps2esdi_queue; 415 disk->private_data = &ps2esdi_info[i]; 416 add_disk(disk); 417 } 418 return 0; 419err_out4: 420 while (i--) 421 put_disk(ps2esdi_gendisk[i]); 422err_out3: 423 release_region(io_base, 4); 424err_out2: 425 free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); 426err_out1: 427 if(ps2esdi_slot) { 428 mca_mark_as_unused(ps2esdi_slot); 429 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); 430 } 431 return error; 432} 433 434static void __init ps2esdi_get_device_cfg(void) 435{ 436 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; 437 438 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME); 439 current_int_handler = ps2esdi_geometry_int_handler; 440 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600; 441 cmd_blk[1] = 0; 442 no_int_yet = TRUE; 443 ps2esdi_out_cmd_blk(cmd_blk); 444 if (no_int_yet) 445 sleep_on(&ps2esdi_int); 446 447 if (ps2esdi_drives > 1) { 448 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */ 449 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600; 450 cmd_blk[1] = 0; 451 no_int_yet = TRUE; 452 ps2esdi_out_cmd_blk(cmd_blk); 453 if (no_int_yet) 454 sleep_on(&ps2esdi_int); 455 } /* if second physical drive is present */ 456 return; 457} 458 459/* strategy routine that handles most of the IO requests */ 460static void do_ps2esdi_request(request_queue_t * q) 461{ 462 struct request *req; 463 /* since, this routine is called with interrupts cleared - they 464 must be before it finishes */ 465 466 req = elv_next_request(q); 467 if (!req) 468 return; 469 470 471 /* check for above 16Mb dmas */ 472 if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) { 473 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME); 474 end_request(req, FAIL); 475 return; 476 } 477 478 if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) { 479 printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n", 480 ps2esdi_drives, req->sector, 481 (unsigned long long)get_capacity(req->rq_disk)); 482 end_request(req, FAIL); 483 return; 484 } 485 486 switch (rq_data_dir(req)) { 487 case READ: 488 ps2esdi_readwrite(READ, req); 489 break; 490 case WRITE: 491 ps2esdi_readwrite(WRITE, req); 492 break; 493 default: 494 printk("%s: Unknown command\n", req->rq_disk->disk_name); 495 end_request(req, FAIL); 496 break; 497 } /* handle different commands */ 498} /* main strategy routine */ 499 500/* resets the ESDI adapter */ 501static void reset_ctrl(void) 502{ 503 504 u_long expire; 505 u_short status; 506 507 /* enable interrupts on the controller */ 508 status = inb(ESDI_INTRPT); 509 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have 510 any interrupt pending... */ 511 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL); 512 513 /* read the ESDI status port - if the controller is not busy, 514 simply do a soft reset (fast) - otherwise we'll have to do a 515 hard (slow) reset. */ 516 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) { 517 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME); 518 outb_p(CTRL_SOFT_RESET, ESDI_ATTN); 519 } 520 /* soft reset */ 521 else { 522 /*BA */ 523 printk("%s: hard reset...\n", DEVICE_NAME); 524 outb_p(CTRL_HARD_RESET, ESDI_CONTROL); 525 expire = jiffies + 2*HZ; 526 while (time_before(jiffies, expire)); 527 outb_p(1, ESDI_CONTROL); 528 } /* hard reset */ 529 530 531} /* reset the controller */ 532 533/* called by the strategy routine to handle read and write requests */ 534static void ps2esdi_readwrite(int cmd, struct request *req) 535{ 536 struct ps2esdi_i_struct *p = req->rq_disk->private_data; 537 unsigned block = req->sector; 538 unsigned count = req->current_nr_sectors; 539 int drive = p - ps2esdi_info; 540 u_short track, head, cylinder, sector; 541 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH]; 542 543 /* do some relevant arithmatic */ 544 track = block / p->sect; 545 head = track % p->head; 546 cylinder = track / p->head; 547 sector = block % p->sect; 548 549 /* call the routine that actually fills out a command block */ 550 ps2esdi_fill_cmd_block 551 (cmd_blk, 552 (cmd == READ) ? CMD_READ : CMD_WRITE, 553 cylinder, head, sector, count, drive); 554 555 /* send the command block to the controller */ 556 current_req = req; 557 spin_unlock_irq(&ps2esdi_lock); 558 if (ps2esdi_out_cmd_blk(cmd_blk)) { 559 spin_lock_irq(&ps2esdi_lock); 560 printk("%s: Controller failed\n", DEVICE_NAME); 561 if ((++req->errors) >= MAX_RETRIES) 562 end_request(req, FAIL); 563 } 564 /* check for failure to put out the command block */ 565 else { 566 spin_lock_irq(&ps2esdi_lock); 567 /* turn disk lights on */ 568 LITE_ON; 569 } 570 571} /* ps2esdi_readwrite */ 572 573/* fill out the command block */ 574static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, 575 u_short cyl, u_short head, u_short sector, u_short length, u_char drive) 576{ 577 578 cmd_blk[0] = (drive << 5) | cmd; 579 cmd_blk[1] = length; 580 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector; 581 cmd_blk[3] = (cyl & 0x3E0) >> 5; 582 583} /* fill out the command block */ 584 585/* write a command block to the controller */ 586static int ps2esdi_out_cmd_blk(u_short * cmd_blk) 587{ 588 589 int i; 590 unsigned long jif; 591 u_char status; 592 593 /* enable interrupts */ 594 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 595 596 /* do not write to the controller, if it is busy */ 597 for (jif = jiffies + ESDI_STAT_TIMEOUT; 598 time_after(jif, jiffies) && 599 (inb(ESDI_STATUS) & STATUS_BUSY); ) 600 ; 601 602 603 /* if device is still busy - then just time out */ 604 if (inb(ESDI_STATUS) & STATUS_BUSY) { 605 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME); 606 return ERROR; 607 } /* timeout ??? */ 608 /* Set up the attention register in the controller */ 609 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN); 610 611 612 /* one by one send each word out */ 613 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) { 614 status = inb(ESDI_STATUS); 615 for (jif = jiffies + ESDI_STAT_TIMEOUT; 616 time_after(jif, jiffies) && (status & STATUS_BUSY) && 617 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS)); 618 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) { 619 outw(*cmd_blk++, ESDI_CMD_INT); 620 } else { 621 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n", 622 DEVICE_NAME, status); 623 return ERROR; 624 } 625 } /* send all words out */ 626 return OK; 627} /* send out the commands */ 628 629 630/* prepare for dma - do all the necessary setup */ 631static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode) 632{ 633 unsigned long flags = claim_dma_lock(); 634 635 mca_disable_dma(dma_arb_level); 636 637 mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer)); 638 639 mca_set_dma_count(dma_arb_level, length * 512 / 2); 640 641 mca_set_dma_mode(dma_arb_level, dma_xmode); 642 643 mca_enable_dma(dma_arb_level); 644 645 release_dma_lock(flags); 646 647} /* prepare for dma */ 648 649 650 651static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id) 652{ 653 u_int int_ret_code; 654 655 if (inb(ESDI_STATUS) & STATUS_INTR) { 656 int_ret_code = inb(ESDI_INTRPT); 657 if (current_int_handler) { 658 /* Disable adapter interrupts till processing is finished */ 659 outb(CTRL_DISABLE_INTR, ESDI_CONTROL); 660 current_int_handler(int_ret_code); 661 } else 662 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME); 663 } else { 664 return IRQ_NONE; 665 } 666 return IRQ_HANDLED; 667} 668 669static void ps2esdi_initial_reset_int_handler(u_int int_ret_code) 670{ 671 672 switch (int_ret_code & 0xf) { 673 case INT_RESET: 674 /*BA */ 675 printk("%s: initial reset completed.\n", DEVICE_NAME); 676 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 677 wake_up(&ps2esdi_int); 678 break; 679 case INT_ATTN_ERROR: 680 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, 681 int_ret_code); 682 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS)); 683 break; 684 default: 685 printk("%s: initial reset handler received interrupt: %02X\n", 686 DEVICE_NAME, int_ret_code); 687 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 688 break; 689 } 690 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 691} 692 693 694static void ps2esdi_geometry_int_handler(u_int int_ret_code) 695{ 696 u_int status, drive_num; 697 unsigned long rba; 698 int i; 699 700 drive_num = int_ret_code >> 5; 701 switch (int_ret_code & 0xf) { 702 case INT_CMD_COMPLETE: 703 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); 704 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { 705 printk("%s: timeout reading status word\n", DEVICE_NAME); 706 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 707 break; 708 } 709 status = inw(ESDI_STT_INT); 710 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) { 711#define REPLY_WORDS 5 /* we already read word 0 */ 712 u_short reply[REPLY_WORDS]; 713 714 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) { 715 /*BA */ 716 printk("%s: Device Configuration Status for drive %u\n", 717 DEVICE_NAME, drive_num); 718 719 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8); 720 721 printk 722 ("Config bits: %s%s%s%s%s\n", 723 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", 724 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) 725 ? "Zero Defect, " : "Defects Present, ", 726 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "", 727 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ", 728 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries"); 729 730 rba = reply[1] | ((unsigned long) reply[2] << 16); 731 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba); 732 733 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n", 734 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff); 735 736 if (!ps2esdi_info[drive_num].head) { 737 ps2esdi_info[drive_num].head = 64; 738 ps2esdi_info[drive_num].sect = 32; 739 ps2esdi_info[drive_num].cyl = rba / (64 * 32); 740 ps2esdi_info[drive_num].wpcom = 0; 741 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl; 742 ps2esdi_info[drive_num].ctl = 8; 743 if (tp720esdi) { /* store the retrieved parameters */ 744 ps2esdi_info[0].head = reply[4] & 0Xff; 745 ps2esdi_info[0].sect = reply[4] >> 8; 746 ps2esdi_info[0].cyl = reply[3]; 747 ps2esdi_info[0].wpcom = 0; 748 ps2esdi_info[0].lzone = reply[3]; 749 } else { 750 if (!intg_esdi) 751 ps2esdi_drives++; 752 } 753 } 754#ifdef OBSOLETE 755 if (!ps2esdi_info[drive_num].head) { 756 ps2esdi_info[drive_num].head = reply[4] & 0Xff; 757 ps2esdi_info[drive_num].sect = reply[4] >> 8; 758 ps2esdi_info[drive_num].cyl = reply[3]; 759 ps2esdi_info[drive_num].wpcom = 0; 760 ps2esdi_info[drive_num].lzone = reply[3]; 761 if (tp720esdi) { /* store the retrieved parameters */ 762 ps2esdi_info[0].head = reply[4] & 0Xff; 763 ps2esdi_info[0].sect = reply[4] >> 8; 764 ps2esdi_info[0].cyl = reply[3]; 765 ps2esdi_info[0].wpcom = 0; 766 ps2esdi_info[0].lzone = reply[3]; 767 } else { 768 ps2esdi_drives++; 769 } 770 } 771#endif 772 773 } else 774 printk("%s: failed while getting device config\n", DEVICE_NAME); 775#undef REPLY_WORDS 776 } else 777 printk("%s: command %02X unknown by geometry handler\n", 778 DEVICE_NAME, status & 0x1f); 779 780 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 781 break; 782 783 case INT_ATTN_ERROR: 784 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, 785 int_ret_code); 786 printk("%s: Device not available\n", DEVICE_NAME); 787 break; 788 case INT_CMD_ECC: 789 case INT_CMD_RETRY: 790 case INT_CMD_ECC_RETRY: 791 case INT_CMD_WARNING: 792 case INT_CMD_ABORT: 793 case INT_CMD_FAILED: 794 case INT_DMA_ERR: 795 case INT_CMD_BLK_ERR: 796 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME); 797 dump_cmd_complete_status(int_ret_code); 798 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 799 break; 800 default: 801 printk("%s: Unknown interrupt reason: %02X\n", 802 DEVICE_NAME, int_ret_code & 0xf); 803 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 804 break; 805 } 806 807 wake_up(&ps2esdi_int); 808 no_int_yet = FALSE; 809 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 810 811} 812 813static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) 814{ 815 unsigned long flags; 816 u_int status; 817 u_int ending; 818 int i; 819 820 switch (int_ret_code & 0x0f) { 821 case INT_TRANSFER_REQ: 822 ps2esdi_prep_dma(current_req->buffer, 823 current_req->current_nr_sectors, 824 (rq_data_dir(current_req) == READ) 825 ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER 826 : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ); 827 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); 828 ending = -1; 829 break; 830 831 case INT_ATTN_ERROR: 832 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, 833 int_ret_code); 834 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 835 ending = FAIL; 836 break; 837 838 case INT_CMD_COMPLETE: 839 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); 840 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { 841 printk("%s: timeout reading status word\n", DEVICE_NAME); 842 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 843 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 844 if ((++current_req->errors) >= MAX_RETRIES) 845 ending = FAIL; 846 else 847 ending = -1; 848 break; 849 } 850 status = inw(ESDI_STT_INT); 851 switch (status & 0x1F) { 852 case (CMD_READ & 0xff): 853 case (CMD_WRITE & 0xff): 854 LITE_OFF; 855 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 856 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 857 ending = SUCCES; 858 break; 859 default: 860 printk("%s: interrupt for unknown command %02X\n", 861 DEVICE_NAME, status & 0x1f); 862 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 863 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 864 ending = -1; 865 break; 866 } 867 break; 868 case INT_CMD_ECC: 869 case INT_CMD_RETRY: 870 case INT_CMD_ECC_RETRY: 871 LITE_OFF; 872 dump_cmd_complete_status(int_ret_code); 873 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 874 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 875 ending = SUCCES; 876 break; 877 case INT_CMD_WARNING: 878 case INT_CMD_ABORT: 879 case INT_CMD_FAILED: 880 case INT_DMA_ERR: 881 LITE_OFF; 882 dump_cmd_complete_status(int_ret_code); 883 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 884 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 885 if ((++current_req->errors) >= MAX_RETRIES) 886 ending = FAIL; 887 else 888 ending = -1; 889 break; 890 891 case INT_CMD_BLK_ERR: 892 dump_cmd_complete_status(int_ret_code); 893 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 894 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 895 ending = FAIL; 896 break; 897 898 case INT_CMD_FORMAT: 899 printk("%s: huh ? Who issued this format command ?\n" 900 ,DEVICE_NAME); 901 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 902 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 903 ending = -1; 904 break; 905 906 case INT_RESET: 907 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ; 908 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 909 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 910 ending = -1; 911 break; 912 913 default: 914 printk("%s: Unknown interrupt reason: %02X\n", 915 DEVICE_NAME, int_ret_code & 0xf); 916 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); 917 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 918 ending = -1; 919 break; 920 } 921 if(ending != -1) { 922 spin_lock_irqsave(&ps2esdi_lock, flags); 923 end_request(current_req, ending); 924 current_req = NULL; 925 do_ps2esdi_request(ps2esdi_queue); 926 spin_unlock_irqrestore(&ps2esdi_lock, flags); 927 } 928} /* handle interrupts */ 929 930 931 932static int ps2esdi_read_status_words(int num_words, 933 int max_words, 934 u_short * buffer) 935{ 936 int i; 937 938 for (; max_words && num_words; max_words--, num_words--, buffer++) { 939 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); 940 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { 941 printk("%s: timeout reading status word\n", DEVICE_NAME); 942 return FAIL; 943 } 944 *buffer = inw(ESDI_STT_INT); 945 } 946 return SUCCES; 947} 948 949 950 951 952static void dump_cmd_complete_status(u_int int_ret_code) 953{ 954#define WAIT_FOR_STATUS \ 955 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \ 956 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \ 957 printk("%s: timeout reading status word\n",DEVICE_NAME); \ 958 return; \ 959 } 960 961 int i, word_count; 962 u_short stat_word; 963 u_long rba; 964 965 printk("%s: Device: %u, interrupt ID: %02X\n", 966 DEVICE_NAME, int_ret_code >> 5, 967 int_ret_code & 0xf); 968 969 WAIT_FOR_STATUS; 970 stat_word = inw(ESDI_STT_INT); 971 word_count = (stat_word >> 8) - 1; 972 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count, 973 stat_word & 0xff); 974 975 if (word_count--) { 976 WAIT_FOR_STATUS; 977 stat_word = inw(ESDI_STT_INT); 978 printk("%s: command status code: %02X, command error code: %02X\n", 979 DEVICE_NAME, stat_word >> 8, stat_word & 0xff); 980 } 981 if (word_count--) { 982 WAIT_FOR_STATUS; 983 stat_word = inw(ESDI_STT_INT); 984 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME, 985 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ", 986 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ", 987 (stat_word & 0x0400) ? "Write Fault, " : "", 988 (stat_word & 0x0200) ? "Track 0, " : "", 989 (stat_word & 0x0100) ? "Seek or command complete, " : "", 990 stat_word >> 8); 991 } 992 if (word_count--) { 993 WAIT_FOR_STATUS; 994 stat_word = inw(ESDI_STT_INT); 995 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word); 996 } 997 if (word_count -= 2) { 998 WAIT_FOR_STATUS; 999 rba = inw(ESDI_STT_INT); 1000 WAIT_FOR_STATUS; 1001 rba |= inw(ESDI_STT_INT) << 16; 1002 printk(", Last Cyl: %u Head: %u Sector: %u\n", 1003 (u_short) ((rba & 0x1ff80000) >> 11), 1004 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f)); 1005 } else 1006 printk("\n"); 1007 1008 if (word_count--) { 1009 WAIT_FOR_STATUS; 1010 stat_word = inw(ESDI_STT_INT); 1011 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word); 1012 } 1013 printk("\n"); 1014 1015#undef WAIT_FOR_STATUS 1016 1017} 1018 1019static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo) 1020{ 1021 struct ps2esdi_i_struct *p = bdev->bd_disk->private_data; 1022 1023 geo->heads = p->head; 1024 geo->sectors = p->sect; 1025 geo->cylinders = p->cyl; 1026 return 0; 1027} 1028 1029static void ps2esdi_reset_timer(unsigned long unused) 1030{ 1031 1032 int status; 1033 1034 status = inb(ESDI_INTRPT); 1035 if ((status & 0xf) == INT_RESET) { 1036 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); 1037 outb(CTRL_ENABLE_INTR, ESDI_CONTROL); 1038 reset_status = 1; 1039 } 1040 wake_up(&ps2esdi_int); 1041} 1042