ps3: vuart: fix error path locking
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / block / ps2esdi.c
blob3c796e236253aba664e45894b614d52609448055
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/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>
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(struct request_queue * 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 static void (*current_int_handler) (u_int) = NULL;
80 static void ps2esdi_normal_interrupt_handler(u_int);
81 static void ps2esdi_initial_reset_int_handler(u_int);
82 static void ps2esdi_geometry_int_handler(u_int);
83 static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
85 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
87 static void dump_cmd_complete_status(u_int int_ret_code);
89 static void ps2esdi_get_device_cfg(void);
91 static void ps2esdi_reset_timer(unsigned long unused);
93 static u_int dma_arb_level; /* DMA arbitration level */
95 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
97 static int no_int_yet;
98 static int ps2esdi_drives;
99 static u_short io_base;
100 static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0);
101 static int reset_status;
102 static int ps2esdi_slot = -1;
103 static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
104 static int intg_esdi = 0; /* If integrated adapter */
105 struct ps2esdi_i_struct {
106 unsigned int head, sect, cyl, wpcom, lzone, ctl;
108 static DEFINE_SPINLOCK(ps2esdi_lock);
109 static struct request_queue *ps2esdi_queue;
110 static struct request *current_req;
112 #if 0
113 #if 0 /* try both - I don't know which one is better... UB */
114 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
116 {4, 48, 1553, 0, 0, 0},
117 {0, 0, 0, 0, 0, 0}};
118 #else
119 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
121 {64, 32, 161, 0, 0, 0},
122 {0, 0, 0, 0, 0, 0}};
123 #endif
124 #endif
125 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
127 {0, 0, 0, 0, 0, 0},
128 {0, 0, 0, 0, 0, 0}};
130 static struct block_device_operations ps2esdi_fops =
132 .owner = THIS_MODULE,
133 .getgeo = ps2esdi_getgeo,
136 static struct gendisk *ps2esdi_gendisk[2];
138 /* initialization routine called by ll_rw_blk.c */
139 static int __init ps2esdi_init(void)
142 int error = 0;
144 /* register the device - pass the name and major number */
145 if (register_blkdev(PS2ESDI_MAJOR, "ed"))
146 return -EBUSY;
148 /* set up some global information - indicating device specific info */
149 ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock);
150 if (!ps2esdi_queue) {
151 unregister_blkdev(PS2ESDI_MAJOR, "ed");
152 return -ENOMEM;
155 /* some minor housekeeping - setup the global gendisk structure */
156 error = ps2esdi_geninit();
157 if (error) {
158 printk(KERN_WARNING "PS2ESDI: error initialising"
159 " device, releasing resources\n");
160 unregister_blkdev(PS2ESDI_MAJOR, "ed");
161 blk_cleanup_queue(ps2esdi_queue);
162 return error;
164 return 0;
165 } /* ps2esdi_init */
167 #ifndef MODULE
169 module_init(ps2esdi_init);
171 #else
173 static int cyl[MAX_HD] = {-1,-1};
174 static int head[MAX_HD] = {-1, -1};
175 static int sect[MAX_HD] = {-1, -1};
177 module_param(tp720esdi, bool, 0);
178 module_param_array(cyl, int, NULL, 0);
179 module_param_array(head, int, NULL, 0);
180 module_param_array(sect, int, NULL, 0);
181 MODULE_LICENSE("GPL");
183 int init_module(void) {
184 int drive;
186 for(drive = 0; drive < MAX_HD; drive++) {
187 struct ps2esdi_i_struct *info = &ps2esdi_info[drive];
189 if (cyl[drive] != -1) {
190 info->cyl = info->lzone = cyl[drive];
191 info->wpcom = 0;
193 if (head[drive] != -1) {
194 info->head = head[drive];
195 info->ctl = (head[drive] > 8 ? 8 : 0);
197 if (sect[drive] != -1) info->sect = sect[drive];
199 return ps2esdi_init();
202 void
203 cleanup_module(void) {
204 int i;
205 if(ps2esdi_slot) {
206 mca_mark_as_unused(ps2esdi_slot);
207 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
209 release_region(io_base, 4);
210 free_dma(dma_arb_level);
211 free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
212 unregister_blkdev(PS2ESDI_MAJOR, "ed");
213 blk_cleanup_queue(ps2esdi_queue);
214 for (i = 0; i < ps2esdi_drives; i++) {
215 del_gendisk(ps2esdi_gendisk[i]);
216 put_disk(ps2esdi_gendisk[i]);
219 #endif /* MODULE */
221 /* handles boot time command line parameters */
222 void __init tp720_setup(char *str, int *ints)
224 /* no params, just sets the tp720esdi flag if it exists */
226 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
227 tp720esdi = 1;
230 void __init ed_setup(char *str, int *ints)
232 int hdind = 0;
234 /* handles 3 parameters only - corresponding to
235 1. Number of cylinders
236 2. Number of heads
237 3. Sectors/track
240 if (ints[0] != 3)
241 return;
243 /* print out the information - seen at boot time */
244 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
245 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
247 /* set the index into device specific information table */
248 if (ps2esdi_info[0].head != 0)
249 hdind = 1;
251 /* set up all the device information */
252 ps2esdi_info[hdind].head = ints[2];
253 ps2esdi_info[hdind].sect = ints[3];
254 ps2esdi_info[hdind].cyl = ints[1];
255 ps2esdi_info[hdind].wpcom = 0;
256 ps2esdi_info[hdind].lzone = ints[1];
257 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
258 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
259 ps2esdi_drives = hdind + 1; /* increment index for the next time */
260 #endif
261 } /* ed_setup */
263 static int ps2esdi_getinfo(char *buf, int slot, void *d)
265 int len = 0;
267 len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
268 dma_arb_level);
269 len += sprintf(buf + len, "IO Port: %x\n", io_base);
270 len += sprintf(buf + len, "IRQ: 14\n");
271 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
273 return len;
276 /* ps2 esdi specific initialization - called thru the gendisk chain */
277 static int __init ps2esdi_geninit(void)
280 The first part contains the initialization code
281 for the ESDI disk subsystem. All we really do
282 is search for the POS registers of the controller
283 to do some simple setup operations. First, we
284 must ensure that the controller is installed,
285 enabled, and configured as PRIMARY. Then we must
286 determine the DMA arbitration level being used by
287 the controller so we can handle data transfer
288 operations properly. If all of this works, then
289 we will set the INIT_FLAG to a non-zero value.
292 int slot = 0, i, reset_start, reset_end;
293 u_char status;
294 unsigned short adapterID;
295 int error = 0;
297 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
298 adapterID = INTG_ESDI_ID;
299 printk("%s: integrated ESDI adapter found in slot %d\n",
300 DEVICE_NAME, slot+1);
301 #ifndef MODULE
302 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
303 #endif
304 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
305 adapterID = NRML_ESDI_ID;
306 printk("%s: normal ESDI adapter found in slot %d\n",
307 DEVICE_NAME, slot+1);
308 mca_set_adapter_name(slot, "PS/2 ESDI");
309 } else {
310 return -ENODEV;
313 ps2esdi_slot = slot;
314 mca_mark_as_used(slot);
315 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
317 /* Found the slot - read the POS register 2 to get the necessary
318 configuration and status information. POS register 2 has the
319 following information :
320 Bit Function
321 7 reserved = 0
322 6 arbitration method
323 0 - fairness enabled
324 1 - fairness disabled, linear priority assignment
325 5-2 arbitration level
326 1 alternate address
327 1 alternate address
328 0 - use addresses 0x3510 - 0x3517
329 0 adapter enable
332 status = mca_read_stored_pos(slot, 2);
333 /* is it enabled ? */
334 if (!(status & STATUS_ENABLED)) {
335 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
336 error = -ENODEV;
337 goto err_out1;
339 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
340 share with the SCSI driver */
341 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
342 IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk)
343 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
344 IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk)
346 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
347 error = -EBUSY;
348 goto err_out1;
350 if (status & STATUS_ALTERNATE)
351 io_base = ALT_IO_BASE;
352 else
353 io_base = PRIMARY_IO_BASE;
355 if (!request_region(io_base, 4, "ed")) {
356 printk(KERN_WARNING"Unable to request region 0x%x\n", io_base);
357 error = -EBUSY;
358 goto err_out2;
360 /* get the dma arbitration level */
361 dma_arb_level = (status >> 2) & 0xf;
363 /* BA */
364 printk("%s: DMA arbitration level : %d\n",
365 DEVICE_NAME, dma_arb_level);
367 LITE_ON;
368 current_int_handler = ps2esdi_initial_reset_int_handler;
369 reset_ctrl();
370 reset_status = 0;
371 reset_start = jiffies;
372 while (!reset_status) {
373 init_timer(&esdi_timer);
374 esdi_timer.expires = jiffies + HZ;
375 esdi_timer.data = 0;
376 add_timer(&esdi_timer);
377 sleep_on(&ps2esdi_int);
379 reset_end = jiffies;
380 LITE_OFF;
381 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
382 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
383 (reset_end - reset_start) % HZ);
386 /* Integrated ESDI Disk and Controller has only one drive! */
387 if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
388 ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1;
393 /* finally this part sets up some global data structures etc. */
395 ps2esdi_get_device_cfg();
397 /* some annoyance in the above routine returns TWO drives?
398 Is something else happining in the background?
399 Regaurdless we fix the # of drives again. AJK */
400 /* Integrated ESDI Disk and Controller has only one drive! */
401 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
402 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */
404 current_int_handler = ps2esdi_normal_interrupt_handler;
406 if (request_dma(dma_arb_level, "ed") !=0) {
407 printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n"
408 ,(int) dma_arb_level);
409 error = -EBUSY;
410 goto err_out3;
412 blk_queue_max_sectors(ps2esdi_queue, 128);
414 error = -ENOMEM;
415 for (i = 0; i < ps2esdi_drives; i++) {
416 struct gendisk *disk = alloc_disk(64);
417 if (!disk)
418 goto err_out4;
419 disk->major = PS2ESDI_MAJOR;
420 disk->first_minor = i<<6;
421 sprintf(disk->disk_name, "ed%c", 'a'+i);
422 disk->fops = &ps2esdi_fops;
423 ps2esdi_gendisk[i] = disk;
426 for (i = 0; i < ps2esdi_drives; i++) {
427 struct gendisk *disk = ps2esdi_gendisk[i];
428 set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect *
429 ps2esdi_info[i].cyl);
430 disk->queue = ps2esdi_queue;
431 disk->private_data = &ps2esdi_info[i];
432 add_disk(disk);
434 return 0;
435 err_out4:
436 while (i--)
437 put_disk(ps2esdi_gendisk[i]);
438 err_out3:
439 release_region(io_base, 4);
440 err_out2:
441 free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
442 err_out1:
443 if(ps2esdi_slot) {
444 mca_mark_as_unused(ps2esdi_slot);
445 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
447 return error;
450 static void __init ps2esdi_get_device_cfg(void)
452 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
454 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
455 current_int_handler = ps2esdi_geometry_int_handler;
456 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
457 cmd_blk[1] = 0;
458 no_int_yet = TRUE;
459 ps2esdi_out_cmd_blk(cmd_blk);
460 if (no_int_yet)
461 sleep_on(&ps2esdi_int);
463 if (ps2esdi_drives > 1) {
464 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
465 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
466 cmd_blk[1] = 0;
467 no_int_yet = TRUE;
468 ps2esdi_out_cmd_blk(cmd_blk);
469 if (no_int_yet)
470 sleep_on(&ps2esdi_int);
471 } /* if second physical drive is present */
472 return;
475 /* strategy routine that handles most of the IO requests */
476 static void do_ps2esdi_request(struct request_queue * q)
478 struct request *req;
479 /* since, this routine is called with interrupts cleared - they
480 must be before it finishes */
482 req = elv_next_request(q);
483 if (!req)
484 return;
486 #if 0
487 printk("%s:got request. device : %s command : %d sector : %ld count : %ld, buffer: %p\n",
488 DEVICE_NAME,
489 req->rq_disk->disk_name,
490 req->cmd, req->sector,
491 req->current_nr_sectors, req->buffer);
492 #endif
494 /* check for above 16Mb dmas */
495 if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) {
496 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
497 end_request(req, FAIL);
498 return;
501 if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) {
502 printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n",
503 ps2esdi_drives, req->sector,
504 (unsigned long long)get_capacity(req->rq_disk));
505 end_request(req, FAIL);
506 return;
509 switch (rq_data_dir(req)) {
510 case READ:
511 ps2esdi_readwrite(READ, req);
512 break;
513 case WRITE:
514 ps2esdi_readwrite(WRITE, req);
515 break;
516 default:
517 printk("%s: Unknown command\n", req->rq_disk->disk_name);
518 end_request(req, FAIL);
519 break;
520 } /* handle different commands */
521 } /* main strategy routine */
523 /* resets the ESDI adapter */
524 static void reset_ctrl(void)
527 u_long expire;
528 u_short status;
530 /* enable interrupts on the controller */
531 status = inb(ESDI_INTRPT);
532 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
533 any interrupt pending... */
534 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
536 /* read the ESDI status port - if the controller is not busy,
537 simply do a soft reset (fast) - otherwise we'll have to do a
538 hard (slow) reset. */
539 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
540 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
541 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
543 /* soft reset */
544 else {
545 /*BA */
546 printk("%s: hard reset...\n", DEVICE_NAME);
547 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
548 expire = jiffies + 2*HZ;
549 while (time_before(jiffies, expire));
550 outb_p(1, ESDI_CONTROL);
551 } /* hard reset */
554 } /* reset the controller */
556 /* called by the strategy routine to handle read and write requests */
557 static void ps2esdi_readwrite(int cmd, struct request *req)
559 struct ps2esdi_i_struct *p = req->rq_disk->private_data;
560 unsigned block = req->sector;
561 unsigned count = req->current_nr_sectors;
562 int drive = p - ps2esdi_info;
563 u_short track, head, cylinder, sector;
564 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
566 /* do some relevant arithmatic */
567 track = block / p->sect;
568 head = track % p->head;
569 cylinder = track / p->head;
570 sector = block % p->sect;
572 #if 0
573 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
574 #endif
575 /* call the routine that actually fills out a command block */
576 ps2esdi_fill_cmd_block
577 (cmd_blk,
578 (cmd == READ) ? CMD_READ : CMD_WRITE,
579 cylinder, head, sector, count, drive);
581 /* send the command block to the controller */
582 current_req = req;
583 spin_unlock_irq(&ps2esdi_lock);
584 if (ps2esdi_out_cmd_blk(cmd_blk)) {
585 spin_lock_irq(&ps2esdi_lock);
586 printk("%s: Controller failed\n", DEVICE_NAME);
587 if ((++req->errors) >= MAX_RETRIES)
588 end_request(req, FAIL);
590 /* check for failure to put out the command block */
591 else {
592 spin_lock_irq(&ps2esdi_lock);
593 #if 0
594 printk("%s: waiting for xfer\n", DEVICE_NAME);
595 #endif
596 /* turn disk lights on */
597 LITE_ON;
600 } /* ps2esdi_readwrite */
602 /* fill out the command block */
603 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
604 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
607 cmd_blk[0] = (drive << 5) | cmd;
608 cmd_blk[1] = length;
609 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
610 cmd_blk[3] = (cyl & 0x3E0) >> 5;
612 } /* fill out the command block */
614 /* write a command block to the controller */
615 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
618 int i;
619 unsigned long jif;
620 u_char status;
622 /* enable interrupts */
623 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
625 /* do not write to the controller, if it is busy */
626 for (jif = jiffies + ESDI_STAT_TIMEOUT;
627 time_after(jif, jiffies) &&
628 (inb(ESDI_STATUS) & STATUS_BUSY); )
631 #if 0
632 printk("%s: i(1)=%ld\n", DEVICE_NAME, jif);
633 #endif
635 /* if device is still busy - then just time out */
636 if (inb(ESDI_STATUS) & STATUS_BUSY) {
637 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
638 return ERROR;
639 } /* timeout ??? */
640 /* Set up the attention register in the controller */
641 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
643 #if 0
644 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
645 #endif
647 /* one by one send each word out */
648 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
649 status = inb(ESDI_STATUS);
650 for (jif = jiffies + ESDI_STAT_TIMEOUT;
651 time_after(jif, jiffies) && (status & STATUS_BUSY) &&
652 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
653 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
654 #if 0
655 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
656 #endif
657 outw(*cmd_blk++, ESDI_CMD_INT);
658 } else {
659 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
660 DEVICE_NAME, status);
661 return ERROR;
663 } /* send all words out */
664 return OK;
665 } /* send out the commands */
668 /* prepare for dma - do all the necessary setup */
669 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
671 unsigned long flags = claim_dma_lock();
673 mca_disable_dma(dma_arb_level);
675 mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer));
677 mca_set_dma_count(dma_arb_level, length * 512 / 2);
679 mca_set_dma_mode(dma_arb_level, dma_xmode);
681 mca_enable_dma(dma_arb_level);
683 release_dma_lock(flags);
685 } /* prepare for dma */
689 static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id)
691 u_int int_ret_code;
693 if (inb(ESDI_STATUS) & STATUS_INTR) {
694 int_ret_code = inb(ESDI_INTRPT);
695 if (current_int_handler) {
696 /* Disable adapter interrupts till processing is finished */
697 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
698 current_int_handler(int_ret_code);
699 } else
700 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
701 } else {
702 return IRQ_NONE;
704 return IRQ_HANDLED;
707 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
710 switch (int_ret_code & 0xf) {
711 case INT_RESET:
712 /*BA */
713 printk("%s: initial reset completed.\n", DEVICE_NAME);
714 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
715 wake_up(&ps2esdi_int);
716 break;
717 case INT_ATTN_ERROR:
718 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
719 int_ret_code);
720 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
721 break;
722 default:
723 printk("%s: initial reset handler received interrupt: %02X\n",
724 DEVICE_NAME, int_ret_code);
725 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
726 break;
728 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
732 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
734 u_int status, drive_num;
735 unsigned long rba;
736 int i;
738 drive_num = int_ret_code >> 5;
739 switch (int_ret_code & 0xf) {
740 case INT_CMD_COMPLETE:
741 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
742 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
743 printk("%s: timeout reading status word\n", DEVICE_NAME);
744 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
745 break;
747 status = inw(ESDI_STT_INT);
748 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
749 #define REPLY_WORDS 5 /* we already read word 0 */
750 u_short reply[REPLY_WORDS];
752 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
753 /*BA */
754 printk("%s: Device Configuration Status for drive %u\n",
755 DEVICE_NAME, drive_num);
757 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
759 printk
760 ("Config bits: %s%s%s%s%s\n",
761 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
762 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
763 ? "Zero Defect, " : "Defects Present, ",
764 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
765 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
766 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
768 rba = reply[1] | ((unsigned long) reply[2] << 16);
769 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
771 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
772 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
774 if (!ps2esdi_info[drive_num].head) {
775 ps2esdi_info[drive_num].head = 64;
776 ps2esdi_info[drive_num].sect = 32;
777 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
778 ps2esdi_info[drive_num].wpcom = 0;
779 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
780 ps2esdi_info[drive_num].ctl = 8;
781 if (tp720esdi) { /* store the retrieved parameters */
782 ps2esdi_info[0].head = reply[4] & 0Xff;
783 ps2esdi_info[0].sect = reply[4] >> 8;
784 ps2esdi_info[0].cyl = reply[3];
785 ps2esdi_info[0].wpcom = 0;
786 ps2esdi_info[0].lzone = reply[3];
787 } else {
788 if (!intg_esdi)
789 ps2esdi_drives++;
792 #ifdef OBSOLETE
793 if (!ps2esdi_info[drive_num].head) {
794 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
795 ps2esdi_info[drive_num].sect = reply[4] >> 8;
796 ps2esdi_info[drive_num].cyl = reply[3];
797 ps2esdi_info[drive_num].wpcom = 0;
798 ps2esdi_info[drive_num].lzone = reply[3];
799 if (tp720esdi) { /* store the retrieved parameters */
800 ps2esdi_info[0].head = reply[4] & 0Xff;
801 ps2esdi_info[0].sect = reply[4] >> 8;
802 ps2esdi_info[0].cyl = reply[3];
803 ps2esdi_info[0].wpcom = 0;
804 ps2esdi_info[0].lzone = reply[3];
805 } else {
806 ps2esdi_drives++;
809 #endif
811 } else
812 printk("%s: failed while getting device config\n", DEVICE_NAME);
813 #undef REPLY_WORDS
814 } else
815 printk("%s: command %02X unknown by geometry handler\n",
816 DEVICE_NAME, status & 0x1f);
818 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
819 break;
821 case INT_ATTN_ERROR:
822 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
823 int_ret_code);
824 printk("%s: Device not available\n", DEVICE_NAME);
825 break;
826 case INT_CMD_ECC:
827 case INT_CMD_RETRY:
828 case INT_CMD_ECC_RETRY:
829 case INT_CMD_WARNING:
830 case INT_CMD_ABORT:
831 case INT_CMD_FAILED:
832 case INT_DMA_ERR:
833 case INT_CMD_BLK_ERR:
834 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
835 dump_cmd_complete_status(int_ret_code);
836 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
837 break;
838 default:
839 printk("%s: Unknown interrupt reason: %02X\n",
840 DEVICE_NAME, int_ret_code & 0xf);
841 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
842 break;
845 wake_up(&ps2esdi_int);
846 no_int_yet = FALSE;
847 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
851 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
853 unsigned long flags;
854 u_int status;
855 u_int ending;
856 int i;
858 switch (int_ret_code & 0x0f) {
859 case INT_TRANSFER_REQ:
860 ps2esdi_prep_dma(current_req->buffer,
861 current_req->current_nr_sectors,
862 (rq_data_dir(current_req) == READ)
863 ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
864 : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
865 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
866 ending = -1;
867 break;
869 case INT_ATTN_ERROR:
870 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
871 int_ret_code);
872 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
873 ending = FAIL;
874 break;
876 case INT_CMD_COMPLETE:
877 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
878 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
879 printk("%s: timeout reading status word\n", DEVICE_NAME);
880 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
881 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
882 if ((++current_req->errors) >= MAX_RETRIES)
883 ending = FAIL;
884 else
885 ending = -1;
886 break;
888 status = inw(ESDI_STT_INT);
889 switch (status & 0x1F) {
890 case (CMD_READ & 0xff):
891 case (CMD_WRITE & 0xff):
892 LITE_OFF;
893 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
894 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
895 ending = SUCCES;
896 break;
897 default:
898 printk("%s: interrupt for unknown command %02X\n",
899 DEVICE_NAME, status & 0x1f);
900 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
901 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
902 ending = -1;
903 break;
905 break;
906 case INT_CMD_ECC:
907 case INT_CMD_RETRY:
908 case INT_CMD_ECC_RETRY:
909 LITE_OFF;
910 dump_cmd_complete_status(int_ret_code);
911 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
912 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
913 ending = SUCCES;
914 break;
915 case INT_CMD_WARNING:
916 case INT_CMD_ABORT:
917 case INT_CMD_FAILED:
918 case INT_DMA_ERR:
919 LITE_OFF;
920 dump_cmd_complete_status(int_ret_code);
921 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
922 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
923 if ((++current_req->errors) >= MAX_RETRIES)
924 ending = FAIL;
925 else
926 ending = -1;
927 break;
929 case INT_CMD_BLK_ERR:
930 dump_cmd_complete_status(int_ret_code);
931 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
932 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
933 ending = FAIL;
934 break;
936 case INT_CMD_FORMAT:
937 printk("%s: huh ? Who issued this format command ?\n"
938 ,DEVICE_NAME);
939 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
940 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
941 ending = -1;
942 break;
944 case INT_RESET:
945 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
946 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
947 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
948 ending = -1;
949 break;
951 default:
952 printk("%s: Unknown interrupt reason: %02X\n",
953 DEVICE_NAME, int_ret_code & 0xf);
954 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
955 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
956 ending = -1;
957 break;
959 if(ending != -1) {
960 spin_lock_irqsave(&ps2esdi_lock, flags);
961 end_request(current_req, ending);
962 current_req = NULL;
963 do_ps2esdi_request(ps2esdi_queue);
964 spin_unlock_irqrestore(&ps2esdi_lock, flags);
966 } /* handle interrupts */
970 static int ps2esdi_read_status_words(int num_words,
971 int max_words,
972 u_short * buffer)
974 int i;
976 for (; max_words && num_words; max_words--, num_words--, buffer++) {
977 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
978 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
979 printk("%s: timeout reading status word\n", DEVICE_NAME);
980 return FAIL;
982 *buffer = inw(ESDI_STT_INT);
984 return SUCCES;
990 static void dump_cmd_complete_status(u_int int_ret_code)
992 #define WAIT_FOR_STATUS \
993 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
994 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
995 printk("%s: timeout reading status word\n",DEVICE_NAME); \
996 return; \
999 int i, word_count;
1000 u_short stat_word;
1001 u_long rba;
1003 printk("%s: Device: %u, interrupt ID: %02X\n",
1004 DEVICE_NAME, int_ret_code >> 5,
1005 int_ret_code & 0xf);
1007 WAIT_FOR_STATUS;
1008 stat_word = inw(ESDI_STT_INT);
1009 word_count = (stat_word >> 8) - 1;
1010 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1011 stat_word & 0xff);
1013 if (word_count--) {
1014 WAIT_FOR_STATUS;
1015 stat_word = inw(ESDI_STT_INT);
1016 printk("%s: command status code: %02X, command error code: %02X\n",
1017 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1019 if (word_count--) {
1020 WAIT_FOR_STATUS;
1021 stat_word = inw(ESDI_STT_INT);
1022 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1023 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1024 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1025 (stat_word & 0x0400) ? "Write Fault, " : "",
1026 (stat_word & 0x0200) ? "Track 0, " : "",
1027 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1028 stat_word >> 8);
1030 if (word_count--) {
1031 WAIT_FOR_STATUS;
1032 stat_word = inw(ESDI_STT_INT);
1033 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1035 if (word_count -= 2) {
1036 WAIT_FOR_STATUS;
1037 rba = inw(ESDI_STT_INT);
1038 WAIT_FOR_STATUS;
1039 rba |= inw(ESDI_STT_INT) << 16;
1040 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1041 (u_short) ((rba & 0x1ff80000) >> 11),
1042 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1043 } else
1044 printk("\n");
1046 if (word_count--) {
1047 WAIT_FOR_STATUS;
1048 stat_word = inw(ESDI_STT_INT);
1049 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1051 printk("\n");
1053 #undef WAIT_FOR_STATUS
1057 static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1059 struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
1061 geo->heads = p->head;
1062 geo->sectors = p->sect;
1063 geo->cylinders = p->cyl;
1064 return 0;
1067 static void ps2esdi_reset_timer(unsigned long unused)
1070 int status;
1072 status = inb(ESDI_INTRPT);
1073 if ((status & 0xf) == INT_RESET) {
1074 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1075 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1076 reset_status = 1;
1078 wake_up(&ps2esdi_int);