Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / block / ps2esdi.c
blob29548784cb7b1ab734c65e68897867a7c992523e
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 */
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 */
17 /* BA Modified for ThinkPad 720 by Boris Ashkinazi */
18 /* (bash@vnet.ibm.com) 08/08/95 */
20 /* Modified further for ThinkPad-720C by Uri Blumenthal */
21 /* (uri@watson.ibm.com) Sep 11, 1995 */
23 /* TODO :
24 + Timeouts
25 + Get disk parameters
26 + DMA above 16MB
27 + reset after read/write error
30 #define DEVICE_NAME "PS/2 ESDI"
32 #include <linux/config.h>
33 #include <linux/major.h>
34 #include <linux/errno.h>
35 #include <linux/wait.h>
36 #include <linux/interrupt.h>
37 #include <linux/fs.h>
38 #include <linux/kernel.h>
39 #include <linux/genhd.h>
40 #include <linux/ps2esdi.h>
41 #include <linux/blkdev.h>
42 #include <linux/mca-legacy.h>
43 #include <linux/init.h>
44 #include <linux/ioport.h>
45 #include <linux/module.h>
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>
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
60 #define TYPE_0_CMD_BLK_LENGTH 2
61 #define TYPE_1_CMD_BLK_LENGTH 4
63 static void reset_ctrl(void);
65 static int ps2esdi_geninit(void);
67 static void do_ps2esdi_request(request_queue_t * q);
69 static void ps2esdi_readwrite(int cmd, struct request *req);
71 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
72 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
74 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
76 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
78 static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
79 struct pt_regs *regs);
80 static void (*current_int_handler) (u_int) = NULL;
81 static void ps2esdi_normal_interrupt_handler(u_int);
82 static void ps2esdi_initial_reset_int_handler(u_int);
83 static void ps2esdi_geometry_int_handler(u_int);
84 static int ps2esdi_ioctl(struct inode *inode, struct file *file,
85 u_int cmd, u_long arg);
87 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
89 static void dump_cmd_complete_status(u_int int_ret_code);
91 static void ps2esdi_get_device_cfg(void);
93 static void ps2esdi_reset_timer(unsigned long unused);
95 static u_int dma_arb_level; /* DMA arbitration level */
97 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
99 static int no_int_yet;
100 static int ps2esdi_drives;
101 static u_short io_base;
102 static struct timer_list esdi_timer =
103 TIMER_INITIALIZER(ps2esdi_reset_timer, 0, 0);
104 static int reset_status;
105 static int ps2esdi_slot = -1;
106 static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
107 static int intg_esdi = 0; /* If integrated adapter */
108 struct ps2esdi_i_struct {
109 unsigned int head, sect, cyl, wpcom, lzone, ctl;
111 static DEFINE_SPINLOCK(ps2esdi_lock);
112 static struct request_queue *ps2esdi_queue;
113 static struct request *current_req;
115 #if 0
116 #if 0 /* try both - I don't know which one is better... UB */
117 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
119 {4, 48, 1553, 0, 0, 0},
120 {0, 0, 0, 0, 0, 0}};
121 #else
122 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
124 {64, 32, 161, 0, 0, 0},
125 {0, 0, 0, 0, 0, 0}};
126 #endif
127 #endif
128 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
130 {0, 0, 0, 0, 0, 0},
131 {0, 0, 0, 0, 0, 0}};
133 static struct block_device_operations ps2esdi_fops =
135 .owner = THIS_MODULE,
136 .ioctl = ps2esdi_ioctl,
139 static struct gendisk *ps2esdi_gendisk[2];
141 /* initialization routine called by ll_rw_blk.c */
142 static int __init ps2esdi_init(void)
145 int error = 0;
147 /* register the device - pass the name and major number */
148 if (register_blkdev(PS2ESDI_MAJOR, "ed"))
149 return -EBUSY;
151 /* set up some global information - indicating device specific info */
152 ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock);
153 if (!ps2esdi_queue) {
154 unregister_blkdev(PS2ESDI_MAJOR, "ed");
155 return -ENOMEM;
158 /* some minor housekeeping - setup the global gendisk structure */
159 error = ps2esdi_geninit();
160 if (error) {
161 printk(KERN_WARNING "PS2ESDI: error initialising"
162 " device, releasing resources\n");
163 unregister_blkdev(PS2ESDI_MAJOR, "ed");
164 blk_cleanup_queue(ps2esdi_queue);
165 return error;
167 return 0;
168 } /* ps2esdi_init */
170 #ifndef MODULE
172 module_init(ps2esdi_init);
174 #else
176 static int cyl[MAX_HD] = {-1,-1};
177 static int head[MAX_HD] = {-1, -1};
178 static int sect[MAX_HD] = {-1, -1};
180 module_param(tp720esdi, bool, 0);
181 module_param_array(cyl, int, NULL, 0);
182 module_param_array(head, int, NULL, 0);
183 module_param_array(sect, int, NULL, 0);
184 MODULE_LICENSE("GPL");
186 int init_module(void) {
187 int drive;
189 for(drive = 0; drive < MAX_HD; drive++) {
190 struct ps2esdi_i_struct *info = &ps2esdi_info[drive];
192 if (cyl[drive] != -1) {
193 info->cyl = info->lzone = cyl[drive];
194 info->wpcom = 0;
196 if (head[drive] != -1) {
197 info->head = head[drive];
198 info->ctl = (head[drive] > 8 ? 8 : 0);
200 if (sect[drive] != -1) info->sect = sect[drive];
202 return ps2esdi_init();
205 void
206 cleanup_module(void) {
207 int i;
208 if(ps2esdi_slot) {
209 mca_mark_as_unused(ps2esdi_slot);
210 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
212 release_region(io_base, 4);
213 free_dma(dma_arb_level);
214 free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
215 unregister_blkdev(PS2ESDI_MAJOR, "ed");
216 blk_cleanup_queue(ps2esdi_queue);
217 for (i = 0; i < ps2esdi_drives; i++) {
218 del_gendisk(ps2esdi_gendisk[i]);
219 put_disk(ps2esdi_gendisk[i]);
222 #endif /* MODULE */
224 /* handles boot time command line parameters */
225 void __init tp720_setup(char *str, int *ints)
227 /* no params, just sets the tp720esdi flag if it exists */
229 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
230 tp720esdi = 1;
233 void __init ed_setup(char *str, int *ints)
235 int hdind = 0;
237 /* handles 3 parameters only - corresponding to
238 1. Number of cylinders
239 2. Number of heads
240 3. Sectors/track
243 if (ints[0] != 3)
244 return;
246 /* print out the information - seen at boot time */
247 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
248 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
250 /* set the index into device specific information table */
251 if (ps2esdi_info[0].head != 0)
252 hdind = 1;
254 /* set up all the device information */
255 ps2esdi_info[hdind].head = ints[2];
256 ps2esdi_info[hdind].sect = ints[3];
257 ps2esdi_info[hdind].cyl = ints[1];
258 ps2esdi_info[hdind].wpcom = 0;
259 ps2esdi_info[hdind].lzone = ints[1];
260 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
261 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
262 ps2esdi_drives = hdind + 1; /* increment index for the next time */
263 #endif
264 } /* ed_setup */
266 static int ps2esdi_getinfo(char *buf, int slot, void *d)
268 int len = 0;
270 len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
271 dma_arb_level);
272 len += sprintf(buf + len, "IO Port: %x\n", io_base);
273 len += sprintf(buf + len, "IRQ: 14\n");
274 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
276 return len;
279 /* ps2 esdi specific initialization - called thru the gendisk chain */
280 static int __init ps2esdi_geninit(void)
283 The first part contains the initialization code
284 for the ESDI disk subsystem. All we really do
285 is search for the POS registers of the controller
286 to do some simple setup operations. First, we
287 must ensure that the controller is installed,
288 enabled, and configured as PRIMARY. Then we must
289 determine the DMA arbitration level being used by
290 the controller so we can handle data transfer
291 operations properly. If all of this works, then
292 we will set the INIT_FLAG to a non-zero value.
295 int slot = 0, i, reset_start, reset_end;
296 u_char status;
297 unsigned short adapterID;
298 int error = 0;
300 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
301 adapterID = INTG_ESDI_ID;
302 printk("%s: integrated ESDI adapter found in slot %d\n",
303 DEVICE_NAME, slot+1);
304 #ifndef MODULE
305 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
306 #endif
307 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
308 adapterID = NRML_ESDI_ID;
309 printk("%s: normal ESDI adapter found in slot %d\n",
310 DEVICE_NAME, slot+1);
311 mca_set_adapter_name(slot, "PS/2 ESDI");
312 } else {
313 return -ENODEV;
316 ps2esdi_slot = slot;
317 mca_mark_as_used(slot);
318 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
320 /* Found the slot - read the POS register 2 to get the necessary
321 configuration and status information. POS register 2 has the
322 following information :
323 Bit Function
324 7 reserved = 0
325 6 arbitration method
326 0 - fairness enabled
327 1 - fairness disabled, linear priority assignment
328 5-2 arbitration level
329 1 alternate address
330 1 alternate address
331 0 - use addresses 0x3510 - 0x3517
332 0 adapter enable
335 status = mca_read_stored_pos(slot, 2);
336 /* is it enabled ? */
337 if (!(status & STATUS_ENABLED)) {
338 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
339 error = -ENODEV;
340 goto err_out1;
342 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
343 share with the SCSI driver */
344 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
345 SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
346 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
347 SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
349 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
350 error = -EBUSY;
351 goto err_out1;
353 if (status & STATUS_ALTERNATE)
354 io_base = ALT_IO_BASE;
355 else
356 io_base = PRIMARY_IO_BASE;
358 if (!request_region(io_base, 4, "ed")) {
359 printk(KERN_WARNING"Unable to request region 0x%x\n", io_base);
360 error = -EBUSY;
361 goto err_out2;
363 /* get the dma arbitration level */
364 dma_arb_level = (status >> 2) & 0xf;
366 /* BA */
367 printk("%s: DMA arbitration level : %d\n",
368 DEVICE_NAME, dma_arb_level);
370 LITE_ON;
371 current_int_handler = ps2esdi_initial_reset_int_handler;
372 reset_ctrl();
373 reset_status = 0;
374 reset_start = jiffies;
375 while (!reset_status) {
376 init_timer(&esdi_timer);
377 esdi_timer.expires = jiffies + HZ;
378 esdi_timer.data = 0;
379 add_timer(&esdi_timer);
380 sleep_on(&ps2esdi_int);
382 reset_end = jiffies;
383 LITE_OFF;
384 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
385 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
386 (reset_end - reset_start) % HZ);
389 /* Integrated ESDI Disk and Controller has only one drive! */
390 if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
391 ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1;
396 /* finally this part sets up some global data structures etc. */
398 ps2esdi_get_device_cfg();
400 /* some annoyance in the above routine returns TWO drives?
401 Is something else happining in the background?
402 Regaurdless we fix the # of drives again. AJK */
403 /* Integrated ESDI Disk and Controller has only one drive! */
404 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
405 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */
407 current_int_handler = ps2esdi_normal_interrupt_handler;
409 if (request_dma(dma_arb_level, "ed") !=0) {
410 printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n"
411 ,(int) dma_arb_level);
412 error = -EBUSY;
413 goto err_out3;
415 blk_queue_max_sectors(ps2esdi_queue, 128);
417 error = -ENOMEM;
418 for (i = 0; i < ps2esdi_drives; i++) {
419 struct gendisk *disk = alloc_disk(64);
420 if (!disk)
421 goto err_out4;
422 disk->major = PS2ESDI_MAJOR;
423 disk->first_minor = i<<6;
424 sprintf(disk->disk_name, "ed%c", 'a'+i);
425 sprintf(disk->devfs_name, "ed/target%d", i);
426 disk->fops = &ps2esdi_fops;
427 ps2esdi_gendisk[i] = disk;
430 for (i = 0; i < ps2esdi_drives; i++) {
431 struct gendisk *disk = ps2esdi_gendisk[i];
432 set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect *
433 ps2esdi_info[i].cyl);
434 disk->queue = ps2esdi_queue;
435 disk->private_data = &ps2esdi_info[i];
436 add_disk(disk);
438 return 0;
439 err_out4:
440 while (i--)
441 put_disk(ps2esdi_gendisk[i]);
442 err_out3:
443 release_region(io_base, 4);
444 err_out2:
445 free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
446 err_out1:
447 if(ps2esdi_slot) {
448 mca_mark_as_unused(ps2esdi_slot);
449 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
451 return error;
454 static void __init ps2esdi_get_device_cfg(void)
456 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
458 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
459 current_int_handler = ps2esdi_geometry_int_handler;
460 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
461 cmd_blk[1] = 0;
462 no_int_yet = TRUE;
463 ps2esdi_out_cmd_blk(cmd_blk);
464 if (no_int_yet)
465 sleep_on(&ps2esdi_int);
467 if (ps2esdi_drives > 1) {
468 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
469 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
470 cmd_blk[1] = 0;
471 no_int_yet = TRUE;
472 ps2esdi_out_cmd_blk(cmd_blk);
473 if (no_int_yet)
474 sleep_on(&ps2esdi_int);
475 } /* if second physical drive is present */
476 return;
479 /* strategy routine that handles most of the IO requests */
480 static void do_ps2esdi_request(request_queue_t * q)
482 struct request *req;
483 /* since, this routine is called with interrupts cleared - they
484 must be before it finishes */
486 req = elv_next_request(q);
487 if (!req)
488 return;
490 #if 0
491 printk("%s:got request. device : %s command : %d sector : %ld count : %ld, buffer: %p\n",
492 DEVICE_NAME,
493 req->rq_disk->disk_name,
494 req->cmd, req->sector,
495 req->current_nr_sectors, req->buffer);
496 #endif
498 /* check for above 16Mb dmas */
499 if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) {
500 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
501 end_request(req, FAIL);
502 return;
505 if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) {
506 printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n",
507 ps2esdi_drives, req->sector,
508 (unsigned long long)get_capacity(req->rq_disk));
509 end_request(req, FAIL);
510 return;
513 switch (rq_data_dir(req)) {
514 case READ:
515 ps2esdi_readwrite(READ, req);
516 break;
517 case WRITE:
518 ps2esdi_readwrite(WRITE, req);
519 break;
520 default:
521 printk("%s: Unknown command\n", req->rq_disk->disk_name);
522 end_request(req, FAIL);
523 break;
524 } /* handle different commands */
525 } /* main strategy routine */
527 /* resets the ESDI adapter */
528 static void reset_ctrl(void)
531 u_long expire;
532 u_short status;
534 /* enable interrupts on the controller */
535 status = inb(ESDI_INTRPT);
536 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
537 any interrupt pending... */
538 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
540 /* read the ESDI status port - if the controller is not busy,
541 simply do a soft reset (fast) - otherwise we'll have to do a
542 hard (slow) reset. */
543 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
544 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
545 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
547 /* soft reset */
548 else {
549 /*BA */
550 printk("%s: hard reset...\n", DEVICE_NAME);
551 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
552 expire = jiffies + 2*HZ;
553 while (time_before(jiffies, expire));
554 outb_p(1, ESDI_CONTROL);
555 } /* hard reset */
558 } /* reset the controller */
560 /* called by the strategy routine to handle read and write requests */
561 static void ps2esdi_readwrite(int cmd, struct request *req)
563 struct ps2esdi_i_struct *p = req->rq_disk->private_data;
564 unsigned block = req->sector;
565 unsigned count = req->current_nr_sectors;
566 int drive = p - ps2esdi_info;
567 u_short track, head, cylinder, sector;
568 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
570 /* do some relevant arithmatic */
571 track = block / p->sect;
572 head = track % p->head;
573 cylinder = track / p->head;
574 sector = block % p->sect;
576 #if 0
577 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
578 #endif
579 /* call the routine that actually fills out a command block */
580 ps2esdi_fill_cmd_block
581 (cmd_blk,
582 (cmd == READ) ? CMD_READ : CMD_WRITE,
583 cylinder, head, sector, count, drive);
585 /* send the command block to the controller */
586 current_req = req;
587 spin_unlock_irq(&ps2esdi_lock);
588 if (ps2esdi_out_cmd_blk(cmd_blk)) {
589 spin_lock_irq(&ps2esdi_lock);
590 printk("%s: Controller failed\n", DEVICE_NAME);
591 if ((++req->errors) >= MAX_RETRIES)
592 end_request(req, FAIL);
594 /* check for failure to put out the command block */
595 else {
596 spin_lock_irq(&ps2esdi_lock);
597 #if 0
598 printk("%s: waiting for xfer\n", DEVICE_NAME);
599 #endif
600 /* turn disk lights on */
601 LITE_ON;
604 } /* ps2esdi_readwrite */
606 /* fill out the command block */
607 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
608 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
611 cmd_blk[0] = (drive << 5) | cmd;
612 cmd_blk[1] = length;
613 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
614 cmd_blk[3] = (cyl & 0x3E0) >> 5;
616 } /* fill out the command block */
618 /* write a command block to the controller */
619 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
622 int i;
623 unsigned long jif;
624 u_char status;
626 /* enable interrupts */
627 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
629 /* do not write to the controller, if it is busy */
630 for (jif = jiffies + ESDI_STAT_TIMEOUT;
631 time_after(jif, jiffies) &&
632 (inb(ESDI_STATUS) & STATUS_BUSY); )
635 #if 0
636 printk("%s: i(1)=%ld\n", DEVICE_NAME, jif);
637 #endif
639 /* if device is still busy - then just time out */
640 if (inb(ESDI_STATUS) & STATUS_BUSY) {
641 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
642 return ERROR;
643 } /* timeout ??? */
644 /* Set up the attention register in the controller */
645 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
647 #if 0
648 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
649 #endif
651 /* one by one send each word out */
652 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
653 status = inb(ESDI_STATUS);
654 for (jif = jiffies + ESDI_STAT_TIMEOUT;
655 time_after(jif, jiffies) && (status & STATUS_BUSY) &&
656 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
657 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
658 #if 0
659 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
660 #endif
661 outw(*cmd_blk++, ESDI_CMD_INT);
662 } else {
663 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
664 DEVICE_NAME, status);
665 return ERROR;
667 } /* send all words out */
668 return OK;
669 } /* send out the commands */
672 /* prepare for dma - do all the necessary setup */
673 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
675 unsigned long flags = claim_dma_lock();
677 mca_disable_dma(dma_arb_level);
679 mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer));
681 mca_set_dma_count(dma_arb_level, length * 512 / 2);
683 mca_set_dma_mode(dma_arb_level, dma_xmode);
685 mca_enable_dma(dma_arb_level);
687 release_dma_lock(flags);
689 } /* prepare for dma */
693 static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
694 struct pt_regs *regs)
696 u_int int_ret_code;
698 if (inb(ESDI_STATUS) & STATUS_INTR) {
699 int_ret_code = inb(ESDI_INTRPT);
700 if (current_int_handler) {
701 /* Disable adapter interrupts till processing is finished */
702 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
703 current_int_handler(int_ret_code);
704 } else
705 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
706 } else {
707 return IRQ_NONE;
709 return IRQ_HANDLED;
712 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
715 switch (int_ret_code & 0xf) {
716 case INT_RESET:
717 /*BA */
718 printk("%s: initial reset completed.\n", DEVICE_NAME);
719 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
720 wake_up(&ps2esdi_int);
721 break;
722 case INT_ATTN_ERROR:
723 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
724 int_ret_code);
725 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
726 break;
727 default:
728 printk("%s: initial reset handler received interrupt: %02X\n",
729 DEVICE_NAME, int_ret_code);
730 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
731 break;
733 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
737 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
739 u_int status, drive_num;
740 unsigned long rba;
741 int i;
743 drive_num = int_ret_code >> 5;
744 switch (int_ret_code & 0xf) {
745 case INT_CMD_COMPLETE:
746 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
747 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
748 printk("%s: timeout reading status word\n", DEVICE_NAME);
749 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
750 break;
752 status = inw(ESDI_STT_INT);
753 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
754 #define REPLY_WORDS 5 /* we already read word 0 */
755 u_short reply[REPLY_WORDS];
757 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
758 /*BA */
759 printk("%s: Device Configuration Status for drive %u\n",
760 DEVICE_NAME, drive_num);
762 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
764 printk
765 ("Config bits: %s%s%s%s%s\n",
766 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
767 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
768 ? "Zero Defect, " : "Defects Present, ",
769 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
770 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
771 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
773 rba = reply[1] | ((unsigned long) reply[2] << 16);
774 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
776 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
777 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
779 if (!ps2esdi_info[drive_num].head) {
780 ps2esdi_info[drive_num].head = 64;
781 ps2esdi_info[drive_num].sect = 32;
782 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
783 ps2esdi_info[drive_num].wpcom = 0;
784 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
785 ps2esdi_info[drive_num].ctl = 8;
786 if (tp720esdi) { /* store the retrieved parameters */
787 ps2esdi_info[0].head = reply[4] & 0Xff;
788 ps2esdi_info[0].sect = reply[4] >> 8;
789 ps2esdi_info[0].cyl = reply[3];
790 ps2esdi_info[0].wpcom = 0;
791 ps2esdi_info[0].lzone = reply[3];
792 } else {
793 if (!intg_esdi)
794 ps2esdi_drives++;
797 #ifdef OBSOLETE
798 if (!ps2esdi_info[drive_num].head) {
799 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
800 ps2esdi_info[drive_num].sect = reply[4] >> 8;
801 ps2esdi_info[drive_num].cyl = reply[3];
802 ps2esdi_info[drive_num].wpcom = 0;
803 ps2esdi_info[drive_num].lzone = reply[3];
804 if (tp720esdi) { /* store the retrieved parameters */
805 ps2esdi_info[0].head = reply[4] & 0Xff;
806 ps2esdi_info[0].sect = reply[4] >> 8;
807 ps2esdi_info[0].cyl = reply[3];
808 ps2esdi_info[0].wpcom = 0;
809 ps2esdi_info[0].lzone = reply[3];
810 } else {
811 ps2esdi_drives++;
814 #endif
816 } else
817 printk("%s: failed while getting device config\n", DEVICE_NAME);
818 #undef REPLY_WORDS
819 } else
820 printk("%s: command %02X unknown by geometry handler\n",
821 DEVICE_NAME, status & 0x1f);
823 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
824 break;
826 case INT_ATTN_ERROR:
827 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
828 int_ret_code);
829 printk("%s: Device not available\n", DEVICE_NAME);
830 break;
831 case INT_CMD_ECC:
832 case INT_CMD_RETRY:
833 case INT_CMD_ECC_RETRY:
834 case INT_CMD_WARNING:
835 case INT_CMD_ABORT:
836 case INT_CMD_FAILED:
837 case INT_DMA_ERR:
838 case INT_CMD_BLK_ERR:
839 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
840 dump_cmd_complete_status(int_ret_code);
841 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
842 break;
843 default:
844 printk("%s: Unknown interrupt reason: %02X\n",
845 DEVICE_NAME, int_ret_code & 0xf);
846 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
847 break;
850 wake_up(&ps2esdi_int);
851 no_int_yet = FALSE;
852 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
856 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
858 unsigned long flags;
859 u_int status;
860 u_int ending;
861 int i;
863 switch (int_ret_code & 0x0f) {
864 case INT_TRANSFER_REQ:
865 ps2esdi_prep_dma(current_req->buffer,
866 current_req->current_nr_sectors,
867 (rq_data_dir(current_req) == READ)
868 ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
869 : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
870 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
871 ending = -1;
872 break;
874 case INT_ATTN_ERROR:
875 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
876 int_ret_code);
877 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
878 ending = FAIL;
879 break;
881 case INT_CMD_COMPLETE:
882 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
883 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
884 printk("%s: timeout reading status word\n", DEVICE_NAME);
885 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
886 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
887 if ((++current_req->errors) >= MAX_RETRIES)
888 ending = FAIL;
889 else
890 ending = -1;
891 break;
893 status = inw(ESDI_STT_INT);
894 switch (status & 0x1F) {
895 case (CMD_READ & 0xff):
896 case (CMD_WRITE & 0xff):
897 LITE_OFF;
898 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
899 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
900 ending = SUCCES;
901 break;
902 default:
903 printk("%s: interrupt for unknown command %02X\n",
904 DEVICE_NAME, status & 0x1f);
905 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
906 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
907 ending = -1;
908 break;
910 break;
911 case INT_CMD_ECC:
912 case INT_CMD_RETRY:
913 case INT_CMD_ECC_RETRY:
914 LITE_OFF;
915 dump_cmd_complete_status(int_ret_code);
916 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
917 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
918 ending = SUCCES;
919 break;
920 case INT_CMD_WARNING:
921 case INT_CMD_ABORT:
922 case INT_CMD_FAILED:
923 case INT_DMA_ERR:
924 LITE_OFF;
925 dump_cmd_complete_status(int_ret_code);
926 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
927 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
928 if ((++current_req->errors) >= MAX_RETRIES)
929 ending = FAIL;
930 else
931 ending = -1;
932 break;
934 case INT_CMD_BLK_ERR:
935 dump_cmd_complete_status(int_ret_code);
936 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
937 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
938 ending = FAIL;
939 break;
941 case INT_CMD_FORMAT:
942 printk("%s: huh ? Who issued this format command ?\n"
943 ,DEVICE_NAME);
944 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
945 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
946 ending = -1;
947 break;
949 case INT_RESET:
950 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
951 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
952 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
953 ending = -1;
954 break;
956 default:
957 printk("%s: Unknown interrupt reason: %02X\n",
958 DEVICE_NAME, int_ret_code & 0xf);
959 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
960 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
961 ending = -1;
962 break;
964 if(ending != -1) {
965 spin_lock_irqsave(&ps2esdi_lock, flags);
966 end_request(current_req, ending);
967 current_req = NULL;
968 do_ps2esdi_request(ps2esdi_queue);
969 spin_unlock_irqrestore(&ps2esdi_lock, flags);
971 } /* handle interrupts */
975 static int ps2esdi_read_status_words(int num_words,
976 int max_words,
977 u_short * buffer)
979 int i;
981 for (; max_words && num_words; max_words--, num_words--, buffer++) {
982 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
983 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
984 printk("%s: timeout reading status word\n", DEVICE_NAME);
985 return FAIL;
987 *buffer = inw(ESDI_STT_INT);
989 return SUCCES;
995 static void dump_cmd_complete_status(u_int int_ret_code)
997 #define WAIT_FOR_STATUS \
998 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
999 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
1000 printk("%s: timeout reading status word\n",DEVICE_NAME); \
1001 return; \
1004 int i, word_count;
1005 u_short stat_word;
1006 u_long rba;
1008 printk("%s: Device: %u, interrupt ID: %02X\n",
1009 DEVICE_NAME, int_ret_code >> 5,
1010 int_ret_code & 0xf);
1012 WAIT_FOR_STATUS;
1013 stat_word = inw(ESDI_STT_INT);
1014 word_count = (stat_word >> 8) - 1;
1015 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1016 stat_word & 0xff);
1018 if (word_count--) {
1019 WAIT_FOR_STATUS;
1020 stat_word = inw(ESDI_STT_INT);
1021 printk("%s: command status code: %02X, command error code: %02X\n",
1022 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1024 if (word_count--) {
1025 WAIT_FOR_STATUS;
1026 stat_word = inw(ESDI_STT_INT);
1027 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1028 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1029 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1030 (stat_word & 0x0400) ? "Write Fault, " : "",
1031 (stat_word & 0x0200) ? "Track 0, " : "",
1032 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1033 stat_word >> 8);
1035 if (word_count--) {
1036 WAIT_FOR_STATUS;
1037 stat_word = inw(ESDI_STT_INT);
1038 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1040 if (word_count -= 2) {
1041 WAIT_FOR_STATUS;
1042 rba = inw(ESDI_STT_INT);
1043 WAIT_FOR_STATUS;
1044 rba |= inw(ESDI_STT_INT) << 16;
1045 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1046 (u_short) ((rba & 0x1ff80000) >> 11),
1047 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1048 } else
1049 printk("\n");
1051 if (word_count--) {
1052 WAIT_FOR_STATUS;
1053 stat_word = inw(ESDI_STT_INT);
1054 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1056 printk("\n");
1058 #undef WAIT_FOR_STATUS
1062 static int ps2esdi_ioctl(struct inode *inode,
1063 struct file *file, u_int cmd, u_long arg)
1065 struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data;
1066 struct ps2esdi_geometry geom;
1068 if (cmd != HDIO_GETGEO)
1069 return -EINVAL;
1070 memset(&geom, 0, sizeof(geom));
1071 geom.heads = p->head;
1072 geom.sectors = p->sect;
1073 geom.cylinders = p->cyl;
1074 geom.start = get_start_sect(inode->i_bdev);
1075 if (copy_to_user((void __user *)arg, &geom, sizeof(geom)))
1076 return -EFAULT;
1077 return 0;
1080 static void ps2esdi_reset_timer(unsigned long unused)
1083 int status;
1085 status = inb(ESDI_INTRPT);
1086 if ((status & 0xf) == INT_RESET) {
1087 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1088 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1089 reset_status = 1;
1091 wake_up(&ps2esdi_int);