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