Merge with Linux 2.4.0-test6-pre9.
[linux-2.6/linux-mips.git] / drivers / block / ps2esdi.c
blob8ff56a70aac8185b92e5596a63b45d93bb3c12bf
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 */
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 */
17 /* BA Modified for ThinkPad 720 by Boris Ashkinazi */
18 /* (bash@vnet.ibm.com) 08/08/95 */
20 /* Modified further for ThinkPad-720C by Uri Blumenthal */
21 /* (uri@watson.ibm.com) Sep 11, 1995 */
23 /* TODO :
24 + Timeouts
25 + Get disk parameters
26 + DMA above 16MB
27 + reset after read/write error
30 #include <linux/config.h>
31 #include <linux/major.h>
33 #ifdef CONFIG_BLK_DEV_PS2
35 #define MAJOR_NR PS2ESDI_MAJOR
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>
51 #include <asm/system.h>
52 #include <asm/io.h>
53 #include <asm/segment.h>
54 #include <asm/dma.h>
55 #include <asm/uaccess.h>
57 #define PS2ESDI_IRQ 14
58 #define MAX_HD 1
59 #define MAX_RETRIES 5
60 #define MAX_16BIT 65536
61 #define ESDI_TIMEOUT 0xf000
62 #define ESDI_STAT_TIMEOUT 4
64 #define TYPE_0_CMD_BLK_LENGTH 2
65 #define TYPE_1_CMD_BLK_LENGTH 4
68 static void reset_ctrl(void);
70 int ps2esdi_init(void);
72 static void ps2esdi_geninit(void);
74 static void do_ps2esdi_request(request_queue_t * q);
76 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
78 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
79 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
81 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
83 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
85 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
86 struct pt_regs *regs);
87 static void (*current_int_handler) (u_int) = NULL;
88 static void ps2esdi_normal_interrupt_handler(u_int);
89 static void ps2esdi_initial_reset_int_handler(u_int);
90 static void ps2esdi_geometry_int_handler(u_int);
92 static void ps2esdi_continue_request(void);
94 static int ps2esdi_open(struct inode *inode, struct file *file);
96 static int ps2esdi_release(struct inode *inode, struct file *file);
98 static int ps2esdi_ioctl(struct inode *inode, struct file *file,
99 u_int cmd, u_long arg);
101 static int ps2esdi_reread_partitions(kdev_t dev);
103 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
105 static void dump_cmd_complete_status(u_int int_ret_code);
107 static void ps2esdi_get_device_cfg(void);
109 void ps2esdi_reset_timer(unsigned long unused);
111 u_int dma_arb_level; /* DMA arbitration level */
113 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
114 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
116 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_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 int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
128 int intg_esdi = 0; /* If integrated adapter */
129 struct ps2esdi_i_struct {
130 unsigned int head, sect, cyl, wpcom, lzone, ctl;
133 #if 0
134 #if 0 /* try both - I don't know which one is better... UB */
135 struct ps2esdi_i_struct ps2esdi_info[] =
137 {4, 48, 1553, 0, 0, 0},
138 {0, 0, 0, 0, 0, 0}};
139 #else
140 struct ps2esdi_i_struct ps2esdi_info[] =
142 {64, 32, 161, 0, 0, 0},
143 {0, 0, 0, 0, 0, 0}};
144 #endif
145 #endif
146 struct ps2esdi_i_struct ps2esdi_info[] =
148 {0, 0, 0, 0, 0, 0},
149 {0, 0, 0, 0, 0, 0}};
151 static struct block_device_operations ps2esdi_fops =
153 open: ps2esdi_open,
154 release: ps2esdi_release,
155 ioctl: ps2esdi_ioctl,
158 static struct gendisk ps2esdi_gendisk =
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 */
172 /* initialization routine called by ll_rw_blk.c */
173 int __init ps2esdi_init(void)
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;
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 */
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 */
193 #ifdef MODULE
195 int cyl[2] = {-1,-1};
196 int head[2] = {-1, -1};
197 int sect[2] = {-1, -1};
199 MODULE_PARM(tp720esdi, "i");
200 MODULE_PARM(cyl, "i");
201 MODULE_PARM(head, "i");
202 MODULE_PARM(track, "i");
204 int init_module(void) {
205 int drive;
207 for(drive = 0; drive <= 1; drive++) {
208 struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
210 if (cyl[drive] != -1) {
211 info->cyl = info->lzone = cyl[drive];
212 info->wpcom = 0;
214 if (head[drive] != -1) {
215 info->head = head[drive];
216 info->ctl = (head[drive] > 8 ? 8 : 0);
218 if (sect[drive] != -1) info->sect = sect[drive];
220 return ps2esdi_init();
223 void
224 cleanup_module(void)
226 if(ps2esdi_slot)
228 mca_mark_as_unused(ps2esdi_slot);
229 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
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));
237 #endif /* MODULE */
239 /* handles boot time command line parameters */
240 void __init tp720_setup(char *str, int *ints)
242 /* no params, just sets the tp720esdi flag if it exists */
244 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
245 tp720esdi = 1;
248 void __init ed_setup(char *str, int *ints)
250 int hdind = 0;
252 /* handles 3 parameters only - corresponding to
253 1. Number of cylinders
254 2. Number of heads
255 3. Sectors/track
258 if (ints[0] != 3)
259 return;
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]);
265 /* set the index into device specific information table */
266 if (ps2esdi_info[0].head != 0)
267 hdind = 1;
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 */
281 static int ps2esdi_getinfo(char *buf, int slot, void *d)
283 int len = 0;
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);
291 return len;
294 /* ps2 esdi specific initialization - called thru the gendisk chain */
295 static void __init ps2esdi_geninit(void)
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.
310 int slot = 0, i, reset_start, reset_end;
311 u_char status;
312 unsigned short adapterID;
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;
330 ps2esdi_slot = slot;
331 mca_mark_as_used(slot);
332 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
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
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;
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)
362 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
363 return;
365 if (status & STATUS_ALTERNATE)
366 io_base = ALT_IO_BASE;
367 else
368 io_base = PRIMARY_IO_BASE;
370 /* get the dma arbitration level */
371 dma_arb_level = (status >> 2) & 0xf;
373 /* BA */
374 printk("%s: DMA arbitration level : %d\n",
375 DEVICE_NAME, dma_arb_level);
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);
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);
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;
403 /* finally this part sets up some global data structures etc. */
405 ps2esdi_get_device_cfg();
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! */
414 current_int_handler = ps2esdi_normal_interrupt_handler;
416 ps2esdi_gendisk.nr_real = ps2esdi_drives;
418 for (i = 0; i < (MAX_HD << 6); i++)
419 ps2esdi_blocksizes[i] = 1024;
421 request_dma(dma_arb_level, "ed");
422 request_region(io_base, 4, "ed");
423 blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
425 for (i = 0; i < ps2esdi_drives; i++) {
426 register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6,
427 &ps2esdi_fops,
428 ps2esdi_info[i].head * ps2esdi_info[i].sect *
429 ps2esdi_info[i].cyl);
430 ps2esdi_valid[i] = 1;
434 static void __init ps2esdi_get_device_cfg(void)
436 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
438 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
439 current_int_handler = ps2esdi_geometry_int_handler;
440 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
441 cmd_blk[1] = 0;
442 no_int_yet = TRUE;
443 ps2esdi_out_cmd_blk(cmd_blk);
444 if (no_int_yet)
445 sleep_on(&ps2esdi_int);
447 if (ps2esdi_drives > 1) {
448 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
449 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
450 cmd_blk[1] = 0;
451 no_int_yet = TRUE;
452 ps2esdi_out_cmd_blk(cmd_blk);
453 if (no_int_yet)
454 sleep_on(&ps2esdi_int);
455 } /* if second physical drive is present */
456 return;
459 /* strategy routine that handles most of the IO requests */
460 static void do_ps2esdi_request(request_queue_t * q)
462 u_int block, count;
463 /* since, this routine is called with interrupts cleared - they
464 must be before it finishes */
465 sti();
467 #if 0
468 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
469 DEVICE_NAME,
470 CURRENT_DEV, MINOR(CURRENT->rq_dev),
471 CURRENT->cmd, CURRENT->sector,
472 CURRENT->nr_sectors, CURRENT->buffer);
473 #endif
475 /* standard macro that ensures that requests are really on the
476 list + sanity checks. */
477 INIT_REQUEST;
479 if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) {
480 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
481 end_request(FAIL);
482 if (!QUEUE_EMPTY)
483 do_ps2esdi_request(q);
484 return;
485 } /* check for above 16Mb dmas */
486 if ((CURRENT_DEV < ps2esdi_drives) &&
487 (CURRENT->sector + 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->dev),
493 CURRENT->cmd, CURRENT->sector,
494 CURRENT->nr_sectors);
495 #endif
498 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
500 #if 0
501 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
502 #endif
503 count = CURRENT->nr_sectors;
504 switch (CURRENT->cmd) {
505 case READ:
506 ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
507 return;
508 break;
509 case WRITE:
510 ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
511 return;
512 break;
513 default:
514 printk("%s: Unknown command\n", DEVICE_NAME);
515 end_request(FAIL);
516 if (!QUEUE_EMPTY)
517 do_ps2esdi_request(q);
518 break;
519 } /* handle different commands */
521 /* is request is valid */
522 else {
523 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
524 CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
525 end_request(FAIL);
526 if (!QUEUE_EMPTY)
527 do_ps2esdi_request(q);
530 } /* main strategy routine */
532 /* resets the ESDI adapter */
533 static void reset_ctrl(void)
536 u_long expire;
537 u_short status;
539 /* enable interrupts on the controller */
540 status = inb(ESDI_INTRPT);
541 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
542 any interrupt pending... */
543 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
545 /* read the ESDI status port - if the controller is not busy,
546 simply do a soft reset (fast) - otherwise we'll have to do a
547 hard (slow) reset. */
548 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
549 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
550 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
552 /* soft reset */
553 else {
554 /*BA */
555 printk("%s: hard reset...\n", DEVICE_NAME);
556 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
557 expire = jiffies + 2*HZ;
558 while (time_before(jiffies, expire));
559 outb_p(1, ESDI_CONTROL);
560 } /* hard reset */
563 } /* reset the controller */
565 /* called by the strategy routine to handle read and write requests */
566 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
569 u_short track, head, cylinder, sector;
570 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
572 /* do some relevant arithmatic */
573 CURRENT->current_nr_sectors =
574 (count < (2 * MAX_16BIT / SECT_SIZE)) ? count : (2 * MAX_16BIT / SECT_SIZE);
575 track = block / ps2esdi_info[drive].sect;
576 head = track % ps2esdi_info[drive].head;
577 cylinder = track / ps2esdi_info[drive].head;
578 sector = block % ps2esdi_info[drive].sect;
580 #if 0
581 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
582 #endif
583 /* call the routine that actually fills out a command block */
584 ps2esdi_fill_cmd_block
585 (cmd_blk,
586 (cmd == READ) ? CMD_READ : CMD_WRITE,
587 cylinder, head, sector,
588 CURRENT->current_nr_sectors, drive);
590 /* send the command block to the controller */
591 if (ps2esdi_out_cmd_blk(cmd_blk)) {
592 printk("%s: Controller failed\n", DEVICE_NAME);
593 if ((++CURRENT->errors) < MAX_RETRIES)
594 return do_ps2esdi_request(NULL);
595 else {
596 end_request(FAIL);
597 if (!QUEUE_EMPTY)
598 do_ps2esdi_request(NULL);
601 /* check for failure to put out the command block */
602 else {
603 #if 0
604 printk("%s: waiting for xfer\n", DEVICE_NAME);
605 #endif
606 /* turn disk lights on */
607 LITE_ON;
610 } /* ps2esdi_readwrite */
612 /* fill out the command block */
613 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
614 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
617 cmd_blk[0] = (drive << 5) | cmd;
618 cmd_blk[1] = length;
619 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
620 cmd_blk[3] = (cyl & 0x3E0) >> 5;
622 } /* fill out the command block */
624 /* write a command block to the controller */
625 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
628 int i, j;
629 u_char status;
631 /* enable interrupts */
632 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
634 /* do not write to the controller, if it is busy */
635 for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
636 STATUS_BUSY););
638 #if 0
639 printk("%s: i(1)=%d\n", DEVICE_NAME, i);
640 #endif
642 /* if device is still busy - then just time out */
643 if (inb(ESDI_STATUS) & STATUS_BUSY) {
644 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
645 return ERROR;
646 } /* timeout ??? */
647 /* Set up the attention register in the controller */
648 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
650 #if 0
651 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
652 #endif
654 /* one by one send each word out */
655 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
656 status = inb(ESDI_STATUS);
657 for (j = jiffies + ESDI_STAT_TIMEOUT;
658 time_after(j, jiffies) && (status & STATUS_BUSY) &&
659 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
660 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
661 #if 0
662 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
663 #endif
664 outw(*cmd_blk++, ESDI_CMD_INT);
665 } else {
666 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
667 DEVICE_NAME, status);
668 return ERROR;
670 } /* send all words out */
671 return OK;
672 } /* send out the commands */
675 /* prepare for dma - do all the necessary setup */
676 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
678 u_int tc;
680 buffer=(char *)virt_to_bus(buffer);
682 #if 0
683 printk("ps2esdi: b_wait: %p\n", CURRENT->bh->b_wait);
684 #endif
685 cli();
687 outb(dma_arb_level | DMA_MASK_CHAN, PORT_DMA_FN);
689 outb(dma_arb_level | DMA_WRITE_ADDR, PORT_DMA_FN);
690 outb((u_int) buffer & (u_int) 0xff, PORT_DMA_EX);
691 outb(((u_int) buffer >> 8) & (u_int) 0xff, PORT_DMA_EX);
692 outb(((u_int) buffer >> 16) & (u_int) 0xff, PORT_DMA_EX);
694 outb(dma_arb_level | DMA_WRITE_TC, PORT_DMA_FN);
695 tc = (length * SECT_SIZE / 2) - 1;
696 outb(tc & 0xff, PORT_DMA_EX);
697 outb((tc >> 8) & 0xff, PORT_DMA_EX);
699 outb(dma_arb_level | DMA_WRITE_MODE, PORT_DMA_FN);
700 outb(dma_xmode, PORT_DMA_EX);
702 outb(dma_arb_level | DMA_UNMASK_CHAN, PORT_DMA_FN);
704 sti();
706 } /* prepare for dma */
710 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
711 struct pt_regs *regs)
713 u_int int_ret_code;
715 if (inb(ESDI_STATUS) & STATUS_INTR) {
716 int_ret_code = inb(ESDI_INTRPT);
717 if (current_int_handler) {
718 /* Disable adapter interrupts till processing is finished */
719 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
720 current_int_handler(int_ret_code);
721 } else
722 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
723 } else {
724 return;
728 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
731 switch (int_ret_code & 0xf) {
732 case INT_RESET:
733 /*BA */
734 printk("%s: initial reset completed.\n", DEVICE_NAME);
735 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
736 wake_up(&ps2esdi_int);
737 break;
738 case INT_ATTN_ERROR:
739 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
740 int_ret_code);
741 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
742 break;
743 default:
744 printk("%s: initial reset handler received interrupt: %02X\n",
745 DEVICE_NAME, int_ret_code);
746 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
747 break;
749 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
753 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
755 u_int status, drive_num;
756 unsigned long rba;
757 int i;
759 drive_num = int_ret_code >> 5;
760 switch (int_ret_code & 0xf) {
761 case INT_CMD_COMPLETE:
762 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
763 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
764 printk("%s: timeout reading status word\n", DEVICE_NAME);
765 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
766 break;
768 status = inw(ESDI_STT_INT);
769 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
770 #define REPLY_WORDS 5 /* we already read word 0 */
771 u_short reply[REPLY_WORDS];
773 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
774 /*BA */
775 printk("%s: Device Configuration Status for drive %u\n",
776 DEVICE_NAME, drive_num);
778 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
780 printk
781 ("Config bits: %s%s%s%s%s\n",
782 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
783 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
784 ? "Zero Defect, " : "Defects Present, ",
785 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
786 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
787 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
789 rba = reply[1] | ((unsigned long) reply[2] << 16);
790 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
792 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
793 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
795 if (!ps2esdi_info[drive_num].head) {
796 ps2esdi_info[drive_num].head = 64;
797 ps2esdi_info[drive_num].sect = 32;
798 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
799 ps2esdi_info[drive_num].wpcom = 0;
800 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
801 ps2esdi_info[drive_num].ctl = 8;
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 if (!intg_esdi)
810 ps2esdi_drives++;
813 #ifdef OBSOLETE
814 if (!ps2esdi_info[drive_num].head) {
815 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
816 ps2esdi_info[drive_num].sect = reply[4] >> 8;
817 ps2esdi_info[drive_num].cyl = reply[3];
818 ps2esdi_info[drive_num].wpcom = 0;
819 ps2esdi_info[drive_num].lzone = reply[3];
820 if (tp720esdi) { /* store the retrieved parameters */
821 ps2esdi_info[0].head = reply[4] & 0Xff;
822 ps2esdi_info[0].sect = reply[4] >> 8;
823 ps2esdi_info[0].cyl = reply[3];
824 ps2esdi_info[0].wpcom = 0;
825 ps2esdi_info[0].lzone = reply[3];
826 } else {
827 ps2esdi_drives++;
830 #endif
832 } else
833 printk("%s: failed while getting device config\n", DEVICE_NAME);
834 #undef REPLY_WORDS
835 } else
836 printk("%s: command %02X unknown by geometry handler\n",
837 DEVICE_NAME, status & 0x1f);
839 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
840 break;
842 case INT_ATTN_ERROR:
843 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
844 int_ret_code);
845 printk("%s: Device not available\n", DEVICE_NAME);
846 break;
847 case INT_CMD_ECC:
848 case INT_CMD_RETRY:
849 case INT_CMD_ECC_RETRY:
850 case INT_CMD_WARNING:
851 case INT_CMD_ABORT:
852 case INT_CMD_FAILED:
853 case INT_DMA_ERR:
854 case INT_CMD_BLK_ERR:
855 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
856 dump_cmd_complete_status(int_ret_code);
857 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
858 break;
859 default:
860 printk("%s: Unknown interrupt reason: %02X\n",
861 DEVICE_NAME, int_ret_code & 0xf);
862 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
863 break;
866 wake_up(&ps2esdi_int);
867 no_int_yet = FALSE;
868 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
872 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
874 u_int status;
875 int i;
877 switch (int_ret_code & 0x0f) {
878 case INT_TRANSFER_REQ:
879 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
880 (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16);
881 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
882 break;
884 case INT_ATTN_ERROR:
885 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
886 int_ret_code);
887 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
888 break;
890 case INT_CMD_COMPLETE:
891 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
892 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
893 printk("%s: timeout reading status word\n", DEVICE_NAME);
894 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
895 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
896 if ((++CURRENT->errors) < MAX_RETRIES)
897 do_ps2esdi_request(NULL);
898 else {
899 end_request(FAIL);
900 if (!QUEUE_EMPTY)
901 do_ps2esdi_request(NULL);
903 break;
905 status = inw(ESDI_STT_INT);
906 switch (status & 0x1F) {
907 case (CMD_READ & 0xff):
908 case (CMD_WRITE & 0xff):
909 LITE_OFF;
910 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
911 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
912 #if 0
913 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);
914 #endif
915 ps2esdi_continue_request();
916 break;
917 default:
918 printk("%s: interrupt for unknown command %02X\n",
919 DEVICE_NAME, status & 0x1f);
920 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
921 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
922 break;
924 break;
925 case INT_CMD_ECC:
926 case INT_CMD_RETRY:
927 case INT_CMD_ECC_RETRY:
928 LITE_OFF;
929 dump_cmd_complete_status(int_ret_code);
930 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
931 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
932 ps2esdi_continue_request();
933 break;
934 case INT_CMD_WARNING:
935 case INT_CMD_ABORT:
936 case INT_CMD_FAILED:
937 case INT_DMA_ERR:
938 LITE_OFF;
939 dump_cmd_complete_status(int_ret_code);
940 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
941 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
942 if ((++CURRENT->errors) < MAX_RETRIES)
943 do_ps2esdi_request(NULL);
944 else {
945 end_request(FAIL);
946 if (!QUEUE_EMPTY)
947 do_ps2esdi_request(NULL);
949 break;
951 case INT_CMD_BLK_ERR:
952 dump_cmd_complete_status(int_ret_code);
953 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
954 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
955 end_request(FAIL);
956 if (!QUEUE_EMPTY)
957 do_ps2esdi_request(NULL);
958 break;
960 case INT_CMD_FORMAT:
961 printk("%s: huh ? Who issued this format command ?\n"
962 ,DEVICE_NAME);
963 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
964 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
965 break;
967 case INT_RESET:
968 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
969 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
970 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
971 break;
973 default:
974 printk("%s: Unknown interrupt reason: %02X\n",
975 DEVICE_NAME, int_ret_code & 0xf);
976 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
977 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
978 break;
981 } /* handle interrupts */
984 static void ps2esdi_continue_request(void)
986 if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
987 CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
988 CURRENT->sector += CURRENT->current_nr_sectors;
989 do_ps2esdi_request(NULL);
990 } else {
991 end_request(SUCCES);
992 if (!QUEUE_EMPTY)
993 do_ps2esdi_request(NULL);
999 static int ps2esdi_read_status_words(int num_words,
1000 int max_words,
1001 u_short * buffer)
1003 int i;
1005 for (; max_words && num_words; max_words--, num_words--, buffer++) {
1006 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
1007 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
1008 printk("%s: timeout reading status word\n", DEVICE_NAME);
1009 return FAIL;
1011 *buffer = inw(ESDI_STT_INT);
1013 return SUCCES;
1019 static void dump_cmd_complete_status(u_int int_ret_code)
1021 #define WAIT_FOR_STATUS \
1022 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
1023 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
1024 printk("%s: timeout reading status word\n",DEVICE_NAME); \
1025 return; \
1028 int i, word_count;
1029 u_short stat_word;
1030 u_long rba;
1032 printk("%s: Device: %u, interrupt ID: %02X\n",
1033 DEVICE_NAME, int_ret_code >> 5,
1034 int_ret_code & 0xf);
1036 WAIT_FOR_STATUS;
1037 stat_word = inw(ESDI_STT_INT);
1038 word_count = (stat_word >> 8) - 1;
1039 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1040 stat_word & 0xff);
1042 if (word_count--) {
1043 WAIT_FOR_STATUS;
1044 stat_word = inw(ESDI_STT_INT);
1045 printk("%s: command status code: %02X, command error code: %02X\n",
1046 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1048 if (word_count--) {
1049 WAIT_FOR_STATUS;
1050 stat_word = inw(ESDI_STT_INT);
1051 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1052 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1053 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1054 (stat_word & 0x0400) ? "Write Fault, " : "",
1055 (stat_word & 0x0200) ? "Track 0, " : "",
1056 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1057 stat_word >> 8);
1059 if (word_count--) {
1060 WAIT_FOR_STATUS;
1061 stat_word = inw(ESDI_STT_INT);
1062 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1064 if (word_count -= 2) {
1065 WAIT_FOR_STATUS;
1066 rba = inw(ESDI_STT_INT);
1067 WAIT_FOR_STATUS;
1068 rba |= inw(ESDI_STT_INT) << 16;
1069 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1070 (u_short) ((rba & 0x1ff80000) >> 11),
1071 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1072 } else
1073 printk("\n");
1075 if (word_count--) {
1076 WAIT_FOR_STATUS;
1077 stat_word = inw(ESDI_STT_INT);
1078 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1080 printk("\n");
1082 #undef WAIT_FOR_STATUS
1087 static int ps2esdi_open(struct inode *inode, struct file *file)
1089 int dev = DEVICE_NR(inode->i_rdev);
1091 if (dev < ps2esdi_drives) {
1092 while (!ps2esdi_valid[dev])
1093 sleep_on(&ps2esdi_wait_open);
1095 access_count[dev]++;
1097 return (0);
1098 } else
1099 return (-ENODEV);
1104 static int ps2esdi_release(struct inode *inode, struct file *file)
1106 int dev = DEVICE_NR(inode->i_rdev);
1108 if (dev < ps2esdi_drives) {
1109 access_count[dev]--;
1111 return 0;
1116 static int ps2esdi_ioctl(struct inode *inode,
1117 struct file *file, u_int cmd, u_long arg)
1120 struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1121 int dev = DEVICE_NR(inode->i_rdev), err;
1123 if (inode && (dev < ps2esdi_drives))
1124 switch (cmd) {
1125 case HDIO_GETGEO:
1126 if (arg) {
1127 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1128 return (err);
1129 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1130 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1131 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1132 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1133 (long *) &geometry->start);
1135 return (0);
1137 break;
1139 case BLKGETSIZE:
1140 if (arg) {
1141 if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
1142 return (err);
1143 put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
1145 return (0);
1147 break;
1149 case BLKRRPART:
1150 if (!capable(CAP_SYS_ADMIN))
1151 return -EACCES;
1152 return (ps2esdi_reread_partitions(inode->i_rdev));
1154 case BLKROSET:
1155 case BLKROGET:
1156 case BLKRASET:
1157 case BLKRAGET:
1158 case BLKFLSBUF:
1159 case BLKPG:
1160 return blk_ioctl(inode->i_rdev, cmd, arg);
1162 return (-EINVAL);
1167 static int ps2esdi_reread_partitions(kdev_t dev)
1169 int target = DEVICE_NR(dev);
1170 int start = target << ps2esdi_gendisk.minor_shift;
1171 int partition;
1173 cli();
1174 ps2esdi_valid[target] = (access_count[target] != 1);
1175 sti();
1176 if (ps2esdi_valid[target])
1177 return (-EBUSY);
1179 for (partition = ps2esdi_gendisk.max_p - 1;
1180 partition >= 0; partition--) {
1181 int minor = (start | partition);
1182 kdev_t devp = MKDEV(MAJOR_NR, minor);
1183 struct super_block * sb = get_super(devp);
1185 sync_dev(devp);
1186 if (sb)
1187 invalidate_inodes(sb);
1188 invalidate_buffers(devp);
1189 ps2esdi_gendisk.part[start + partition].start_sect = 0;
1190 ps2esdi_gendisk.part[start + partition].nr_sects = 0;
1193 grok_partitions(&ps2esdi_gendisk, target, 1<<6,
1194 ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect);
1196 ps2esdi_valid[target] = 1;
1197 wake_up(&ps2esdi_wait_open);
1199 return (0);
1202 void ps2esdi_reset_timer(unsigned long unused)
1205 int status;
1207 status = inb(ESDI_INTRPT);
1208 if ((status & 0xf) == INT_RESET) {
1209 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1210 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1211 reset_status = 1;
1213 wake_up(&ps2esdi_int);
1216 #endif