OSDN Git Service

[PATCH] ps2esdi: typo may cause premature timeout
[linux-kernel-docs/linux-2.4.36.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 #include <linux/module.h>
51
52 #include <asm/system.h>
53 #include <asm/io.h>
54 #include <asm/segment.h>
55 #include <asm/dma.h>
56 #include <asm/mca_dma.h>
57 #include <asm/uaccess.h>
58
59 #define PS2ESDI_IRQ 14
60 #define MAX_HD 2
61 #define MAX_RETRIES 5
62 #define MAX_16BIT 65536
63 #define ESDI_TIMEOUT   0xf000
64 #define ESDI_STAT_TIMEOUT 4
65
66 #define TYPE_0_CMD_BLK_LENGTH 2
67 #define TYPE_1_CMD_BLK_LENGTH 4
68
69
70 static void reset_ctrl(void);
71
72 int ps2esdi_init(void);
73
74 static void ps2esdi_geninit(void);
75
76 static void do_ps2esdi_request(request_queue_t * q);
77
78 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
79
80 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
81 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
82
83 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
84
85 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
86
87 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
88                                       struct pt_regs *regs);
89 static void (*current_int_handler) (u_int) = NULL;
90 static void ps2esdi_normal_interrupt_handler(u_int);
91 static void ps2esdi_initial_reset_int_handler(u_int);
92 static void ps2esdi_geometry_int_handler(u_int);
93
94 static int ps2esdi_open(struct inode *inode, struct file *file);
95
96 static int ps2esdi_release(struct inode *inode, struct file *file);
97
98 static int ps2esdi_ioctl(struct inode *inode, struct file *file,
99                          u_int cmd, u_long arg);
100
101 static int ps2esdi_reread_partitions(kdev_t dev);
102
103 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
104
105 static void dump_cmd_complete_status(u_int int_ret_code);
106
107 static void ps2esdi_get_device_cfg(void);
108
109 static void ps2esdi_reset_timer(unsigned long unused);
110
111 static u_int dma_arb_level;             /* DMA arbitration level */
112
113 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
114 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
115
116 static int no_int_yet;
117 static int access_count[MAX_HD];
118 static char ps2esdi_valid[MAX_HD];
119 static int ps2esdi_sizes[MAX_HD << 6];
120 static int ps2esdi_blocksizes[MAX_HD << 6];
121 static int ps2esdi_maxsect[MAX_HD << 6];
122 static int ps2esdi_drives;
123 static struct hd_struct ps2esdi[MAX_HD << 6];
124 static u_short io_base;
125 static struct timer_list esdi_timer = { function: ps2esdi_reset_timer };
126 static int reset_status;
127 static int ps2esdi_slot = -1;
128 static int tp720esdi = 0;       /* Is it Integrated ESDI of ThinkPad-720? */
129 static int intg_esdi = 0;       /* If integrated adapter */
130 struct ps2esdi_i_struct {
131         unsigned int head, sect, cyl, wpcom, lzone, ctl;
132 };
133
134 #if 0
135 #if 0                           /* try both - I don't know which one is better... UB */
136 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
137 {
138         {4, 48, 1553, 0, 0, 0},
139         {0, 0, 0, 0, 0, 0}};
140 #else
141 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
142 {
143         {64, 32, 161, 0, 0, 0},
144         {0, 0, 0, 0, 0, 0}};
145 #endif
146 #endif
147 static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
148 {
149         {0, 0, 0, 0, 0, 0},
150         {0, 0, 0, 0, 0, 0}};
151
152 static struct block_device_operations ps2esdi_fops =
153 {
154         owner:          THIS_MODULE,
155         open:           ps2esdi_open,
156         release:        ps2esdi_release,
157         ioctl:          ps2esdi_ioctl,
158 };
159
160 static struct gendisk ps2esdi_gendisk =
161 {
162         major:          MAJOR_NR,
163         major_name:     "ed",
164         minor_shift:    6,
165         max_p:          1 << 6,
166         part:           ps2esdi,
167         sizes:          ps2esdi_sizes,
168         real_devices:   (void *)ps2esdi_info,
169         fops:           &ps2esdi_fops,
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         add_gendisk(&ps2esdi_gendisk);
188         ps2esdi_geninit();
189         return 0;
190 }                               /* ps2esdi_init */
191
192 #ifdef MODULE
193
194 static int cyl[MAX_HD] = {-1,-1};
195 static int head[MAX_HD] = {-1, -1};
196 static int sect[MAX_HD] = {-1, -1};
197
198 MODULE_PARM(tp720esdi, "i");
199 MODULE_PARM(cyl, "i");
200 MODULE_PARM(head, "i");
201 MODULE_PARM(track, "i");
202 MODULE_LICENSE("GPL");
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                 mca_mark_as_unused(ps2esdi_slot);
228                 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
229         }
230         release_region(io_base, 4);
231         free_dma(dma_arb_level);
232         free_irq(PS2ESDI_IRQ, NULL);
233         devfs_unregister_blkdev(MAJOR_NR, "ed");
234         del_gendisk(&ps2esdi_gendisk);
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
470 #if 0
471         printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld, buffer: %p\n",
472                DEVICE_NAME,
473                CURRENT_DEV, MINOR(CURRENT->rq_dev),
474                CURRENT->cmd, CURRENT->sector,
475                CURRENT->current_nr_sectors, CURRENT->buffer);
476 #endif
477
478         /* standard macro that ensures that requests are really on the
479            list + sanity checks.                     */
480         INIT_REQUEST;
481
482         if (virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
483                 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
484                 end_request(FAIL);
485         }                       /* check for above 16Mb dmas */
486         else if ((CURRENT_DEV < ps2esdi_drives) &&
487             (CURRENT->sector + CURRENT->current_nr_sectors <=
488              ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
489 #if 0
490                 printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld\n",
491                        DEVICE_NAME,
492                        CURRENT_DEV, MINOR(CURRENT->rq_dev),
493                        CURRENT->cmd, CURRENT->sector,
494                        CURRENT->current_nr_sectors);
495 #endif
496
497
498                 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
499
500 #if 0
501                 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
502 #endif
503                 count = CURRENT->current_nr_sectors;
504                 switch (CURRENT->cmd) {
505                 case READ:
506                         ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
507                         break;
508                 case WRITE:
509                         ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
510                         break;
511                 default:
512                         printk("%s: Unknown command\n", DEVICE_NAME);
513                         end_request(FAIL);
514                         break;
515                 }               /* handle different commands */
516         }
517         /* is request is valid */ 
518         else {
519                 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
520                        CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
521                 end_request(FAIL);
522         }
523
524 }                               /* main strategy routine */
525
526 /* resets the ESDI adapter */
527 static void reset_ctrl(void)
528 {
529
530         u_long expire;
531         u_short status;
532
533         /* enable interrupts on the controller */
534         status = inb(ESDI_INTRPT);
535         outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);     /* to be sure we don't have
536                                                            any interrupt pending... */
537         outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
538
539         /* read the ESDI status port - if the controller is not busy,
540            simply do a soft reset (fast) - otherwise we'll have to do a
541            hard (slow) reset.  */
542         if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
543                 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
544                 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
545         }
546         /* soft reset */ 
547         else {
548                 /*BA */
549                 printk("%s: hard reset...\n", DEVICE_NAME);
550                 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
551                 expire = jiffies + 2*HZ;
552                 while (time_before(jiffies, expire));
553                 outb_p(1, ESDI_CONTROL);
554         }                       /* hard reset */
555
556
557 }                               /* reset the controller */
558
559 /* called by the strategy routine to handle read and write requests */
560 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
561 {
562
563         u_short track, head, cylinder, sector;
564         u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
565         int err;
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         spin_unlock_irq(&io_request_lock);
584         /* send the command block to the controller */
585         err = ps2esdi_out_cmd_blk(cmd_blk);
586         spin_lock_irq(&io_request_lock);
587         
588         if (err) {
589                 printk(KERN_ERR "%s: Controller failed\n", DEVICE_NAME);
590                 if ((++CURRENT->errors) >= MAX_RETRIES)
591                         end_request(FAIL);
592         }
593         /* check for failure to put out the command block */ 
594         else {
595 #if 0
596                 printk("%s: waiting for xfer\n", DEVICE_NAME);
597 #endif
598                 /* turn disk lights on */
599                 LITE_ON;
600         }
601
602 }                               /* ps2esdi_readwrite */
603
604 /* fill out the command block */
605 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
606  u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
607 {
608
609         cmd_blk[0] = (drive << 5) | cmd;
610         cmd_blk[1] = length;
611         cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
612         cmd_blk[3] = (cyl & 0x3E0) >> 5;
613
614 }                               /* fill out the command block */
615
616 /* write a command block to the controller */
617 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
618 {
619
620         int i, j;
621         u_char status;
622
623         /* enable interrupts */
624         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
625
626         /* do not write to the controller, if it is busy */
627         for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
628                                                           STATUS_BUSY););
629
630 #if 0
631         printk("%s: i(1)=%d\n", DEVICE_NAME, i);
632 #endif
633
634         /* if device is still busy - then just time out */
635         if (inb(ESDI_STATUS) & STATUS_BUSY) {
636                 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
637                 return ERROR;
638         }                       /* timeout ??? */
639         /* Set up the attention register in the controller */
640         outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
641
642 #if 0
643         printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
644 #endif
645
646         /* one by one send each word out */
647         for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
648                 status = inb(ESDI_STATUS);
649                 for (j = jiffies + ESDI_STAT_TIMEOUT;
650                      time_after(j, jiffies) && (status & STATUS_BUSY) &&
651                    (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
652                 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
653 #if 0
654                         printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
655 #endif
656                         outw(*cmd_blk++, ESDI_CMD_INT);
657                 } else {
658                         printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
659                                DEVICE_NAME, status);
660                         return ERROR;
661                 }
662         }                       /* send all words out */
663         return OK;
664 }                               /* send out the commands */
665
666
667 /* prepare for dma - do all the necessary setup */
668 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
669 {
670         unsigned long flags;
671 #if 0
672         printk("ps2esdi: b_wait: %p\n", &CURRENT->bh->b_wait);
673 #endif
674         flags = claim_dma_lock();
675
676         mca_disable_dma(dma_arb_level);
677
678         mca_set_dma_addr(dma_arb_level, virt_to_bus(buffer));
679
680         mca_set_dma_count(dma_arb_level, length * 512 / 2);
681
682         mca_set_dma_mode(dma_arb_level, dma_xmode);
683
684         mca_enable_dma(dma_arb_level);
685
686         release_dma_lock(flags);
687
688 }                               /* prepare for dma */
689
690
691
692 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
693                                       struct pt_regs *regs)
694 {
695         u_int int_ret_code;
696
697         if (inb(ESDI_STATUS) & STATUS_INTR) {
698                 int_ret_code = inb(ESDI_INTRPT);
699                 if (current_int_handler) {
700                         /* Disable adapter interrupts till processing is finished */
701                         outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
702                         current_int_handler(int_ret_code);
703                 } else
704                         printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
705         } else {
706                 return;
707         }
708 }
709
710 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
711 {
712
713         switch (int_ret_code & 0xf) {
714         case INT_RESET:
715                 /*BA */
716                 printk("%s: initial reset completed.\n", DEVICE_NAME);
717                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
718                 wake_up(&ps2esdi_int);
719                 break;
720         case INT_ATTN_ERROR:
721                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
722                        int_ret_code);
723                 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
724                 break;
725         default:
726                 printk("%s: initial reset handler received interrupt: %02X\n",
727                        DEVICE_NAME, int_ret_code);
728                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
729                 break;
730         }
731         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
732 }
733
734
735 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
736 {
737         u_int status, drive_num;
738         unsigned long rba;
739         int i;
740
741         drive_num = int_ret_code >> 5;
742         switch (int_ret_code & 0xf) {
743         case INT_CMD_COMPLETE:
744                 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
745                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
746                         printk("%s: timeout reading status word\n", DEVICE_NAME);
747                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
748                         break;
749                 }
750                 status = inw(ESDI_STT_INT);
751                 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
752 #define REPLY_WORDS 5           /* we already read word 0 */
753                         u_short reply[REPLY_WORDS];
754
755                         if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
756                                 /*BA */
757                                 printk("%s: Device Configuration Status for drive %u\n",
758                                        DEVICE_NAME, drive_num);
759
760                                 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
761
762                                 printk
763                                     ("Config bits: %s%s%s%s%s\n",
764                                      (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
765                                      ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
766                                  ? "Zero Defect, " : "Defects Present, ",
767                                      (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
768                                      (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
769                                      (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
770
771                                 rba = reply[1] | ((unsigned long) reply[2] << 16);
772                                 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
773
774                                 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
775                                        DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
776
777                                 if (!ps2esdi_info[drive_num].head) {
778                                         ps2esdi_info[drive_num].head = 64;
779                                         ps2esdi_info[drive_num].sect = 32;
780                                         ps2esdi_info[drive_num].cyl = rba / (64 * 32);
781                                         ps2esdi_info[drive_num].wpcom = 0;
782                                         ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
783                                         ps2esdi_info[drive_num].ctl = 8;
784                                         if (tp720esdi) {        /* store the retrieved parameters */
785                                                 ps2esdi_info[0].head = reply[4] & 0Xff;
786                                                 ps2esdi_info[0].sect = reply[4] >> 8;
787                                                 ps2esdi_info[0].cyl = reply[3];
788                                                 ps2esdi_info[0].wpcom = 0;
789                                                 ps2esdi_info[0].lzone = reply[3];
790                                         } else {
791                                                 if (!intg_esdi)
792                                                         ps2esdi_drives++;
793                                         }
794                                 }
795 #ifdef OBSOLETE
796                                 if (!ps2esdi_info[drive_num].head) {
797                                         ps2esdi_info[drive_num].head = reply[4] & 0Xff;
798                                         ps2esdi_info[drive_num].sect = reply[4] >> 8;
799                                         ps2esdi_info[drive_num].cyl = reply[3];
800                                         ps2esdi_info[drive_num].wpcom = 0;
801                                         ps2esdi_info[drive_num].lzone = reply[3];
802                                         if (tp720esdi) {        /* store the retrieved parameters */
803                                                 ps2esdi_info[0].head = reply[4] & 0Xff;
804                                                 ps2esdi_info[0].sect = reply[4] >> 8;
805                                                 ps2esdi_info[0].cyl = reply[3];
806                                                 ps2esdi_info[0].wpcom = 0;
807                                                 ps2esdi_info[0].lzone = reply[3];
808                                         } else {
809                                                 ps2esdi_drives++;
810                                         }
811                                 }
812 #endif
813
814                         } else
815                                 printk("%s: failed while getting device config\n", DEVICE_NAME);
816 #undef REPLY_WORDS
817                 } else
818                         printk("%s: command %02X unknown by geometry handler\n",
819                                DEVICE_NAME, status & 0x1f);
820
821                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
822                 break;
823
824         case INT_ATTN_ERROR:
825                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
826                        int_ret_code);
827                 printk("%s: Device not available\n", DEVICE_NAME);
828                 break;
829         case INT_CMD_ECC:
830         case INT_CMD_RETRY:
831         case INT_CMD_ECC_RETRY:
832         case INT_CMD_WARNING:
833         case INT_CMD_ABORT:
834         case INT_CMD_FAILED:
835         case INT_DMA_ERR:
836         case INT_CMD_BLK_ERR:
837                 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
838                 dump_cmd_complete_status(int_ret_code);
839                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
840                 break;
841         default:
842                 printk("%s: Unknown interrupt reason: %02X\n",
843                        DEVICE_NAME, int_ret_code & 0xf);
844                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
845                 break;
846         }
847
848         wake_up(&ps2esdi_int);
849         no_int_yet = FALSE;
850         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
851
852 }
853
854 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
855 {
856         unsigned long flags;
857         u_int status;
858         u_int ending;
859         int i;
860
861         switch (int_ret_code & 0x0f) {
862         case INT_TRANSFER_REQ:
863                 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
864                     (CURRENT->cmd == READ)
865                     ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
866                     : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
867                 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
868                 ending = -1;
869                 break;
870
871         case INT_ATTN_ERROR:
872                 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
873                        int_ret_code);
874                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
875                 ending = FAIL;
876                 break;
877
878         case INT_CMD_COMPLETE:
879                 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
880                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
881                         printk("%s: timeout reading status word\n", DEVICE_NAME);
882                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
883                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
884                         if ((++CURRENT->errors) >= MAX_RETRIES)
885                                 ending = FAIL;
886                         else
887                                 ending = -1;
888                         break;
889                 }
890                 status = inw(ESDI_STT_INT);
891                 switch (status & 0x1F) {
892                 case (CMD_READ & 0xff):
893                 case (CMD_WRITE & 0xff):
894                         LITE_OFF;
895                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
896                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
897 #if 0
898                         printk("ps2esdi: cmd_complete b_wait: %p\n", &CURRENT->bh->b_wait);
899 #endif
900                         ending = SUCCES;
901                         break;
902                 default:
903                         printk("%s: interrupt for unknown command %02X\n",
904                                DEVICE_NAME, status & 0x1f);
905                         outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
906                         outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
907                         ending = -1;
908                         break;
909                 }
910                 break;
911         case INT_CMD_ECC:
912         case INT_CMD_RETRY:
913         case INT_CMD_ECC_RETRY:
914                 LITE_OFF;
915                 dump_cmd_complete_status(int_ret_code);
916                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
917                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
918                 ending = SUCCES;
919                 break;
920         case INT_CMD_WARNING:
921         case INT_CMD_ABORT:
922         case INT_CMD_FAILED:
923         case INT_DMA_ERR:
924                 LITE_OFF;
925                 dump_cmd_complete_status(int_ret_code);
926                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
927                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
928                 if ((++CURRENT->errors) >= MAX_RETRIES)
929                         ending = FAIL;
930                 else
931                         ending = -1;
932                 break;
933
934         case INT_CMD_BLK_ERR:
935                 dump_cmd_complete_status(int_ret_code);
936                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
937                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
938                 ending = FAIL;
939                 break;
940
941         case INT_CMD_FORMAT:
942                 printk("%s: huh ? Who issued this format command ?\n"
943                        ,DEVICE_NAME);
944                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
945                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
946                 ending = -1;
947                 break;
948
949         case INT_RESET:
950                 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
951                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
952                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
953                 ending = -1;
954                 break;
955
956         default:
957                 printk("%s: Unknown interrupt reason: %02X\n",
958                        DEVICE_NAME, int_ret_code & 0xf);
959                 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
960                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
961                 ending = -1;
962                 break;
963         }
964         if(ending != -1) {
965                 spin_lock_irqsave(&io_request_lock, flags);
966                 end_request(ending);
967                 do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
968                 spin_unlock_irqrestore(&io_request_lock, flags);
969         }
970 }                               /* handle interrupts */
971
972
973
974 static int ps2esdi_read_status_words(int num_words,
975                                      int max_words,
976                                      u_short * buffer)
977 {
978         int i;
979
980         for (; max_words && num_words; max_words--, num_words--, buffer++) {
981                 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
982                 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
983                         printk("%s: timeout reading status word\n", DEVICE_NAME);
984                         return FAIL;
985                 }
986                 *buffer = inw(ESDI_STT_INT);
987         }
988         return SUCCES;
989 }
990
991
992
993
994 static void dump_cmd_complete_status(u_int int_ret_code)
995 {
996 #define WAIT_FOR_STATUS \
997   for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
998     if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
999     printk("%s: timeout reading status word\n",DEVICE_NAME); \
1000     return; \
1001     }
1002
1003         int i, word_count;
1004         u_short stat_word;
1005         u_long rba;
1006
1007         printk("%s: Device: %u, interrupt ID: %02X\n",
1008                DEVICE_NAME, int_ret_code >> 5,
1009                int_ret_code & 0xf);
1010
1011         WAIT_FOR_STATUS;
1012         stat_word = inw(ESDI_STT_INT);
1013         word_count = (stat_word >> 8) - 1;
1014         printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1015                stat_word & 0xff);
1016
1017         if (word_count--) {
1018                 WAIT_FOR_STATUS;
1019                 stat_word = inw(ESDI_STT_INT);
1020                 printk("%s: command status code: %02X, command error code: %02X\n",
1021                        DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1022         }
1023         if (word_count--) {
1024                 WAIT_FOR_STATUS;
1025                 stat_word = inw(ESDI_STT_INT);
1026                 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1027                        (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1028                   (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1029                        (stat_word & 0x0400) ? "Write Fault, " : "",
1030                        (stat_word & 0x0200) ? "Track 0, " : "",
1031                 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1032                        stat_word >> 8);
1033         }
1034         if (word_count--) {
1035                 WAIT_FOR_STATUS;
1036                 stat_word = inw(ESDI_STT_INT);
1037                 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1038         }
1039         if (word_count -= 2) {
1040                 WAIT_FOR_STATUS;
1041                 rba = inw(ESDI_STT_INT);
1042                 WAIT_FOR_STATUS;
1043                 rba |= inw(ESDI_STT_INT) << 16;
1044                 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1045                        (u_short) ((rba & 0x1ff80000) >> 11),
1046                  (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1047         } else
1048                 printk("\n");
1049
1050         if (word_count--) {
1051                 WAIT_FOR_STATUS;
1052                 stat_word = inw(ESDI_STT_INT);
1053                 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1054         }
1055         printk("\n");
1056
1057 #undef WAIT_FOR_STATUS
1058
1059 }
1060
1061
1062 static int ps2esdi_open(struct inode *inode, struct file *file)
1063 {
1064         int dev = DEVICE_NR(inode->i_rdev);
1065
1066         if (dev < ps2esdi_drives) {
1067                 while (!ps2esdi_valid[dev])
1068                         sleep_on(&ps2esdi_wait_open);
1069
1070                 access_count[dev]++;
1071
1072                 return (0);
1073         } else
1074                 return (-ENODEV);
1075 }
1076
1077
1078
1079 static int ps2esdi_release(struct inode *inode, struct file *file)
1080 {
1081         int dev = DEVICE_NR(inode->i_rdev);
1082
1083         if (dev < ps2esdi_drives) {
1084                 access_count[dev]--;
1085         }
1086         return 0;
1087 }
1088
1089
1090
1091 static int ps2esdi_ioctl(struct inode *inode,
1092                          struct file *file, u_int cmd, u_long arg)
1093 {
1094
1095         struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1096         int dev = DEVICE_NR(inode->i_rdev), err;
1097
1098         if (inode && (dev < ps2esdi_drives))
1099                 switch (cmd) {
1100                 case HDIO_GETGEO:
1101                         if (arg) {
1102                                 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1103                                         return (err);
1104                                 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1105                                 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1106                                 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1107                                 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1108                                             (long *) &geometry->start);
1109
1110                                 return (0);
1111                         }
1112                         break;
1113
1114                 case BLKRRPART:
1115                         if (!capable(CAP_SYS_ADMIN)) 
1116                                 return -EACCES;
1117                         return (ps2esdi_reread_partitions(inode->i_rdev));
1118
1119                 case BLKGETSIZE:
1120                 case BLKGETSIZE64:
1121                 case BLKROSET:
1122                 case BLKROGET:
1123                 case BLKRASET:
1124                 case BLKRAGET:
1125                 case BLKFLSBUF:
1126                 case BLKBSZGET:
1127                 case BLKBSZSET:
1128                 case BLKPG:
1129                         return blk_ioctl(inode->i_rdev, cmd, arg);
1130                 }
1131         return (-EINVAL);
1132 }
1133
1134
1135
1136 static int ps2esdi_reread_partitions(kdev_t dev)
1137 {
1138         int target = DEVICE_NR(dev);
1139         int start = target << ps2esdi_gendisk.minor_shift;
1140         int partition;
1141
1142         ps2esdi_valid[target] = (access_count[target] != 1);
1143         if (ps2esdi_valid[target])
1144                 return (-EBUSY);
1145
1146         for (partition = ps2esdi_gendisk.max_p - 1;
1147              partition >= 0; partition--) {
1148                 int minor = (start | partition);
1149                 invalidate_device(MKDEV(MAJOR_NR, minor), 1);
1150                 ps2esdi_gendisk.part[minor].start_sect = 0;
1151                 ps2esdi_gendisk.part[minor].nr_sects = 0;
1152         }
1153
1154         grok_partitions(&ps2esdi_gendisk, target, 1<<6, 
1155                 ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect);
1156
1157         ps2esdi_valid[target] = 1;
1158         wake_up(&ps2esdi_wait_open);
1159
1160         return (0);
1161 }
1162
1163 static void ps2esdi_reset_timer(unsigned long unused)
1164 {
1165
1166         int status;
1167
1168         status = inb(ESDI_INTRPT);
1169         if ((status & 0xf) == INT_RESET) {
1170                 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1171                 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1172                 reset_status = 1;
1173         }
1174         wake_up(&ps2esdi_int);
1175 }
1176
1177 #endif