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