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