v2.4.9.2 -> v2.4.9.3
[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_NR,               /* Major number */
161         "ed",                   /* Major name */
162         6,                      /* Bits to shift to get real from partition */
163         1 << 6,                 /* Number of partitions per real disk */
164         ps2esdi,                /* hd struct */
165         ps2esdi_sizes,          /* block sizes */
166         0,                      /* number */
167         (void *) ps2esdi_info,  /* internal */
168         NULL,                   /* next */
169         &ps2esdi_fops,          /* file operations */
170 };
171
172 /* initialization routine called by ll_rw_blk.c   */
173 int __init ps2esdi_init(void)
174 {
175
176         /* register the device - pass the name, major number and operations
177            vector .                                                 */
178         if (devfs_register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
179                 printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR);
180                 return -1;
181         }
182         /* set up some global information - indicating device specific info */
183         blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
184         read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read ahead */
185
186         /* some minor housekeeping - setup the global gendisk structure */
187         ps2esdi_gendisk.next = gendisk_head;
188         gendisk_head = &ps2esdi_gendisk;
189         ps2esdi_geninit();
190         return 0;
191 }                               /* ps2esdi_init */
192
193 #ifdef MODULE
194
195 static int cyl[MAX_HD] = {-1,-1};
196 static int head[MAX_HD] = {-1, -1};
197 static int sect[MAX_HD] = {-1, -1};
198
199 MODULE_PARM(tp720esdi, "i");
200 MODULE_PARM(cyl, "i");
201 MODULE_PARM(head, "i");
202 MODULE_PARM(track, "i");
203
204 int init_module(void) {
205         int drive;
206
207         for(drive = 0; drive < MAX_HD; drive++) {
208                 struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
209
210                 if (cyl[drive] != -1) {
211                         info->cyl = info->lzone = cyl[drive];
212                         info->wpcom = 0;
213                 }
214                 if (head[drive] != -1) {
215                         info->head = head[drive];
216                         info->ctl = (head[drive] > 8 ? 8 : 0);
217                 }
218                 if (sect[drive] != -1) info->sect = sect[drive];
219         }
220         return ps2esdi_init();
221 }
222
223 void
224 cleanup_module(void)
225 {
226         if(ps2esdi_slot)
227         {
228                 mca_mark_as_unused(ps2esdi_slot);
229                 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
230         }
231         release_region(io_base, 4);
232         free_dma(dma_arb_level);
233         free_irq(PS2ESDI_IRQ, NULL)
234         devfs_unregister_blkdev(MAJOR_NR, "ed");
235         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
236 }
237 #endif /* MODULE */
238
239 /* handles boot time command line parameters */
240 void __init tp720_setup(char *str, int *ints)
241 {
242         /* no params, just sets the tp720esdi flag if it exists */
243
244         printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
245         tp720esdi = 1;
246 }
247
248 void __init ed_setup(char *str, int *ints)
249 {
250         int hdind = 0;
251
252         /* handles 3 parameters only - corresponding to
253            1. Number of cylinders
254            2. Number of heads
255            3. Sectors/track
256          */
257
258         if (ints[0] != 3)
259                 return;
260
261         /* print out the information - seen at boot time */
262         printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
263                DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
264
265         /* set the index into device specific information table */
266         if (ps2esdi_info[0].head != 0)
267                 hdind = 1;
268
269         /* set up all the device information */
270         ps2esdi_info[hdind].head = ints[2];
271         ps2esdi_info[hdind].sect = ints[3];
272         ps2esdi_info[hdind].cyl = ints[1];
273         ps2esdi_info[hdind].wpcom = 0;
274         ps2esdi_info[hdind].lzone = ints[1];
275         ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
276 #if 0                           /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
277         ps2esdi_drives = hdind + 1;     /* increment index for the next time */
278 #endif
279 }                               /* ed_setup */
280
281 static int ps2esdi_getinfo(char *buf, int slot, void *d)
282 {
283         int len = 0;
284
285         len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
286                        dma_arb_level);
287         len += sprintf(buf + len, "IO Port: %x\n", io_base);
288         len += sprintf(buf + len, "IRQ: 14\n");
289         len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
290
291         return len;
292 }
293
294 /* ps2 esdi specific initialization - called thru the gendisk chain */
295 static void __init ps2esdi_geninit(void)
296 {
297         /*
298            The first part contains the initialization code
299            for the ESDI disk subsystem.  All we really do
300            is search for the POS registers of the controller
301            to do some simple setup operations.  First, we
302            must ensure that the controller is installed,
303            enabled, and configured as PRIMARY.  Then we must
304            determine the DMA arbitration level being used by
305            the controller so we can handle data transfer
306            operations properly.  If all of this works, then
307            we will set the INIT_FLAG to a non-zero value.
308          */
309
310         int slot = 0, i, reset_start, reset_end;
311         u_char status;
312         unsigned short adapterID;
313
314         if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
315                 adapterID = INTG_ESDI_ID;
316                 printk("%s: integrated ESDI adapter found in slot %d\n",
317                        DEVICE_NAME, slot+1);
318 #ifndef MODULE
319                 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
320 #endif
321         } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
322                 adapterID = NRML_ESDI_ID;
323                 printk("%s: normal ESDI adapter found in slot %d\n",
324                        DEVICE_NAME, slot+1);
325                 mca_set_adapter_name(slot, "PS/2 ESDI");
326         } else {
327                 return;
328         }
329
330         ps2esdi_slot = slot;
331         mca_mark_as_used(slot);
332         mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
333
334         /* Found the slot - read the POS register 2 to get the necessary
335            configuration and status information.  POS register 2 has the
336            following information :
337            Bit           Function
338            7             reserved = 0
339            6             arbitration method
340            0 - fairness enabled
341            1 - fairness disabled, linear priority assignment
342            5-2           arbitration level
343            1             alternate address
344            1              alternate address
345            0 - use addresses 0x3510 - 0x3517
346            0             adapter enable
347          */
348
349         status = mca_read_stored_pos(slot, 2);
350         /* is it enabled ? */
351         if (!(status & STATUS_ENABLED)) {
352                 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
353                 return;
354         }
355         /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
356            share with the SCSI driver */
357         if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
358                   SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
359             && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
360                            SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
361             ) {
362                 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
363                 return;
364         }
365         if (status & STATUS_ALTERNATE)
366                 io_base = ALT_IO_BASE;
367         else
368                 io_base = PRIMARY_IO_BASE;
369
370         /* get the dma arbitration level */
371         dma_arb_level = (status >> 2) & 0xf;
372
373         /* BA */
374         printk("%s: DMA arbitration level : %d\n",
375                DEVICE_NAME, dma_arb_level);
376
377         LITE_ON;
378         current_int_handler = ps2esdi_initial_reset_int_handler;
379         reset_ctrl();
380         reset_status = 0;
381         reset_start = jiffies;
382         while (!reset_status) {
383                 init_timer(&esdi_timer);
384                 esdi_timer.expires = jiffies + HZ;
385                 esdi_timer.data = 0;
386                 add_timer(&esdi_timer);
387                 sleep_on(&ps2esdi_int);
388         }
389         reset_end = jiffies;
390         LITE_OFF;
391         printk("%s: reset interrupt after %d jiffies,  %u.%02u secs\n",
392                DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
393                (reset_end - reset_start) % HZ);
394
395
396         /* Integrated ESDI Disk and Controller has only one drive! */
397         if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
398                 ps2esdi_drives = 1;     /* then we have only one physical disk! */              intg_esdi = 1;
399         }
400
401
402
403         /* finally this part sets up some global data structures etc. */
404
405         ps2esdi_get_device_cfg();
406
407         /* some annoyance in the above routine returns TWO drives?
408          Is something else happining in the background?
409          Regaurdless we fix the # of drives again. AJK */
410         /* Integrated ESDI Disk and Controller has only one drive! */
411         if (adapterID == INTG_ESDI_ID)  /* if not "normal" PS2 ESDI adapter */
412                 ps2esdi_drives = 1;     /* Not three or two, ONE DAMNIT! */
413
414         current_int_handler = ps2esdi_normal_interrupt_handler;
415
416         ps2esdi_gendisk.nr_real = ps2esdi_drives;
417
418         /* 128 was old default, maybe maxsect=255 is ok too? - Paul G. */
419         for (i = 0; i < (MAX_HD << 6); i++) {
420                 ps2esdi_maxsect[i] = 128;
421                 ps2esdi_blocksizes[i] = 1024;
422         }
423
424         request_dma(dma_arb_level, "ed");
425         request_region(io_base, 4, "ed");
426         blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
427         max_sectors[MAJOR_NR] = ps2esdi_maxsect;
428
429         for (i = 0; i < ps2esdi_drives; i++) {
430                 register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6,
431                                 &ps2esdi_fops,
432                                 ps2esdi_info[i].head * ps2esdi_info[i].sect *
433                                 ps2esdi_info[i].cyl);
434                 ps2esdi_valid[i] = 1;
435         }
436 }
437
438 static void __init ps2esdi_get_device_cfg(void)
439 {
440         u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
441
442         /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
443         current_int_handler = ps2esdi_geometry_int_handler;
444         cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
445         cmd_blk[1] = 0;
446         no_int_yet = TRUE;
447         ps2esdi_out_cmd_blk(cmd_blk);
448         if (no_int_yet)
449                 sleep_on(&ps2esdi_int);
450
451         if (ps2esdi_drives > 1) {
452                 printk("%s: Drive 1\n", DEVICE_NAME);   /*BA */
453                 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
454                 cmd_blk[1] = 0;
455                 no_int_yet = TRUE;
456                 ps2esdi_out_cmd_blk(cmd_blk);
457                 if (no_int_yet)
458                         sleep_on(&ps2esdi_int);
459         }                       /* if second physical drive is present */
460         return;
461 }
462
463 /* strategy routine that handles most of the IO requests */
464 static void do_ps2esdi_request(request_queue_t * q)
465 {
466         u_int block, count;
467         /* since, this routine is called with interrupts cleared - they 
468            must be before it finishes  */
469         sti();
470
471 #if 0
472         printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld, buffer: %p\n",
473                DEVICE_NAME,
474                CURRENT_DEV, MINOR(CURRENT->rq_dev),
475                CURRENT->cmd, CURRENT->sector,
476                CURRENT->current_nr_sectors, CURRENT->buffer);
477 #endif
478
479         /* standard macro that ensures that requests are really on the
480            list + sanity checks.                     */
481         INIT_REQUEST;
482
483         if (virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
484                 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
485                 end_request(FAIL);
486         }                       /* check for above 16Mb dmas */
487         else if ((CURRENT_DEV < ps2esdi_drives) &&
488             (CURRENT->sector + CURRENT->current_nr_sectors <=
489              ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
490 #if 0
491                 printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld\n",
492                        DEVICE_NAME,
493                        CURRENT_DEV, MINOR(CURRENT->rq_dev),
494                        CURRENT->cmd, CURRENT->sector,
495                        CURRENT->current_nr_sectors);
496 #endif
497
498
499                 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
500
501 #if 0
502                 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
503 #endif
504                 count = CURRENT->current_nr_sectors;
505                 switch (CURRENT->cmd) {
506                 case READ:
507                         ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
508                         break;
509                 case WRITE:
510                         ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
511                         break;
512                 default:
513                         printk("%s: Unknown command\n", DEVICE_NAME);
514                         end_request(FAIL);
515                         break;
516                 }               /* handle different commands */
517         }
518         /* is request is valid */ 
519         else {
520                 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
521                        CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
522                 end_request(FAIL);
523         }
524
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, u_char drive, u_int block, u_int count)
562 {
563
564         u_short track, head, cylinder, sector;
565         u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
566
567         /* do some relevant arithmatic */
568         track = block / ps2esdi_info[drive].sect;
569         head = track % ps2esdi_info[drive].head;
570         cylinder = track / ps2esdi_info[drive].head;
571         sector = block % ps2esdi_info[drive].sect;
572
573 #if 0
574         printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
575 #endif
576         /* call the routine that actually fills out a command block */
577         ps2esdi_fill_cmd_block
578             (cmd_blk,
579              (cmd == READ) ? CMD_READ : CMD_WRITE,
580              cylinder, head, sector,
581              CURRENT->current_nr_sectors, drive);
582
583         /* send the command block to the controller */
584         if (ps2esdi_out_cmd_blk(cmd_blk)) {
585                 printk("%s: Controller failed\n", DEVICE_NAME);
586                 if ((++CURRENT->errors) >= MAX_RETRIES)
587                         end_request(FAIL);
588         }
589         /* check for failure to put out the command block */ 
590         else {
591 #if 0
592                 printk("%s: waiting for xfer\n", DEVICE_NAME);
593 #endif
594                 /* turn disk lights on */
595                 LITE_ON;
596         }
597
598 }                               /* ps2esdi_readwrite */
599
600 /* fill out the command block */
601 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
602  u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
603 {
604
605         cmd_blk[0] = (drive << 5) | cmd;
606         cmd_blk[1] = length;
607         cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
608         cmd_blk[3] = (cyl & 0x3E0) >> 5;
609
610 }                               /* fill out the command block */
611
612 /* write a command block to the controller */
613 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
614 {
615
616         int i, j;
617         u_char status;
618
619         /* enable interrupts */
620         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
621
622         /* do not write to the controller, if it is busy */
623         for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
624                                                           STATUS_BUSY););
625
626 #if 0
627         printk("%s: i(1)=%d\n", DEVICE_NAME, i);
628 #endif
629
630         /* if device is still busy - then just time out */
631         if (inb(ESDI_STATUS) & STATUS_BUSY) {
632                 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
633                 return ERROR;
634         }                       /* timeout ??? */
635         /* Set up the attention register in the controller */
636         outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
637
638 #if 0
639         printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
640 #endif
641
642         /* one by one send each word out */
643         for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
644                 status = inb(ESDI_STATUS);
645                 for (j = jiffies + ESDI_STAT_TIMEOUT;
646                      time_after(j, jiffies) && (status & STATUS_BUSY) &&
647                    (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
648                 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
649 #if 0
650                         printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
651 #endif
652                         outw(*cmd_blk++, ESDI_CMD_INT);
653                 } else {
654                         printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
655                                DEVICE_NAME, status);
656                         return ERROR;
657                 }
658         }                       /* send all words out */
659         return OK;
660 }                               /* send out the commands */
661
662
663 /* prepare for dma - do all the necessary setup */
664 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
665 {
666         unsigned long flags;
667 #if 0
668         printk("ps2esdi: b_wait: %p\n", &CURRENT->bh->b_wait);
669 #endif
670         flags = claim_dma_lock();
671
672         mca_disable_dma(dma_arb_level);
673
674         mca_set_dma_addr(dma_arb_level, virt_to_bus(buffer));
675
676         mca_set_dma_count(dma_arb_level, length * 512 / 2);
677
678         mca_set_dma_mode(dma_arb_level, dma_xmode);
679
680         mca_enable_dma(dma_arb_level);
681
682         release_dma_lock(flags);
683
684 }                               /* prepare for dma */
685
686
687
688 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
689                                       struct pt_regs *regs)
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;
703         }
704 }
705
706 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
707 {
708
709         switch (int_ret_code & 0xf) {
710         case INT_RESET:
711                 /*BA */
712                 printk("%s: initial reset completed.\n", DEVICE_NAME);
713                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
714                 wake_up(&ps2esdi_int);
715                 break;
716         case INT_ATTN_ERROR:
717                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
718                        int_ret_code);
719                 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
720                 break;
721         default:
722                 printk("%s: initial reset handler received interrupt: %02X\n",
723                        DEVICE_NAME, int_ret_code);
724                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
725                 break;
726         }
727         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
728 }
729
730
731 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
732 {
733         u_int status, drive_num;
734         unsigned long rba;
735         int i;
736
737         drive_num = int_ret_code >> 5;
738         switch (int_ret_code & 0xf) {
739         case INT_CMD_COMPLETE:
740                 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
741                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
742                         printk("%s: timeout reading status word\n", DEVICE_NAME);
743                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
744                         break;
745                 }
746                 status = inw(ESDI_STT_INT);
747                 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
748 #define REPLY_WORDS 5           /* we already read word 0 */
749                         u_short reply[REPLY_WORDS];
750
751                         if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
752                                 /*BA */
753                                 printk("%s: Device Configuration Status for drive %u\n",
754                                        DEVICE_NAME, drive_num);
755
756                                 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
757
758                                 printk
759                                     ("Config bits: %s%s%s%s%s\n",
760                                      (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
761                                      ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
762                                  ? "Zero Defect, " : "Defects Present, ",
763                                      (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
764                                      (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
765                                      (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
766
767                                 rba = reply[1] | ((unsigned long) reply[2] << 16);
768                                 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
769
770                                 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
771                                        DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
772
773                                 if (!ps2esdi_info[drive_num].head) {
774                                         ps2esdi_info[drive_num].head = 64;
775                                         ps2esdi_info[drive_num].sect = 32;
776                                         ps2esdi_info[drive_num].cyl = rba / (64 * 32);
777                                         ps2esdi_info[drive_num].wpcom = 0;
778                                         ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
779                                         ps2esdi_info[drive_num].ctl = 8;
780                                         if (tp720esdi) {        /* store the retrieved parameters */
781                                                 ps2esdi_info[0].head = reply[4] & 0Xff;
782                                                 ps2esdi_info[0].sect = reply[4] >> 8;
783                                                 ps2esdi_info[0].cyl = reply[3];
784                                                 ps2esdi_info[0].wpcom = 0;
785                                                 ps2esdi_info[0].lzone = reply[3];
786                                         } else {
787                                                 if (!intg_esdi)
788                                                         ps2esdi_drives++;
789                                         }
790                                 }
791 #ifdef OBSOLETE
792                                 if (!ps2esdi_info[drive_num].head) {
793                                         ps2esdi_info[drive_num].head = reply[4] & 0Xff;
794                                         ps2esdi_info[drive_num].sect = reply[4] >> 8;
795                                         ps2esdi_info[drive_num].cyl = reply[3];
796                                         ps2esdi_info[drive_num].wpcom = 0;
797                                         ps2esdi_info[drive_num].lzone = reply[3];
798                                         if (tp720esdi) {        /* store the retrieved parameters */
799                                                 ps2esdi_info[0].head = reply[4] & 0Xff;
800                                                 ps2esdi_info[0].sect = reply[4] >> 8;
801                                                 ps2esdi_info[0].cyl = reply[3];
802                                                 ps2esdi_info[0].wpcom = 0;
803                                                 ps2esdi_info[0].lzone = reply[3];
804                                         } else {
805                                                 ps2esdi_drives++;
806                                         }
807                                 }
808 #endif
809
810                         } else
811                                 printk("%s: failed while getting device config\n", DEVICE_NAME);
812 #undef REPLY_WORDS
813                 } else
814                         printk("%s: command %02X unknown by geometry handler\n",
815                                DEVICE_NAME, status & 0x1f);
816
817                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
818                 break;
819
820         case INT_ATTN_ERROR:
821                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
822                        int_ret_code);
823                 printk("%s: Device not available\n", DEVICE_NAME);
824                 break;
825         case INT_CMD_ECC:
826         case INT_CMD_RETRY:
827         case INT_CMD_ECC_RETRY:
828         case INT_CMD_WARNING:
829         case INT_CMD_ABORT:
830         case INT_CMD_FAILED:
831         case INT_DMA_ERR:
832         case INT_CMD_BLK_ERR:
833                 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
834                 dump_cmd_complete_status(int_ret_code);
835                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
836                 break;
837         default:
838                 printk("%s: Unknown interrupt reason: %02X\n",
839                        DEVICE_NAME, int_ret_code & 0xf);
840                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
841                 break;
842         }
843
844         wake_up(&ps2esdi_int);
845         no_int_yet = FALSE;
846         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
847
848 }
849
850 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
851 {
852         unsigned long flags;
853         u_int status;
854         u_int ending;
855         int i;
856
857         switch (int_ret_code & 0x0f) {
858         case INT_TRANSFER_REQ:
859                 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
860                     (CURRENT->cmd == READ)
861                     ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
862                     : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
863                 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
864                 ending = -1;
865                 break;
866
867         case INT_ATTN_ERROR:
868                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
869                        int_ret_code);
870                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
871                 ending = FAIL;
872                 break;
873
874         case INT_CMD_COMPLETE:
875                 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
876                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
877                         printk("%s: timeout reading status word\n", DEVICE_NAME);
878                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
879                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
880                         if ((++CURRENT->errors) >= MAX_RETRIES)
881                                 ending = FAIL;
882                         else
883                                 ending = -1;
884                         break;
885                 }
886                 status = inw(ESDI_STT_INT);
887                 switch (status & 0x1F) {
888                 case (CMD_READ & 0xff):
889                 case (CMD_WRITE & 0xff):
890                         LITE_OFF;
891                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
892                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
893 #if 0
894                         printk("ps2esdi: cmd_complete b_wait: %p\n", &CURRENT->bh->b_wait);
895 #endif
896                         ending = SUCCES;
897                         break;
898                 default:
899                         printk("%s: interrupt for unknown command %02X\n",
900                                DEVICE_NAME, status & 0x1f);
901                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
902                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
903                         ending = -1;
904                         break;
905                 }
906                 break;
907         case INT_CMD_ECC:
908         case INT_CMD_RETRY:
909         case INT_CMD_ECC_RETRY:
910                 LITE_OFF;
911                 dump_cmd_complete_status(int_ret_code);
912                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
913                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
914                 ending = SUCCES;
915                 break;
916         case INT_CMD_WARNING:
917         case INT_CMD_ABORT:
918         case INT_CMD_FAILED:
919         case INT_DMA_ERR:
920                 LITE_OFF;
921                 dump_cmd_complete_status(int_ret_code);
922                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
923                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
924                 if ((++CURRENT->errors) >= MAX_RETRIES)
925                         ending = FAIL;
926                 else
927                         ending = -1;
928                 break;
929
930         case INT_CMD_BLK_ERR:
931                 dump_cmd_complete_status(int_ret_code);
932                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
933                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
934                 ending = FAIL;
935                 break;
936
937         case INT_CMD_FORMAT:
938                 printk("%s: huh ? Who issued this format command ?\n"
939                        ,DEVICE_NAME);
940                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
941                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
942                 ending = -1;
943                 break;
944
945         case INT_RESET:
946                 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
947                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
948                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
949                 ending = -1;
950                 break;
951
952         default:
953                 printk("%s: Unknown interrupt reason: %02X\n",
954                        DEVICE_NAME, int_ret_code & 0xf);
955                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
956                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
957                 ending = -1;
958                 break;
959         }
960         if(ending != -1) {
961                 spin_lock_irqsave(&io_request_lock, flags);
962                 end_request(ending);
963                 do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
964                 spin_unlock_irqrestore(&io_request_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
1058 static int ps2esdi_open(struct inode *inode, struct file *file)
1059 {
1060         int dev = DEVICE_NR(inode->i_rdev);
1061
1062         if (dev < ps2esdi_drives) {
1063                 while (!ps2esdi_valid[dev])
1064                         sleep_on(&ps2esdi_wait_open);
1065
1066                 access_count[dev]++;
1067
1068                 return (0);
1069         } else
1070                 return (-ENODEV);
1071 }
1072
1073
1074
1075 static int ps2esdi_release(struct inode *inode, struct file *file)
1076 {
1077         int dev = DEVICE_NR(inode->i_rdev);
1078
1079         if (dev < ps2esdi_drives) {
1080                 access_count[dev]--;
1081         }
1082         return 0;
1083 }
1084
1085
1086
1087 static int ps2esdi_ioctl(struct inode *inode,
1088                          struct file *file, u_int cmd, u_long arg)
1089 {
1090
1091         struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1092         int dev = DEVICE_NR(inode->i_rdev), err;
1093
1094         if (inode && (dev < ps2esdi_drives))
1095                 switch (cmd) {
1096                 case HDIO_GETGEO:
1097                         if (arg) {
1098                                 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1099                                         return (err);
1100                                 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1101                                 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1102                                 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1103                                 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1104                                             (long *) &geometry->start);
1105
1106                                 return (0);
1107                         }
1108                         break;
1109
1110                 case BLKGETSIZE:
1111                         if (arg) {
1112                                 if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
1113                                          return (err);
1114                                 put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
1115
1116                                 return (0);
1117                         }
1118                         break;
1119
1120                 case BLKRRPART:
1121                         if (!capable(CAP_SYS_ADMIN)) 
1122                                 return -EACCES;
1123                         return (ps2esdi_reread_partitions(inode->i_rdev));
1124
1125                 case BLKROSET:
1126                 case BLKROGET:
1127                 case BLKRASET:
1128                 case BLKRAGET:
1129                 case BLKFLSBUF:
1130                 case BLKBSZGET:
1131                 case BLKBSZSET:
1132                 case BLKPG:
1133                         return blk_ioctl(inode->i_rdev, cmd, arg);
1134                 }
1135         return (-EINVAL);
1136 }
1137
1138
1139
1140 static int ps2esdi_reread_partitions(kdev_t dev)
1141 {
1142         int target = DEVICE_NR(dev);
1143         int start = target << ps2esdi_gendisk.minor_shift;
1144         int partition;
1145
1146         cli();
1147         ps2esdi_valid[target] = (access_count[target] != 1);
1148         sti();
1149         if (ps2esdi_valid[target])
1150                 return (-EBUSY);
1151
1152         for (partition = ps2esdi_gendisk.max_p - 1;
1153              partition >= 0; partition--) {
1154                 int minor = (start | partition);
1155                 invalidate_device(MKDEV(MAJOR_NR, minor), 1);
1156                 ps2esdi_gendisk.part[minor].start_sect = 0;
1157                 ps2esdi_gendisk.part[minor].nr_sects = 0;
1158         }
1159
1160         grok_partitions(&ps2esdi_gendisk, target, 1<<6, 
1161                 ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect);
1162
1163         ps2esdi_valid[target] = 1;
1164         wake_up(&ps2esdi_wait_open);
1165
1166         return (0);
1167 }
1168
1169 static void ps2esdi_reset_timer(unsigned long unused)
1170 {
1171
1172         int status;
1173
1174         status = inb(ESDI_INTRPT);
1175         if ((status & 0xf) == INT_RESET) {
1176                 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1177                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1178                 reset_status = 1;
1179         }
1180         wake_up(&ps2esdi_int);
1181 }
1182
1183 #endif