a729013a39737b24541a999f38950c7206ae6181
[cascardo/linux.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/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 #include <linux/hdreg.h>
47
48 #include <asm/system.h>
49 #include <asm/io.h>
50 #include <asm/dma.h>
51 #include <asm/mca_dma.h>
52 #include <asm/uaccess.h>
53
54 #define PS2ESDI_IRQ 14
55 #define MAX_HD 2
56 #define MAX_RETRIES 5
57 #define MAX_16BIT 65536
58 #define ESDI_TIMEOUT   0xf000
59 #define ESDI_STAT_TIMEOUT 4
60
61 #define TYPE_0_CMD_BLK_LENGTH 2
62 #define TYPE_1_CMD_BLK_LENGTH 4
63
64 static void reset_ctrl(void);
65
66 static int ps2esdi_geninit(void);
67
68 static void do_ps2esdi_request(request_queue_t * q);
69
70 static void ps2esdi_readwrite(int cmd, struct request *req);
71
72 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
73 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
74
75 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
76
77 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
78
79 static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
80                                       struct pt_regs *regs);
81 static void (*current_int_handler) (u_int) = NULL;
82 static void ps2esdi_normal_interrupt_handler(u_int);
83 static void ps2esdi_initial_reset_int_handler(u_int);
84 static void ps2esdi_geometry_int_handler(u_int);
85 static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
86
87 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
88
89 static void dump_cmd_complete_status(u_int int_ret_code);
90
91 static void ps2esdi_get_device_cfg(void);
92
93 static void ps2esdi_reset_timer(unsigned long unused);
94
95 static u_int dma_arb_level;             /* DMA arbitration level */
96
97 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
98
99 static int no_int_yet;
100 static int ps2esdi_drives;
101 static u_short io_base;
102 static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0);
103 static int reset_status;
104 static int ps2esdi_slot = -1;
105 static int tp720esdi = 0;       /* Is it Integrated ESDI of ThinkPad-720? */
106 static int intg_esdi = 0;       /* If integrated adapter */
107 struct ps2esdi_i_struct {
108         unsigned int head, sect, cyl, wpcom, lzone, ctl;
109 };
110 static DEFINE_SPINLOCK(ps2esdi_lock);
111 static struct request_queue *ps2esdi_queue;
112 static struct request *current_req;
113
114 #if 0
115 #if 0                           /* try both - I don't know which one is better... UB */
116 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
117 {
118         {4, 48, 1553, 0, 0, 0},
119         {0, 0, 0, 0, 0, 0}};
120 #else
121 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
122 {
123         {64, 32, 161, 0, 0, 0},
124         {0, 0, 0, 0, 0, 0}};
125 #endif
126 #endif
127 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
128 {
129         {0, 0, 0, 0, 0, 0},
130         {0, 0, 0, 0, 0, 0}};
131
132 static struct block_device_operations ps2esdi_fops =
133 {
134         .owner          = THIS_MODULE,
135         .getgeo         = ps2esdi_getgeo,
136 };
137
138 static struct gendisk *ps2esdi_gendisk[2];
139
140 /* initialization routine called by ll_rw_blk.c   */
141 static int __init ps2esdi_init(void)
142 {
143
144         int error = 0;
145
146         /* register the device - pass the name and major number */
147         if (register_blkdev(PS2ESDI_MAJOR, "ed"))
148                 return -EBUSY;
149
150         /* set up some global information - indicating device specific info */
151         ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock);
152         if (!ps2esdi_queue) {
153                 unregister_blkdev(PS2ESDI_MAJOR, "ed");
154                 return -ENOMEM;
155         }
156
157         /* some minor housekeeping - setup the global gendisk structure */
158         error = ps2esdi_geninit();
159         if (error) {
160                 printk(KERN_WARNING "PS2ESDI: error initialising"
161                         " device, releasing resources\n");
162                 unregister_blkdev(PS2ESDI_MAJOR, "ed");
163                 blk_cleanup_queue(ps2esdi_queue);
164                 return error;
165         }
166         return 0;
167 }                               /* ps2esdi_init */
168
169 #ifndef MODULE
170
171 module_init(ps2esdi_init);
172
173 #else
174
175 static int cyl[MAX_HD] = {-1,-1};
176 static int head[MAX_HD] = {-1, -1};
177 static int sect[MAX_HD] = {-1, -1};
178
179 module_param(tp720esdi, bool, 0);
180 module_param_array(cyl, int, NULL, 0);
181 module_param_array(head, int, NULL, 0);
182 module_param_array(sect, int, NULL, 0);
183 MODULE_LICENSE("GPL");
184
185 int init_module(void) {
186         int drive;
187
188         for(drive = 0; drive < MAX_HD; drive++) {
189                 struct ps2esdi_i_struct *info = &ps2esdi_info[drive];
190
191                 if (cyl[drive] != -1) {
192                         info->cyl = info->lzone = cyl[drive];
193                         info->wpcom = 0;
194                 }
195                 if (head[drive] != -1) {
196                         info->head = head[drive];
197                         info->ctl = (head[drive] > 8 ? 8 : 0);
198                 }
199                 if (sect[drive] != -1) info->sect = sect[drive];
200         }
201         return ps2esdi_init();
202 }
203
204 void
205 cleanup_module(void) {
206         int i;
207         if(ps2esdi_slot) {
208                 mca_mark_as_unused(ps2esdi_slot);
209                 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
210         }
211         release_region(io_base, 4);
212         free_dma(dma_arb_level);
213         free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
214         unregister_blkdev(PS2ESDI_MAJOR, "ed");
215         blk_cleanup_queue(ps2esdi_queue);
216         for (i = 0; i < ps2esdi_drives; i++) {
217                 del_gendisk(ps2esdi_gendisk[i]);
218                 put_disk(ps2esdi_gendisk[i]);
219         }
220 }
221 #endif /* MODULE */
222
223 /* handles boot time command line parameters */
224 void __init tp720_setup(char *str, int *ints)
225 {
226         /* no params, just sets the tp720esdi flag if it exists */
227
228         printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
229         tp720esdi = 1;
230 }
231
232 void __init ed_setup(char *str, int *ints)
233 {
234         int hdind = 0;
235
236         /* handles 3 parameters only - corresponding to
237            1. Number of cylinders
238            2. Number of heads
239            3. Sectors/track
240          */
241
242         if (ints[0] != 3)
243                 return;
244
245         /* print out the information - seen at boot time */
246         printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
247                DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
248
249         /* set the index into device specific information table */
250         if (ps2esdi_info[0].head != 0)
251                 hdind = 1;
252
253         /* set up all the device information */
254         ps2esdi_info[hdind].head = ints[2];
255         ps2esdi_info[hdind].sect = ints[3];
256         ps2esdi_info[hdind].cyl = ints[1];
257         ps2esdi_info[hdind].wpcom = 0;
258         ps2esdi_info[hdind].lzone = ints[1];
259         ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
260 #if 0                           /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
261         ps2esdi_drives = hdind + 1;     /* increment index for the next time */
262 #endif
263 }                               /* ed_setup */
264
265 static int ps2esdi_getinfo(char *buf, int slot, void *d)
266 {
267         int len = 0;
268
269         len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
270                        dma_arb_level);
271         len += sprintf(buf + len, "IO Port: %x\n", io_base);
272         len += sprintf(buf + len, "IRQ: 14\n");
273         len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
274
275         return len;
276 }
277
278 /* ps2 esdi specific initialization - called thru the gendisk chain */
279 static int __init ps2esdi_geninit(void)
280 {
281         /*
282            The first part contains the initialization code
283            for the ESDI disk subsystem.  All we really do
284            is search for the POS registers of the controller
285            to do some simple setup operations.  First, we
286            must ensure that the controller is installed,
287            enabled, and configured as PRIMARY.  Then we must
288            determine the DMA arbitration level being used by
289            the controller so we can handle data transfer
290            operations properly.  If all of this works, then
291            we will set the INIT_FLAG to a non-zero value.
292          */
293
294         int slot = 0, i, reset_start, reset_end;
295         u_char status;
296         unsigned short adapterID;
297         int error = 0;
298
299         if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
300                 adapterID = INTG_ESDI_ID;
301                 printk("%s: integrated ESDI adapter found in slot %d\n",
302                        DEVICE_NAME, slot+1);
303 #ifndef MODULE
304                 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
305 #endif
306         } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
307                 adapterID = NRML_ESDI_ID;
308                 printk("%s: normal ESDI adapter found in slot %d\n",
309                        DEVICE_NAME, slot+1);
310                 mca_set_adapter_name(slot, "PS/2 ESDI");
311         } else {
312                 return -ENODEV;
313         }
314
315         ps2esdi_slot = slot;
316         mca_mark_as_used(slot);
317         mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
318
319         /* Found the slot - read the POS register 2 to get the necessary
320            configuration and status information.  POS register 2 has the
321            following information :
322            Bit           Function
323            7             reserved = 0
324            6             arbitration method
325            0 - fairness enabled
326            1 - fairness disabled, linear priority assignment
327            5-2           arbitration level
328            1             alternate address
329            1              alternate address
330            0 - use addresses 0x3510 - 0x3517
331            0             adapter enable
332          */
333
334         status = mca_read_stored_pos(slot, 2);
335         /* is it enabled ? */
336         if (!(status & STATUS_ENABLED)) {
337                 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
338                 error = -ENODEV;
339                 goto err_out1;
340         }
341         /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
342            share with the SCSI driver */
343         if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
344                   SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
345             && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
346                            SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
347             ) {
348                 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
349                 error = -EBUSY;
350                 goto err_out1;
351         }
352         if (status & STATUS_ALTERNATE)
353                 io_base = ALT_IO_BASE;
354         else
355                 io_base = PRIMARY_IO_BASE;
356
357         if (!request_region(io_base, 4, "ed")) {
358                 printk(KERN_WARNING"Unable to request region 0x%x\n", io_base);
359                 error = -EBUSY;
360                 goto err_out2;
361         }
362         /* get the dma arbitration level */
363         dma_arb_level = (status >> 2) & 0xf;
364
365         /* BA */
366         printk("%s: DMA arbitration level : %d\n",
367                DEVICE_NAME, dma_arb_level);
368
369         LITE_ON;
370         current_int_handler = ps2esdi_initial_reset_int_handler;
371         reset_ctrl();
372         reset_status = 0;
373         reset_start = jiffies;
374         while (!reset_status) {
375                 init_timer(&esdi_timer);
376                 esdi_timer.expires = jiffies + HZ;
377                 esdi_timer.data = 0;
378                 add_timer(&esdi_timer);
379                 sleep_on(&ps2esdi_int);
380         }
381         reset_end = jiffies;
382         LITE_OFF;
383         printk("%s: reset interrupt after %d jiffies,  %u.%02u secs\n",
384                DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
385                (reset_end - reset_start) % HZ);
386
387
388         /* Integrated ESDI Disk and Controller has only one drive! */
389         if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
390                 ps2esdi_drives = 1;     /* then we have only one physical disk! */              intg_esdi = 1;
391         }
392
393
394
395         /* finally this part sets up some global data structures etc. */
396
397         ps2esdi_get_device_cfg();
398
399         /* some annoyance in the above routine returns TWO drives?
400          Is something else happining in the background?
401          Regaurdless we fix the # of drives again. AJK */
402         /* Integrated ESDI Disk and Controller has only one drive! */
403         if (adapterID == INTG_ESDI_ID)  /* if not "normal" PS2 ESDI adapter */
404                 ps2esdi_drives = 1;     /* Not three or two, ONE DAMNIT! */
405
406         current_int_handler = ps2esdi_normal_interrupt_handler;
407
408         if (request_dma(dma_arb_level, "ed") !=0) {
409                 printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n"
410                         ,(int) dma_arb_level);
411                 error = -EBUSY;
412                 goto err_out3;
413         }
414         blk_queue_max_sectors(ps2esdi_queue, 128);
415
416         error = -ENOMEM;
417         for (i = 0; i < ps2esdi_drives; i++) {
418                 struct gendisk *disk = alloc_disk(64);
419                 if (!disk)
420                         goto err_out4;
421                 disk->major = PS2ESDI_MAJOR;
422                 disk->first_minor = i<<6;
423                 sprintf(disk->disk_name, "ed%c", 'a'+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 }