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