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