Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[sfrench/cifs-2.6.git] / 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/major.h>
33 #include <linux/errno.h>
34 #include <linux/wait.h>
35 #include <linux/interrupt.h>
36 #include <linux/fs.h>
37 #include <linux/kernel.h>
38 #include <linux/genhd.h>
39 #include <linux/ps2esdi.h>
40 #include <linux/blkdev.h>
41 #include <linux/mca-legacy.h>
42 #include <linux/init.h>
43 #include <linux/ioport.h>
44 #include <linux/module.h>
45 #include <linux/hdreg.h>
46
47 #include <asm/system.h>
48 #include <asm/io.h>
49 #include <asm/dma.h>
50 #include <asm/mca_dma.h>
51 #include <asm/uaccess.h>
52
53 #define PS2ESDI_IRQ 14
54 #define MAX_HD 2
55 #define MAX_RETRIES 5
56 #define MAX_16BIT 65536
57 #define ESDI_TIMEOUT   0xf000
58 #define ESDI_STAT_TIMEOUT 4
59
60 #define TYPE_0_CMD_BLK_LENGTH 2
61 #define TYPE_1_CMD_BLK_LENGTH 4
62
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                   IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk)
344             && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
345                            IRQF_SHARED, "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                 disk->fops = &ps2esdi_fops;
424                 ps2esdi_gendisk[i] = disk;
425         }
426
427         for (i = 0; i < ps2esdi_drives; i++) {
428                 struct gendisk *disk = ps2esdi_gendisk[i];
429                 set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect *
430                                 ps2esdi_info[i].cyl);
431                 disk->queue = ps2esdi_queue;
432                 disk->private_data = &ps2esdi_info[i];
433                 add_disk(disk);
434         }
435         return 0;
436 err_out4:
437         while (i--)
438                 put_disk(ps2esdi_gendisk[i]);
439 err_out3:
440         release_region(io_base, 4);
441 err_out2:
442         free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
443 err_out1:
444         if(ps2esdi_slot) {
445                 mca_mark_as_unused(ps2esdi_slot);
446                 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
447         }
448         return error;
449 }
450
451 static void __init ps2esdi_get_device_cfg(void)
452 {
453         u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
454
455         /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
456         current_int_handler = ps2esdi_geometry_int_handler;
457         cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
458         cmd_blk[1] = 0;
459         no_int_yet = TRUE;
460         ps2esdi_out_cmd_blk(cmd_blk);
461         if (no_int_yet)
462                 sleep_on(&ps2esdi_int);
463
464         if (ps2esdi_drives > 1) {
465                 printk("%s: Drive 1\n", DEVICE_NAME);   /*BA */
466                 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
467                 cmd_blk[1] = 0;
468                 no_int_yet = TRUE;
469                 ps2esdi_out_cmd_blk(cmd_blk);
470                 if (no_int_yet)
471                         sleep_on(&ps2esdi_int);
472         }                       /* if second physical drive is present */
473         return;
474 }
475
476 /* strategy routine that handles most of the IO requests */
477 static void do_ps2esdi_request(request_queue_t * q)
478 {
479         struct request *req;
480         /* since, this routine is called with interrupts cleared - they 
481            must be before it finishes  */
482
483         req = elv_next_request(q);
484         if (!req)
485                 return;
486
487 #if 0
488         printk("%s:got request. device : %s command : %d  sector : %ld count : %ld, buffer: %p\n",
489                DEVICE_NAME,
490                req->rq_disk->disk_name,
491                req->cmd, req->sector,
492                req->current_nr_sectors, req->buffer);
493 #endif
494
495         /* check for above 16Mb dmas */
496         if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) {
497                 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
498                 end_request(req, FAIL);
499                 return;
500         }
501
502         if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) {
503                 printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n",
504                     ps2esdi_drives, req->sector,
505                     (unsigned long long)get_capacity(req->rq_disk));
506                 end_request(req, FAIL);
507                 return;
508         }
509
510         switch (rq_data_dir(req)) {
511         case READ:
512                 ps2esdi_readwrite(READ, req);
513                 break;
514         case WRITE:
515                 ps2esdi_readwrite(WRITE, req);
516                 break;
517         default:
518                 printk("%s: Unknown command\n", req->rq_disk->disk_name);
519                 end_request(req, FAIL);
520                 break;
521         }               /* handle different commands */
522 }                               /* main strategy routine */
523
524 /* resets the ESDI adapter */
525 static void reset_ctrl(void)
526 {
527
528         u_long expire;
529         u_short status;
530
531         /* enable interrupts on the controller */
532         status = inb(ESDI_INTRPT);
533         outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);     /* to be sure we don't have
534                                                            any interrupt pending... */
535         outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
536
537         /* read the ESDI status port - if the controller is not busy,
538            simply do a soft reset (fast) - otherwise we'll have to do a
539            hard (slow) reset.  */
540         if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
541                 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
542                 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
543         }
544         /* soft reset */ 
545         else {
546                 /*BA */
547                 printk("%s: hard reset...\n", DEVICE_NAME);
548                 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
549                 expire = jiffies + 2*HZ;
550                 while (time_before(jiffies, expire));
551                 outb_p(1, ESDI_CONTROL);
552         }                       /* hard reset */
553
554
555 }                               /* reset the controller */
556
557 /* called by the strategy routine to handle read and write requests */
558 static void ps2esdi_readwrite(int cmd, struct request *req)
559 {
560         struct ps2esdi_i_struct *p = req->rq_disk->private_data;
561         unsigned block = req->sector;
562         unsigned count = req->current_nr_sectors;
563         int drive = p - ps2esdi_info;
564         u_short track, head, cylinder, sector;
565         u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
566
567         /* do some relevant arithmatic */
568         track = block / p->sect;
569         head = track % p->head;
570         cylinder = track / p->head;
571         sector = block % p->sect;
572
573 #if 0
574         printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
575 #endif
576         /* call the routine that actually fills out a command block */
577         ps2esdi_fill_cmd_block
578             (cmd_blk,
579              (cmd == READ) ? CMD_READ : CMD_WRITE,
580              cylinder, head, sector, count, drive);
581
582         /* send the command block to the controller */
583         current_req = req;
584         spin_unlock_irq(&ps2esdi_lock);
585         if (ps2esdi_out_cmd_blk(cmd_blk)) {
586                 spin_lock_irq(&ps2esdi_lock);
587                 printk("%s: Controller failed\n", DEVICE_NAME);
588                 if ((++req->errors) >= MAX_RETRIES)
589                         end_request(req, FAIL);
590         }
591         /* check for failure to put out the command block */ 
592         else {
593                 spin_lock_irq(&ps2esdi_lock);
594 #if 0
595                 printk("%s: waiting for xfer\n", DEVICE_NAME);
596 #endif
597                 /* turn disk lights on */
598                 LITE_ON;
599         }
600
601 }                               /* ps2esdi_readwrite */
602
603 /* fill out the command block */
604 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
605  u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
606 {
607
608         cmd_blk[0] = (drive << 5) | cmd;
609         cmd_blk[1] = length;
610         cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
611         cmd_blk[3] = (cyl & 0x3E0) >> 5;
612
613 }                               /* fill out the command block */
614
615 /* write a command block to the controller */
616 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
617 {
618
619         int i;
620         unsigned long jif;
621         u_char status;
622
623         /* enable interrupts */
624         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
625
626         /* do not write to the controller, if it is busy */
627         for (jif = jiffies + ESDI_STAT_TIMEOUT;
628                 time_after(jif, jiffies) &&
629                         (inb(ESDI_STATUS) & STATUS_BUSY); )
630                 ;
631
632 #if 0
633         printk("%s: i(1)=%ld\n", DEVICE_NAME, jif);
634 #endif
635
636         /* if device is still busy - then just time out */
637         if (inb(ESDI_STATUS) & STATUS_BUSY) {
638                 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
639                 return ERROR;
640         }                       /* timeout ??? */
641         /* Set up the attention register in the controller */
642         outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
643
644 #if 0
645         printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
646 #endif
647
648         /* one by one send each word out */
649         for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
650                 status = inb(ESDI_STATUS);
651                 for (jif = jiffies + ESDI_STAT_TIMEOUT;
652                      time_after(jif, jiffies) && (status & STATUS_BUSY) &&
653                    (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
654                 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
655 #if 0
656                         printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
657 #endif
658                         outw(*cmd_blk++, ESDI_CMD_INT);
659                 } else {
660                         printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
661                                DEVICE_NAME, status);
662                         return ERROR;
663                 }
664         }                       /* send all words out */
665         return OK;
666 }                               /* send out the commands */
667
668
669 /* prepare for dma - do all the necessary setup */
670 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
671 {
672         unsigned long flags = claim_dma_lock();
673
674         mca_disable_dma(dma_arb_level);
675
676         mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer));
677
678         mca_set_dma_count(dma_arb_level, length * 512 / 2);
679
680         mca_set_dma_mode(dma_arb_level, dma_xmode);
681
682         mca_enable_dma(dma_arb_level);
683
684         release_dma_lock(flags);
685
686 }                               /* prepare for dma */
687
688
689
690 static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
691                                       struct pt_regs *regs)
692 {
693         u_int int_ret_code;
694
695         if (inb(ESDI_STATUS) & STATUS_INTR) {
696                 int_ret_code = inb(ESDI_INTRPT);
697                 if (current_int_handler) {
698                         /* Disable adapter interrupts till processing is finished */
699                         outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
700                         current_int_handler(int_ret_code);
701                 } else
702                         printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
703         } else {
704                 return IRQ_NONE;
705         }
706         return IRQ_HANDLED;
707 }
708
709 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
710 {
711
712         switch (int_ret_code & 0xf) {
713         case INT_RESET:
714                 /*BA */
715                 printk("%s: initial reset completed.\n", DEVICE_NAME);
716                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
717                 wake_up(&ps2esdi_int);
718                 break;
719         case INT_ATTN_ERROR:
720                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
721                        int_ret_code);
722                 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
723                 break;
724         default:
725                 printk("%s: initial reset handler received interrupt: %02X\n",
726                        DEVICE_NAME, int_ret_code);
727                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
728                 break;
729         }
730         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
731 }
732
733
734 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
735 {
736         u_int status, drive_num;
737         unsigned long rba;
738         int i;
739
740         drive_num = int_ret_code >> 5;
741         switch (int_ret_code & 0xf) {
742         case INT_CMD_COMPLETE:
743                 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
744                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
745                         printk("%s: timeout reading status word\n", DEVICE_NAME);
746                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
747                         break;
748                 }
749                 status = inw(ESDI_STT_INT);
750                 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
751 #define REPLY_WORDS 5           /* we already read word 0 */
752                         u_short reply[REPLY_WORDS];
753
754                         if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
755                                 /*BA */
756                                 printk("%s: Device Configuration Status for drive %u\n",
757                                        DEVICE_NAME, drive_num);
758
759                                 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
760
761                                 printk
762                                     ("Config bits: %s%s%s%s%s\n",
763                                      (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
764                                      ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
765                                  ? "Zero Defect, " : "Defects Present, ",
766                                      (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
767                                      (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
768                                      (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
769
770                                 rba = reply[1] | ((unsigned long) reply[2] << 16);
771                                 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
772
773                                 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
774                                        DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
775
776                                 if (!ps2esdi_info[drive_num].head) {
777                                         ps2esdi_info[drive_num].head = 64;
778                                         ps2esdi_info[drive_num].sect = 32;
779                                         ps2esdi_info[drive_num].cyl = rba / (64 * 32);
780                                         ps2esdi_info[drive_num].wpcom = 0;
781                                         ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
782                                         ps2esdi_info[drive_num].ctl = 8;
783                                         if (tp720esdi) {        /* store the retrieved parameters */
784                                                 ps2esdi_info[0].head = reply[4] & 0Xff;
785                                                 ps2esdi_info[0].sect = reply[4] >> 8;
786                                                 ps2esdi_info[0].cyl = reply[3];
787                                                 ps2esdi_info[0].wpcom = 0;
788                                                 ps2esdi_info[0].lzone = reply[3];
789                                         } else {
790                                                 if (!intg_esdi)
791                                                         ps2esdi_drives++;
792                                         }
793                                 }
794 #ifdef OBSOLETE
795                                 if (!ps2esdi_info[drive_num].head) {
796                                         ps2esdi_info[drive_num].head = reply[4] & 0Xff;
797                                         ps2esdi_info[drive_num].sect = reply[4] >> 8;
798                                         ps2esdi_info[drive_num].cyl = reply[3];
799                                         ps2esdi_info[drive_num].wpcom = 0;
800                                         ps2esdi_info[drive_num].lzone = reply[3];
801                                         if (tp720esdi) {        /* store the retrieved parameters */
802                                                 ps2esdi_info[0].head = reply[4] & 0Xff;
803                                                 ps2esdi_info[0].sect = reply[4] >> 8;
804                                                 ps2esdi_info[0].cyl = reply[3];
805                                                 ps2esdi_info[0].wpcom = 0;
806                                                 ps2esdi_info[0].lzone = reply[3];
807                                         } else {
808                                                 ps2esdi_drives++;
809                                         }
810                                 }
811 #endif
812
813                         } else
814                                 printk("%s: failed while getting device config\n", DEVICE_NAME);
815 #undef REPLY_WORDS
816                 } else
817                         printk("%s: command %02X unknown by geometry handler\n",
818                                DEVICE_NAME, status & 0x1f);
819
820                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
821                 break;
822
823         case INT_ATTN_ERROR:
824                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
825                        int_ret_code);
826                 printk("%s: Device not available\n", DEVICE_NAME);
827                 break;
828         case INT_CMD_ECC:
829         case INT_CMD_RETRY:
830         case INT_CMD_ECC_RETRY:
831         case INT_CMD_WARNING:
832         case INT_CMD_ABORT:
833         case INT_CMD_FAILED:
834         case INT_DMA_ERR:
835         case INT_CMD_BLK_ERR:
836                 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
837                 dump_cmd_complete_status(int_ret_code);
838                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
839                 break;
840         default:
841                 printk("%s: Unknown interrupt reason: %02X\n",
842                        DEVICE_NAME, int_ret_code & 0xf);
843                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
844                 break;
845         }
846
847         wake_up(&ps2esdi_int);
848         no_int_yet = FALSE;
849         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
850
851 }
852
853 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
854 {
855         unsigned long flags;
856         u_int status;
857         u_int ending;
858         int i;
859
860         switch (int_ret_code & 0x0f) {
861         case INT_TRANSFER_REQ:
862                 ps2esdi_prep_dma(current_req->buffer,
863                                  current_req->current_nr_sectors,
864                     (rq_data_dir(current_req) == READ)
865                     ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
866                     : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
867                 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
868                 ending = -1;
869                 break;
870
871         case INT_ATTN_ERROR:
872                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
873                        int_ret_code);
874                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
875                 ending = FAIL;
876                 break;
877
878         case INT_CMD_COMPLETE:
879                 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
880                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
881                         printk("%s: timeout reading status word\n", DEVICE_NAME);
882                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
883                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
884                         if ((++current_req->errors) >= MAX_RETRIES)
885                                 ending = FAIL;
886                         else
887                                 ending = -1;
888                         break;
889                 }
890                 status = inw(ESDI_STT_INT);
891                 switch (status & 0x1F) {
892                 case (CMD_READ & 0xff):
893                 case (CMD_WRITE & 0xff):
894                         LITE_OFF;
895                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
896                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
897                         ending = SUCCES;
898                         break;
899                 default:
900                         printk("%s: interrupt for unknown command %02X\n",
901                                DEVICE_NAME, status & 0x1f);
902                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
903                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
904                         ending = -1;
905                         break;
906                 }
907                 break;
908         case INT_CMD_ECC:
909         case INT_CMD_RETRY:
910         case INT_CMD_ECC_RETRY:
911                 LITE_OFF;
912                 dump_cmd_complete_status(int_ret_code);
913                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
914                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
915                 ending = SUCCES;
916                 break;
917         case INT_CMD_WARNING:
918         case INT_CMD_ABORT:
919         case INT_CMD_FAILED:
920         case INT_DMA_ERR:
921                 LITE_OFF;
922                 dump_cmd_complete_status(int_ret_code);
923                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
924                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
925                 if ((++current_req->errors) >= MAX_RETRIES)
926                         ending = FAIL;
927                 else
928                         ending = -1;
929                 break;
930
931         case INT_CMD_BLK_ERR:
932                 dump_cmd_complete_status(int_ret_code);
933                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
934                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
935                 ending = FAIL;
936                 break;
937
938         case INT_CMD_FORMAT:
939                 printk("%s: huh ? Who issued this format command ?\n"
940                        ,DEVICE_NAME);
941                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
942                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
943                 ending = -1;
944                 break;
945
946         case INT_RESET:
947                 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
948                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
949                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
950                 ending = -1;
951                 break;
952
953         default:
954                 printk("%s: Unknown interrupt reason: %02X\n",
955                        DEVICE_NAME, int_ret_code & 0xf);
956                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
957                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
958                 ending = -1;
959                 break;
960         }
961         if(ending != -1) {
962                 spin_lock_irqsave(&ps2esdi_lock, flags);
963                 end_request(current_req, ending);
964                 current_req = NULL;
965                 do_ps2esdi_request(ps2esdi_queue);
966                 spin_unlock_irqrestore(&ps2esdi_lock, flags);
967         }
968 }                               /* handle interrupts */
969
970
971
972 static int ps2esdi_read_status_words(int num_words,
973                                      int max_words,
974                                      u_short * buffer)
975 {
976         int i;
977
978         for (; max_words && num_words; max_words--, num_words--, buffer++) {
979                 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
980                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
981                         printk("%s: timeout reading status word\n", DEVICE_NAME);
982                         return FAIL;
983                 }
984                 *buffer = inw(ESDI_STT_INT);
985         }
986         return SUCCES;
987 }
988
989
990
991
992 static void dump_cmd_complete_status(u_int int_ret_code)
993 {
994 #define WAIT_FOR_STATUS \
995   for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
996     if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
997     printk("%s: timeout reading status word\n",DEVICE_NAME); \
998     return; \
999     }
1000
1001         int i, word_count;
1002         u_short stat_word;
1003         u_long rba;
1004
1005         printk("%s: Device: %u, interrupt ID: %02X\n",
1006                DEVICE_NAME, int_ret_code >> 5,
1007                int_ret_code & 0xf);
1008
1009         WAIT_FOR_STATUS;
1010         stat_word = inw(ESDI_STT_INT);
1011         word_count = (stat_word >> 8) - 1;
1012         printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1013                stat_word & 0xff);
1014
1015         if (word_count--) {
1016                 WAIT_FOR_STATUS;
1017                 stat_word = inw(ESDI_STT_INT);
1018                 printk("%s: command status code: %02X, command error code: %02X\n",
1019                        DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1020         }
1021         if (word_count--) {
1022                 WAIT_FOR_STATUS;
1023                 stat_word = inw(ESDI_STT_INT);
1024                 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1025                        (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1026                   (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1027                        (stat_word & 0x0400) ? "Write Fault, " : "",
1028                        (stat_word & 0x0200) ? "Track 0, " : "",
1029                 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1030                        stat_word >> 8);
1031         }
1032         if (word_count--) {
1033                 WAIT_FOR_STATUS;
1034                 stat_word = inw(ESDI_STT_INT);
1035                 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1036         }
1037         if (word_count -= 2) {
1038                 WAIT_FOR_STATUS;
1039                 rba = inw(ESDI_STT_INT);
1040                 WAIT_FOR_STATUS;
1041                 rba |= inw(ESDI_STT_INT) << 16;
1042                 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1043                        (u_short) ((rba & 0x1ff80000) >> 11),
1044                  (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1045         } else
1046                 printk("\n");
1047
1048         if (word_count--) {
1049                 WAIT_FOR_STATUS;
1050                 stat_word = inw(ESDI_STT_INT);
1051                 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1052         }
1053         printk("\n");
1054
1055 #undef WAIT_FOR_STATUS
1056
1057 }
1058
1059 static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1060 {
1061         struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
1062
1063         geo->heads = p->head;
1064         geo->sectors = p->sect;
1065         geo->cylinders = p->cyl;
1066         return 0;
1067 }
1068
1069 static void ps2esdi_reset_timer(unsigned long unused)
1070 {
1071
1072         int status;
1073
1074         status = inb(ESDI_INTRPT);
1075         if ((status & 0xf) == INT_RESET) {
1076                 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1077                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1078                 reset_status = 1;
1079         }
1080         wake_up(&ps2esdi_int);
1081 }