Import 2.3.9pre5
[davej-history.git] / drivers / block / ps2esdi.c
blobe1ff03e8ffb71af6198b03e74b3869ec5bbf0ac7
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/blk.h>
45 #include <linux/blkpg.h>
46 #include <linux/mca.h>
47 #include <linux/init.h>
48 #include <linux/ioport.h>
50 #include <asm/system.h>
51 #include <asm/io.h>
52 #include <asm/segment.h>
53 #include <asm/dma.h>
54 #include <asm/uaccess.h>
56 #define PS2ESDI_IRQ 14
57 #define MAX_HD 1
58 #define MAX_RETRIES 5
59 #define MAX_16BIT 65536
60 #define ESDI_TIMEOUT 0xf000
61 #define ESDI_STAT_TIMEOUT 4
63 #define TYPE_0_CMD_BLK_LENGTH 2
64 #define TYPE_1_CMD_BLK_LENGTH 4
67 static void reset_ctrl(void);
69 int ps2esdi_init(void);
71 static void ps2esdi_geninit(struct gendisk *ignored);
73 static void do_ps2esdi_request(void);
75 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
77 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
78 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
80 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
82 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
84 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
85 struct pt_regs *regs);
86 static void (*current_int_handler) (u_int) = NULL;
87 static void ps2esdi_normal_interrupt_handler(u_int);
88 static void ps2esdi_initial_reset_int_handler(u_int);
89 static void ps2esdi_geometry_int_handler(u_int);
91 static void ps2esdi_continue_request(void);
93 static int ps2esdi_open(struct inode *inode, struct file *file);
95 static int ps2esdi_release(struct inode *inode, struct file *file);
97 static int ps2esdi_ioctl(struct inode *inode, struct file *file,
98 u_int cmd, u_long arg);
100 static int ps2esdi_reread_partitions(kdev_t dev);
102 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
104 static void dump_cmd_complete_status(u_int int_ret_code);
106 static void ps2esdi_get_device_cfg(void);
108 void ps2esdi_reset_timer(unsigned long unused);
110 u_int dma_arb_level; /* DMA arbitration level */
112 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
113 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
115 int no_int_yet;
116 static int access_count[MAX_HD] = {0,};
117 static char ps2esdi_valid[MAX_HD] = {0,};
118 static int ps2esdi_sizes[MAX_HD << 6] = {0,};
119 static int ps2esdi_blocksizes[MAX_HD << 6] = {0,};
120 static int ps2esdi_drives = 0;
121 static struct hd_struct ps2esdi[MAX_HD << 6];
122 static u_short io_base;
123 static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer};
124 static int reset_status;
125 static int ps2esdi_slot = -1;
126 int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
128 struct ps2esdi_i_struct {
129 unsigned int head, sect, cyl, wpcom, lzone, ctl;
132 #if 0
133 #if 0 /* try both - I don't know which one is better... UB */
134 struct ps2esdi_i_struct ps2esdi_info[] =
136 {4, 48, 1553, 0, 0, 0},
137 {0, 0, 0, 0, 0, 0}};
138 #else
139 struct ps2esdi_i_struct ps2esdi_info[] =
141 {64, 32, 161, 0, 0, 0},
142 {0, 0, 0, 0, 0, 0}};
143 #endif
144 #endif
145 struct ps2esdi_i_struct ps2esdi_info[] =
147 {0, 0, 0, 0, 0, 0},
148 {0, 0, 0, 0, 0, 0}};
150 static struct file_operations ps2esdi_fops =
152 NULL, /* lseek - default */
153 block_read, /* read - general block-dev read */
154 block_write, /* write - general block-dev write */
155 NULL, /* readdir - bad */
156 NULL, /* poll */
157 ps2esdi_ioctl, /* ioctl */
158 NULL, /* mmap */
159 ps2esdi_open, /* open */
160 NULL, /* flush */
161 ps2esdi_release, /* release */
162 block_fsync /* fsync */
165 static struct gendisk ps2esdi_gendisk =
167 MAJOR_NR, /* Major number */
168 "ed", /* Major name */
169 6, /* Bits to shift to get real from partition */
170 1 << 6, /* Number of partitions per real disk */
171 MAX_HD, /* maximum number of real disks */
172 ps2esdi_geninit, /* init function */
173 ps2esdi, /* hd struct */
174 ps2esdi_sizes, /* block sizes */
175 0, /* number */
176 (void *) ps2esdi_info, /* internal */
177 NULL /* next */
180 /* initialization routine called by ll_rw_blk.c */
181 __initfunc(int ps2esdi_init(void))
184 /* register the device - pass the name, major number and operations
185 vector . */
186 if (register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
187 printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR);
188 return -1;
190 /* set up some global information - indicating device specific info */
191 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
192 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
194 /* some minor housekeeping - setup the global gendisk structure */
195 ps2esdi_gendisk.next = gendisk_head;
196 gendisk_head = &ps2esdi_gendisk;
197 return 0;
199 } /* ps2esdi_init */
201 #ifdef MODULE
203 int cyl[2] = {-1,-1};
204 int head[2] = {-1, -1};
205 int sect[2] = {-1, -1};
207 MODULE_PARM(tp720esdi, "i");
208 MODULE_PARM(cyl, "i");
209 MODULE_PARM(head, "i");
210 MODULE_PARM(track, "i");
212 int init_module(void) {
213 int drive;
215 for(drive = 0; drive <= 1; drive++) {
216 struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
218 if (cyl[drive] != -1) {
219 info->cyl = info->lzone = cyl[drive];
220 info->wpcom = 0;
222 if (head[drive] != -1) {
223 info->head = head[drive];
224 info->ctl = (head[drive] > 8 ? 8 : 0);
226 if (sect[drive] != -1) info->sect = sect[drive];
228 return ps2esdi_init();
231 void
232 cleanup_module(void)
234 if(ps2esdi_slot)
236 mca_mark_as_unused(ps2esdi_slot);
237 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
239 release_region(io_base, 4);
240 free_dma(dma_arb_level);
241 free_irq(PS2ESDI_IRQ, NULL)
242 unregister_blkdev(MAJOR_NR, "ed");
244 #endif /* MODULE */
246 /* handles boot time command line parameters */
247 __initfunc(void tp720_setup(char *str, int *ints))
249 /* no params, just sets the tp720esdi flag if it exists */
251 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
252 tp720esdi = 1;
255 __initfunc(void ed_setup(char *str, int *ints))
257 int hdind = 0;
259 /* handles 3 parameters only - corresponding to
260 1. Number of cylinders
261 2. Number of heads
262 3. Sectors/track
265 if (ints[0] != 3)
266 return;
268 /* print out the information - seen at boot time */
269 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
270 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
272 /* set the index into device specific information table */
273 if (ps2esdi_info[0].head != 0)
274 hdind = 1;
276 /* set up all the device information */
277 ps2esdi_info[hdind].head = ints[2];
278 ps2esdi_info[hdind].sect = ints[3];
279 ps2esdi_info[hdind].cyl = ints[1];
280 ps2esdi_info[hdind].wpcom = 0;
281 ps2esdi_info[hdind].lzone = ints[1];
282 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
283 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
284 ps2esdi_drives = hdind + 1; /* increment index for the next time */
285 #endif
286 } /* ed_setup */
288 static int ps2esdi_getinfo(char *buf, int slot, void *d)
290 int len = 0;
292 len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
293 dma_arb_level);
294 len += sprintf(buf + len, "IO Port: %x\n", io_base);
295 len += sprintf(buf + len, "IRQ: 14\n");
296 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
298 return len;
301 /* ps2 esdi specific initialization - called thru the gendisk chain */
302 __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
305 The first part contains the initialization code
306 for the ESDI disk subsystem. All we really do
307 is search for the POS registers of the controller
308 to do some simple setup operations. First, we
309 must ensure that the controller is installed,
310 enabled, and configured as PRIMARY. Then we must
311 determine the DMA arbitration level being used by
312 the controller so we can handle data transfer
313 operations properly. If all of this works, then
314 we will set the INIT_FLAG to a non-zero value.
317 int slot = 0, i, reset_start, reset_end;
318 u_char status;
319 unsigned short adapterID;
321 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
322 adapterID = INTG_ESDI_ID;
323 printk("%s: integrated ESDI adapter found in slot %d\n",
324 DEVICE_NAME, slot+1);
325 #ifndef MODULE
326 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
327 #endif
328 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
329 adapterID = NRML_ESDI_ID;
330 printk("%s: normal ESDI adapter found in slot %d\n",
331 DEVICE_NAME, slot+1);
332 mca_set_adapter_name(slot, "PS/2 ESDI");
333 } else {
334 return;
337 ps2esdi_slot = slot;
338 mca_mark_as_used(slot);
339 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
341 /* Found the slot - read the POS register 2 to get the necessary
342 configuration and status information. POS register 2 has the
343 following information :
344 Bit Function
345 7 reserved = 0
346 6 arbitration method
347 0 - fairness enabled
348 1 - fairness disabled, linear priority assignment
349 5-2 arbitration level
350 1 alternate address
351 1 alternate address
352 0 - use addresses 0x3510 - 0x3517
353 0 adapter enable
356 status = mca_read_stored_pos(slot, 2);
357 /* is it enabled ? */
358 if (!(status & STATUS_ENABLED)) {
359 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
360 return;
362 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
363 share with the SCSI driver */
364 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
365 SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
366 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
367 SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
369 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
370 return;
372 if (status & STATUS_ALTERNATE)
373 io_base = ALT_IO_BASE;
374 else
375 io_base = PRIMARY_IO_BASE;
377 /* get the dma arbitration level */
378 dma_arb_level = (status >> 2) & 0xf;
380 /* BA */
381 printk("%s: DMA arbitration level : %d\n",
382 DEVICE_NAME, dma_arb_level);
384 LITE_ON;
385 current_int_handler = ps2esdi_initial_reset_int_handler;
386 reset_ctrl();
387 reset_status = 0;
388 reset_start = jiffies;
389 while (!reset_status) {
390 esdi_timer.expires = 100;
391 esdi_timer.data = 0;
392 esdi_timer.next = esdi_timer.prev = NULL;
393 add_timer(&esdi_timer);
394 sleep_on(&ps2esdi_int);
396 reset_end = jiffies;
397 LITE_OFF;
398 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
399 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
400 (reset_end - reset_start) % HZ);
403 /* Integrated ESDI Disk and Controller has only one drive! */
404 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
405 ps2esdi_drives = 1; /* then we have only one physical disk! */
409 /* finally this part sets up some global data structures etc. */
411 ps2esdi_get_device_cfg();
413 /* some annoyance in the above routine returns TWO drives?
414 Is something else happining in the background?
415 Regaurdless we fix the # of drives again. AJK */
416 /* Integrated ESDI Disk and Controller has only one drive! */
417 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
418 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */
420 current_int_handler = ps2esdi_normal_interrupt_handler;
422 ps2esdi_gendisk.nr_real = ps2esdi_drives;
424 for (i = 0; i < ps2esdi_drives; i++) {
425 ps2esdi[i << 6].nr_sects =
426 ps2esdi_info[i].head *
427 ps2esdi_info[i].sect *
428 ps2esdi_info[i].cyl;
429 ps2esdi_valid[i] = 1;
431 for (i = 0; i < (MAX_HD << 6); i++)
432 ps2esdi_blocksizes[i] = 1024;
434 request_dma(dma_arb_level, "ed");
435 request_region(io_base, 4, "ed");
436 blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
437 } /* ps2esdi_geninit */
440 __initfunc(static void ps2esdi_get_device_cfg(void))
442 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
444 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
445 current_int_handler = ps2esdi_geometry_int_handler;
446 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
447 cmd_blk[1] = 0;
448 no_int_yet = TRUE;
449 ps2esdi_out_cmd_blk(cmd_blk);
450 if (no_int_yet)
451 sleep_on(&ps2esdi_int);
453 if (ps2esdi_drives > 1) {
454 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
455 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
456 cmd_blk[1] = 0;
457 no_int_yet = TRUE;
458 ps2esdi_out_cmd_blk(cmd_blk);
459 if (no_int_yet)
460 sleep_on(&ps2esdi_int);
461 } /* if second physical drive is present */
462 return;
465 /* strategy routine that handles most of the IO requests */
466 static void do_ps2esdi_request(void)
468 u_int block, count;
469 /* since, this routine is called with interrupts cleared - they
470 must be before it finishes */
471 sti();
473 #if 0
474 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
475 DEVICE_NAME,
476 CURRENT_DEV, MINOR(CURRENT->rq_dev),
477 CURRENT->cmd, CURRENT->sector,
478 CURRENT->nr_sectors, CURRENT->buffer);
479 #endif
481 /* standard macro that ensures that requests are really on the
482 list + sanity checks. */
483 INIT_REQUEST;
485 if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) {
486 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
487 end_request(FAIL);
488 if (CURRENT)
489 do_ps2esdi_request();
490 return;
491 } /* check for above 16Mb dmas */
492 if ((CURRENT_DEV < ps2esdi_drives) &&
493 (CURRENT->sector + CURRENT->nr_sectors <=
494 ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
495 #if 0
496 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
497 DEVICE_NAME,
498 CURRENT_DEV, MINOR(CURRENT->dev),
499 CURRENT->cmd, CURRENT->sector,
500 CURRENT->nr_sectors);
501 #endif
504 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
506 #if 0
507 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
508 #endif
509 count = CURRENT->nr_sectors;
510 switch (CURRENT->cmd) {
511 case READ:
512 ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
513 return;
514 break;
515 case WRITE:
516 ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
517 return;
518 break;
519 default:
520 printk("%s: Unknown command\n", DEVICE_NAME);
521 end_request(FAIL);
522 if (CURRENT)
523 do_ps2esdi_request();
524 break;
525 } /* handle different commands */
527 /* is request is valid */
528 else {
529 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
530 CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
531 end_request(FAIL);
532 if (CURRENT)
533 do_ps2esdi_request();
536 } /* main strategy routine */
538 /* resets the ESDI adapter */
539 static void reset_ctrl(void)
542 u_long expire;
543 u_short status;
545 /* enable interrupts on the controller */
546 status = inb(ESDI_INTRPT);
547 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
548 any interrupt pending... */
549 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
551 /* read the ESDI status port - if the controller is not busy,
552 simply do a soft reset (fast) - otherwise we'll have to do a
553 hard (slow) reset. */
554 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
555 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
556 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
558 /* soft reset */
559 else {
560 /*BA */
561 printk("%s: hard reset...\n", DEVICE_NAME);
562 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
563 expire = jiffies + 200;
564 while (time_before(jiffies, expire));
565 outb_p(1, ESDI_CONTROL);
566 } /* hard reset */
569 } /* reset the controller */
571 /* called by the strategy routine to handle read and write requests */
572 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
575 u_short track, head, cylinder, sector;
576 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
578 /* do some relevant arithmatic */
579 CURRENT->current_nr_sectors =
580 (count < (2 * MAX_16BIT / SECT_SIZE)) ? count : (2 * MAX_16BIT / SECT_SIZE);
581 track = block / ps2esdi_info[drive].sect;
582 head = track % ps2esdi_info[drive].head;
583 cylinder = track / ps2esdi_info[drive].head;
584 sector = block % ps2esdi_info[drive].sect;
586 #if 0
587 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
588 #endif
589 /* call the routine that actually fills out a command block */
590 ps2esdi_fill_cmd_block
591 (cmd_blk,
592 (cmd == READ) ? CMD_READ : CMD_WRITE,
593 cylinder, head, sector,
594 CURRENT->current_nr_sectors, drive);
596 /* send the command block to the controller */
597 if (ps2esdi_out_cmd_blk(cmd_blk)) {
598 printk("%s: Controller failed\n", DEVICE_NAME);
599 if ((++CURRENT->errors) < MAX_RETRIES)
600 return do_ps2esdi_request();
601 else {
602 end_request(FAIL);
603 if (CURRENT)
604 do_ps2esdi_request();
607 /* check for failure to put out the command block */
608 else {
609 #if 0
610 printk("%s: waiting for xfer\n", DEVICE_NAME);
611 #endif
612 /* turn disk lights on */
613 LITE_ON;
616 } /* ps2esdi_readwrite */
618 /* fill out the command block */
619 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
620 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
623 cmd_blk[0] = (drive << 5) | cmd;
624 cmd_blk[1] = length;
625 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
626 cmd_blk[3] = (cyl & 0x3E0) >> 5;
628 } /* fill out the command block */
630 /* write a command block to the controller */
631 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
634 int i, j;
635 u_char status;
637 /* enable interrupts */
638 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
640 /* do not write to the controller, if it is busy */
641 for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
642 STATUS_BUSY););
644 #if 0
645 printk("%s: i(1)=%d\n", DEVICE_NAME, i);
646 #endif
648 /* if device is still busy - then just time out */
649 if (inb(ESDI_STATUS) & STATUS_BUSY) {
650 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
651 return ERROR;
652 } /* timeout ??? */
653 /* Set up the attention register in the controller */
654 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
656 #if 0
657 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
658 #endif
660 /* one by one send each word out */
661 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
662 status = inb(ESDI_STATUS);
663 for (j = jiffies + ESDI_STAT_TIMEOUT;
664 time_after(j, jiffies) && (status & STATUS_BUSY) &&
665 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
666 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
667 #if 0
668 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
669 #endif
670 outw(*cmd_blk++, ESDI_CMD_INT);
671 } else {
672 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
673 DEVICE_NAME, status);
674 return ERROR;
676 } /* send all words out */
677 return OK;
678 } /* send out the commands */
681 /* prepare for dma - do all the necessary setup */
682 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
684 u_int tc;
686 buffer=(char *)virt_to_bus(buffer);
688 #if 0
689 printk("ps2esdi: b_wait: %p\n", CURRENT->bh->b_wait);
690 #endif
691 cli();
693 outb(dma_arb_level | DMA_MASK_CHAN, PORT_DMA_FN);
695 outb(dma_arb_level | DMA_WRITE_ADDR, PORT_DMA_FN);
696 outb((u_int) buffer & (u_int) 0xff, PORT_DMA_EX);
697 outb(((u_int) buffer >> 8) & (u_int) 0xff, PORT_DMA_EX);
698 outb(((u_int) buffer >> 16) & (u_int) 0xff, PORT_DMA_EX);
700 outb(dma_arb_level | DMA_WRITE_TC, PORT_DMA_FN);
701 tc = (length * SECT_SIZE / 2) - 1;
702 outb(tc & 0xff, PORT_DMA_EX);
703 outb((tc >> 8) & 0xff, PORT_DMA_EX);
705 outb(dma_arb_level | DMA_WRITE_MODE, PORT_DMA_FN);
706 outb(dma_xmode, PORT_DMA_EX);
708 outb(dma_arb_level | DMA_UNMASK_CHAN, PORT_DMA_FN);
710 sti();
712 } /* prepare for dma */
716 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
717 struct pt_regs *regs)
719 u_int int_ret_code;
721 if (inb(ESDI_STATUS) & STATUS_INTR) {
722 int_ret_code = inb(ESDI_INTRPT);
723 if (current_int_handler) {
724 /* Disable adapter interrupts till processing is finished */
725 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
726 current_int_handler(int_ret_code);
727 } else
728 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
729 } else {
730 return;
734 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
737 switch (int_ret_code & 0xf) {
738 case INT_RESET:
739 /*BA */
740 printk("%s: initial reset completed.\n", DEVICE_NAME);
741 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
742 wake_up(&ps2esdi_int);
743 break;
744 case INT_ATTN_ERROR:
745 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
746 int_ret_code);
747 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
748 break;
749 default:
750 printk("%s: initial reset handler received interrupt: %02X\n",
751 DEVICE_NAME, int_ret_code);
752 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
753 break;
755 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
759 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
761 u_int status, drive_num;
762 unsigned long rba;
763 int i;
765 drive_num = int_ret_code >> 5;
766 switch (int_ret_code & 0xf) {
767 case INT_CMD_COMPLETE:
768 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
769 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
770 printk("%s: timeout reading status word\n", DEVICE_NAME);
771 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
772 break;
774 status = inw(ESDI_STT_INT);
775 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
776 #define REPLY_WORDS 5 /* we already read word 0 */
777 u_short reply[REPLY_WORDS];
779 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
780 /*BA */
781 printk("%s: Device Configuration Status for drive %u\n",
782 DEVICE_NAME, drive_num);
784 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
786 printk
787 ("Config bits: %s%s%s%s%s\n",
788 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
789 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
790 ? "Zero Defect, " : "Defects Present, ",
791 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
792 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
793 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
795 rba = reply[1] | ((unsigned long) reply[2] << 16);
796 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
798 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
799 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
801 if (!ps2esdi_info[drive_num].head) {
802 ps2esdi_info[drive_num].head = 64;
803 ps2esdi_info[drive_num].sect = 32;
804 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
805 ps2esdi_info[drive_num].wpcom = 0;
806 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
807 ps2esdi_info[drive_num].ctl = 8;
808 if (tp720esdi) { /* store the retrieved parameters */
809 ps2esdi_info[0].head = reply[4] & 0Xff;
810 ps2esdi_info[0].sect = reply[4] >> 8;
811 ps2esdi_info[0].cyl = reply[3];
812 ps2esdi_info[0].wpcom = 0;
813 ps2esdi_info[0].lzone = reply[3];
814 } else {
815 ps2esdi_drives++;
818 #ifdef OBSOLETE
819 if (!ps2esdi_info[drive_num].head) {
820 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
821 ps2esdi_info[drive_num].sect = reply[4] >> 8;
822 ps2esdi_info[drive_num].cyl = reply[3];
823 ps2esdi_info[drive_num].wpcom = 0;
824 ps2esdi_info[drive_num].lzone = reply[3];
825 if (tp720esdi) { /* store the retrieved parameters */
826 ps2esdi_info[0].head = reply[4] & 0Xff;
827 ps2esdi_info[0].sect = reply[4] >> 8;
828 ps2esdi_info[0].cyl = reply[3];
829 ps2esdi_info[0].wpcom = 0;
830 ps2esdi_info[0].lzone = reply[3];
831 } else {
832 ps2esdi_drives++;
835 #endif
837 } else
838 printk("%s: failed while getting device config\n", DEVICE_NAME);
839 #undef REPLY_WORDS
840 } else
841 printk("%s: command %02X unknown by geometry handler\n",
842 DEVICE_NAME, status & 0x1f);
844 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
845 break;
847 case INT_ATTN_ERROR:
848 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
849 int_ret_code);
850 printk("%s: Device not available\n", DEVICE_NAME);
851 break;
852 case INT_CMD_ECC:
853 case INT_CMD_RETRY:
854 case INT_CMD_ECC_RETRY:
855 case INT_CMD_WARNING:
856 case INT_CMD_ABORT:
857 case INT_CMD_FAILED:
858 case INT_DMA_ERR:
859 case INT_CMD_BLK_ERR:
860 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
861 dump_cmd_complete_status(int_ret_code);
862 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
863 break;
864 default:
865 printk("%s: Unknown interrupt reason: %02X\n",
866 DEVICE_NAME, int_ret_code & 0xf);
867 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
868 break;
871 wake_up(&ps2esdi_int);
872 no_int_yet = FALSE;
873 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
877 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
879 u_int status;
880 int i;
882 switch (int_ret_code & 0x0f) {
883 case INT_TRANSFER_REQ:
884 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
885 (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16);
886 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
887 break;
889 case INT_ATTN_ERROR:
890 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
891 int_ret_code);
892 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
893 break;
895 case INT_CMD_COMPLETE:
896 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
897 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
898 printk("%s: timeout reading status word\n", DEVICE_NAME);
899 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
900 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
901 if ((++CURRENT->errors) < MAX_RETRIES)
902 do_ps2esdi_request();
903 else {
904 end_request(FAIL);
905 if (CURRENT)
906 do_ps2esdi_request();
908 break;
910 status = inw(ESDI_STT_INT);
911 switch (status & 0x1F) {
912 case (CMD_READ & 0xff):
913 case (CMD_WRITE & 0xff):
914 LITE_OFF;
915 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
916 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
917 #if 0
918 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);
919 #endif
920 ps2esdi_continue_request();
921 break;
922 default:
923 printk("%s: interrupt for unknown command %02X\n",
924 DEVICE_NAME, status & 0x1f);
925 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
926 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
927 break;
929 break;
930 case INT_CMD_ECC:
931 case INT_CMD_RETRY:
932 case INT_CMD_ECC_RETRY:
933 LITE_OFF;
934 dump_cmd_complete_status(int_ret_code);
935 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
936 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
937 ps2esdi_continue_request();
938 break;
939 case INT_CMD_WARNING:
940 case INT_CMD_ABORT:
941 case INT_CMD_FAILED:
942 case INT_DMA_ERR:
943 LITE_OFF;
944 dump_cmd_complete_status(int_ret_code);
945 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
946 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
947 if ((++CURRENT->errors) < MAX_RETRIES)
948 do_ps2esdi_request();
949 else {
950 end_request(FAIL);
951 if (CURRENT)
952 do_ps2esdi_request();
954 break;
956 case INT_CMD_BLK_ERR:
957 dump_cmd_complete_status(int_ret_code);
958 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
959 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
960 end_request(FAIL);
961 if (CURRENT)
962 do_ps2esdi_request();
963 break;
965 case INT_CMD_FORMAT:
966 printk("%s: huh ? Who issued this format command ?\n"
967 ,DEVICE_NAME);
968 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
969 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
970 break;
972 case INT_RESET:
973 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
974 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
975 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
976 break;
978 default:
979 printk("%s: Unknown interrupt reason: %02X\n",
980 DEVICE_NAME, int_ret_code & 0xf);
981 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
982 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
983 break;
986 } /* handle interrupts */
989 static void ps2esdi_continue_request(void)
991 if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
992 CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
993 CURRENT->sector += CURRENT->current_nr_sectors;
994 do_ps2esdi_request();
995 } else {
996 end_request(SUCCES);
997 if (CURRENT)
998 do_ps2esdi_request();
1004 static int ps2esdi_read_status_words(int num_words,
1005 int max_words,
1006 u_short * buffer)
1008 int i;
1010 for (; max_words && num_words; max_words--, num_words--, buffer++) {
1011 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
1012 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
1013 printk("%s: timeout reading status word\n", DEVICE_NAME);
1014 return FAIL;
1016 *buffer = inw(ESDI_STT_INT);
1018 return SUCCES;
1024 static void dump_cmd_complete_status(u_int int_ret_code)
1026 #define WAIT_FOR_STATUS \
1027 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
1028 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
1029 printk("%s: timeout reading status word\n",DEVICE_NAME); \
1030 return; \
1033 int i, word_count;
1034 u_short stat_word;
1035 u_long rba;
1037 printk("%s: Device: %u, interrupt ID: %02X\n",
1038 DEVICE_NAME, int_ret_code >> 5,
1039 int_ret_code & 0xf);
1041 WAIT_FOR_STATUS;
1042 stat_word = inw(ESDI_STT_INT);
1043 word_count = (stat_word >> 8) - 1;
1044 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1045 stat_word & 0xff);
1047 if (word_count--) {
1048 WAIT_FOR_STATUS;
1049 stat_word = inw(ESDI_STT_INT);
1050 printk("%s: command status code: %02X, command error code: %02X\n",
1051 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1053 if (word_count--) {
1054 WAIT_FOR_STATUS;
1055 stat_word = inw(ESDI_STT_INT);
1056 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1057 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1058 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1059 (stat_word & 0x0400) ? "Write Fault, " : "",
1060 (stat_word & 0x0200) ? "Track 0, " : "",
1061 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1062 stat_word >> 8);
1064 if (word_count--) {
1065 WAIT_FOR_STATUS;
1066 stat_word = inw(ESDI_STT_INT);
1067 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1069 if (word_count -= 2) {
1070 WAIT_FOR_STATUS;
1071 rba = inw(ESDI_STT_INT);
1072 WAIT_FOR_STATUS;
1073 rba |= inw(ESDI_STT_INT) << 16;
1074 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1075 (u_short) ((rba & 0x1ff80000) >> 11),
1076 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1077 } else
1078 printk("\n");
1080 if (word_count--) {
1081 WAIT_FOR_STATUS;
1082 stat_word = inw(ESDI_STT_INT);
1083 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1085 printk("\n");
1087 #undef WAIT_FOR_STATUS
1092 static int ps2esdi_open(struct inode *inode, struct file *file)
1094 int dev = DEVICE_NR(inode->i_rdev);
1096 if (dev < ps2esdi_drives) {
1097 while (!ps2esdi_valid[dev])
1098 sleep_on(&ps2esdi_wait_open);
1100 access_count[dev]++;
1102 return (0);
1103 } else
1104 return (-ENODEV);
1109 static int ps2esdi_release(struct inode *inode, struct file *file)
1111 int dev = DEVICE_NR(inode->i_rdev);
1113 if (dev < ps2esdi_drives) {
1114 sync_dev(inode->i_rdev);
1115 access_count[dev]--;
1117 return 0;
1122 static int ps2esdi_ioctl(struct inode *inode,
1123 struct file *file, u_int cmd, u_long arg)
1126 struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1127 int dev = DEVICE_NR(inode->i_rdev), err;
1129 if (inode && (dev < ps2esdi_drives))
1130 switch (cmd) {
1131 case HDIO_GETGEO:
1132 if (arg) {
1133 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1134 return (err);
1135 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1136 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1137 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1138 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1139 (long *) &geometry->start);
1141 return (0);
1143 break;
1145 case BLKGETSIZE:
1146 if (arg) {
1147 if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
1148 return (err);
1149 put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
1151 return (0);
1153 break;
1155 case BLKRRPART:
1156 if (!capable(CAP_SYS_ADMIN))
1157 return -EACCES;
1158 return (ps2esdi_reread_partitions(inode->i_rdev));
1160 case BLKROSET:
1161 case BLKROGET:
1162 case BLKRASET:
1163 case BLKRAGET:
1164 case BLKFLSBUF:
1165 case BLKPG:
1166 return blk_ioctl(inode->i_rdev, cmd, arg);
1168 return (-EINVAL);
1173 static int ps2esdi_reread_partitions(kdev_t dev)
1175 int target = DEVICE_NR(dev);
1176 int start = target << ps2esdi_gendisk.minor_shift;
1177 int partition;
1179 cli();
1180 ps2esdi_valid[target] = (access_count[target] != 1);
1181 sti();
1182 if (ps2esdi_valid[target])
1183 return (-EBUSY);
1185 for (partition = ps2esdi_gendisk.max_p - 1;
1186 partition >= 0; partition--) {
1187 int minor = (start | partition);
1188 kdev_t devp = MKDEV(MAJOR_NR, minor);
1189 struct super_block * sb = get_super(devp);
1191 sync_dev(devp);
1192 if (sb)
1193 invalidate_inodes(sb);
1194 invalidate_buffers(devp);
1195 ps2esdi_gendisk.part[start + partition].start_sect = 0;
1196 ps2esdi_gendisk.part[start + partition].nr_sects = 0;
1199 ps2esdi_gendisk.part[start].nr_sects = ps2esdi_info[target].head *
1200 ps2esdi_info[target].cyl * ps2esdi_info[target].sect;
1201 resetup_one_dev(&ps2esdi_gendisk, target);
1203 ps2esdi_valid[target] = 1;
1204 wake_up(&ps2esdi_wait_open);
1206 return (0);
1209 void ps2esdi_reset_timer(unsigned long unused)
1212 int status;
1214 status = inb(ESDI_INTRPT);
1215 if ((status & 0xf) == INT_RESET) {
1216 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1217 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1218 reset_status = 1;
1220 wake_up(&ps2esdi_int);
1223 #endif