Import 2.3.1pre2
[davej-history.git] / drivers / block / ps2esdi.c
blob015c9468bb820580b7225dac036056b5d7528800
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/mca.h>
46 #include <linux/init.h>
47 #include <linux/ioport.h>
49 #include <asm/system.h>
50 #include <asm/io.h>
51 #include <asm/segment.h>
52 #include <asm/dma.h>
53 #include <asm/uaccess.h>
55 #define PS2ESDI_IRQ 14
56 #define MAX_HD 1
57 #define MAX_RETRIES 5
58 #define MAX_16BIT 65536
59 #define ESDI_TIMEOUT 0xf000
60 #define ESDI_STAT_TIMEOUT 4
62 #define TYPE_0_CMD_BLK_LENGTH 2
63 #define TYPE_1_CMD_BLK_LENGTH 4
66 static void reset_ctrl(void);
68 int ps2esdi_init(void);
70 static void ps2esdi_geninit(struct gendisk *ignored);
72 static void do_ps2esdi_request(void);
74 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
76 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
77 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
79 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
81 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
83 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
84 struct pt_regs *regs);
85 static void (*current_int_handler) (u_int) = NULL;
86 static void ps2esdi_normal_interrupt_handler(u_int);
87 static void ps2esdi_initial_reset_int_handler(u_int);
88 static void ps2esdi_geometry_int_handler(u_int);
90 static void ps2esdi_continue_request(void);
92 static int ps2esdi_open(struct inode *inode, struct file *file);
94 static int ps2esdi_release(struct inode *inode, struct file *file);
96 static int ps2esdi_ioctl(struct inode *inode, struct file *file,
97 u_int cmd, u_long arg);
99 static int ps2esdi_reread_partitions(kdev_t dev);
101 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
103 static void dump_cmd_complete_status(u_int int_ret_code);
105 static void ps2esdi_get_device_cfg(void);
107 void ps2esdi_reset_timer(unsigned long unused);
109 u_int dma_arb_level; /* DMA arbitration level */
111 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
112 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
114 int no_int_yet;
115 static int access_count[MAX_HD] = {0,};
116 static char ps2esdi_valid[MAX_HD] = {0,};
117 static int ps2esdi_sizes[MAX_HD << 6] = {0,};
118 static int ps2esdi_blocksizes[MAX_HD << 6] = {0,};
119 static int ps2esdi_drives = 0;
120 static struct hd_struct ps2esdi[MAX_HD << 6];
121 static u_short io_base;
122 static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer};
123 static int reset_status;
124 static int ps2esdi_slot = -1;
125 int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
127 struct ps2esdi_i_struct {
128 unsigned int head, sect, cyl, wpcom, lzone, ctl;
131 #if 0
132 #if 0 /* try both - I don't know which one is better... UB */
133 struct ps2esdi_i_struct ps2esdi_info[] =
135 {4, 48, 1553, 0, 0, 0},
136 {0, 0, 0, 0, 0, 0}};
137 #else
138 struct ps2esdi_i_struct ps2esdi_info[] =
140 {64, 32, 161, 0, 0, 0},
141 {0, 0, 0, 0, 0, 0}};
142 #endif
143 #endif
144 struct ps2esdi_i_struct ps2esdi_info[] =
146 {0, 0, 0, 0, 0, 0},
147 {0, 0, 0, 0, 0, 0}};
149 static struct file_operations ps2esdi_fops =
151 NULL, /* lseek - default */
152 block_read, /* read - general block-dev read */
153 block_write, /* write - general block-dev write */
154 NULL, /* readdir - bad */
155 NULL, /* poll */
156 ps2esdi_ioctl, /* ioctl */
157 NULL, /* mmap */
158 ps2esdi_open, /* open */
159 NULL, /* flush */
160 ps2esdi_release, /* release */
161 block_fsync /* fsync */
164 static struct gendisk ps2esdi_gendisk =
166 MAJOR_NR, /* Major number */
167 "ed", /* Major name */
168 6, /* Bits to shift to get real from partition */
169 1 << 6, /* Number of partitions per real disk */
170 MAX_HD, /* maximum number of real disks */
171 ps2esdi_geninit, /* init function */
172 ps2esdi, /* hd struct */
173 ps2esdi_sizes, /* block sizes */
174 0, /* number */
175 (void *) ps2esdi_info, /* internal */
176 NULL /* next */
179 /* initialization routine called by ll_rw_blk.c */
180 __initfunc(int ps2esdi_init(void))
183 /* register the device - pass the name, major number and operations
184 vector . */
185 if (register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
186 printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR);
187 return -1;
189 /* set up some global information - indicating device specific info */
190 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
191 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
193 /* some minor housekeeping - setup the global gendisk structure */
194 ps2esdi_gendisk.next = gendisk_head;
195 gendisk_head = &ps2esdi_gendisk;
196 return 0;
198 } /* ps2esdi_init */
200 #ifdef MODULE
202 int cyl[2] = {-1,-1};
203 int head[2] = {-1, -1};
204 int sect[2] = {-1, -1};
206 MODULE_PARM(tp720esdi, "i");
207 MODULE_PARM(cyl, "i");
208 MODULE_PARM(head, "i");
209 MODULE_PARM(track, "i");
211 int init_module(void) {
212 int drive;
214 for(drive = 0; drive <= 1; drive++) {
215 struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
217 if (cyl[drive] != -1) {
218 info->cyl = info->lzone = cyl[drive];
219 info->wpcom = 0;
221 if (head[drive] != -1) {
222 info->head = head[drive];
223 info->ctl = (head[drive] > 8 ? 8 : 0);
225 if (sect[drive] != -1) info->sect = sect[drive];
227 return ps2esdi_init();
230 void
231 cleanup_module(void)
233 if(ps2esdi_slot)
235 mca_mark_as_unused(ps2esdi_slot);
236 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
238 release_region(io_base, 4);
239 free_dma(dma_arb_level);
240 free_irq(PS2ESDI_IRQ, NULL)
241 unregister_blkdev(MAJOR_NR, "ed");
243 #endif /* MODULE */
245 /* handles boot time command line parameters */
246 __initfunc(void tp720_setup(char *str, int *ints))
248 /* no params, just sets the tp720esdi flag if it exists */
250 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
251 tp720esdi = 1;
254 __initfunc(void ed_setup(char *str, int *ints))
256 int hdind = 0;
258 /* handles 3 parameters only - corresponding to
259 1. Number of cylinders
260 2. Number of heads
261 3. Sectors/track
264 if (ints[0] != 3)
265 return;
267 /* print out the information - seen at boot time */
268 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
269 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
271 /* set the index into device specific information table */
272 if (ps2esdi_info[0].head != 0)
273 hdind = 1;
275 /* set up all the device information */
276 ps2esdi_info[hdind].head = ints[2];
277 ps2esdi_info[hdind].sect = ints[3];
278 ps2esdi_info[hdind].cyl = ints[1];
279 ps2esdi_info[hdind].wpcom = 0;
280 ps2esdi_info[hdind].lzone = ints[1];
281 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
282 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
283 ps2esdi_drives = hdind + 1; /* increment index for the next time */
284 #endif
285 } /* ed_setup */
287 static int ps2esdi_getinfo(char *buf, int slot, void *d)
289 int len = 0;
291 len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
292 dma_arb_level);
293 len += sprintf(buf + len, "IO Port: %x\n", io_base);
294 len += sprintf(buf + len, "IRQ: 14\n");
295 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
297 return len;
300 /* ps2 esdi specific initialization - called thru the gendisk chain */
301 __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
304 The first part contains the initialization code
305 for the ESDI disk subsystem. All we really do
306 is search for the POS registers of the controller
307 to do some simple setup operations. First, we
308 must ensure that the controller is installed,
309 enabled, and configured as PRIMARY. Then we must
310 determine the DMA arbitration level being used by
311 the controller so we can handle data transfer
312 operations properly. If all of this works, then
313 we will set the INIT_FLAG to a non-zero value.
316 int slot = 0, i, reset_start, reset_end;
317 u_char status;
318 unsigned short adapterID;
320 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
321 adapterID = INTG_ESDI_ID;
322 printk("%s: integrated ESDI adapter found in slot %d\n",
323 DEVICE_NAME, slot+1);
324 #ifndef MODULE
325 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
326 #endif
327 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
328 adapterID = NRML_ESDI_ID;
329 printk("%s: normal ESDI adapter found in slot %d\n",
330 DEVICE_NAME, slot+1);
331 mca_set_adapter_name(slot, "PS/2 ESDI");
332 } else {
333 return;
336 ps2esdi_slot = slot;
337 mca_mark_as_used(slot);
338 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
340 /* Found the slot - read the POS register 2 to get the necessary
341 configuration and status information. POS register 2 has the
342 following information :
343 Bit Function
344 7 reserved = 0
345 6 arbitration method
346 0 - fairness enabled
347 1 - fairness disabled, linear priority assignment
348 5-2 arbitration level
349 1 alternate address
350 1 alternate address
351 0 - use addresses 0x3510 - 0x3517
352 0 adapter enable
355 status = mca_read_stored_pos(slot, 2);
356 /* is it enabled ? */
357 if (!(status & STATUS_ENABLED)) {
358 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
359 return;
361 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
362 share with the SCSI driver */
363 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
364 SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
365 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
366 SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
368 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
369 return;
371 if (status & STATUS_ALTERNATE)
372 io_base = ALT_IO_BASE;
373 else
374 io_base = PRIMARY_IO_BASE;
376 /* get the dma arbitration level */
377 dma_arb_level = (status >> 2) & 0xf;
379 /* BA */
380 printk("%s: DMA arbitration level : %d\n",
381 DEVICE_NAME, dma_arb_level);
383 LITE_ON;
384 current_int_handler = ps2esdi_initial_reset_int_handler;
385 reset_ctrl();
386 reset_status = 0;
387 reset_start = jiffies;
388 while (!reset_status) {
389 esdi_timer.expires = 100;
390 esdi_timer.data = 0;
391 esdi_timer.next = esdi_timer.prev = NULL;
392 add_timer(&esdi_timer);
393 sleep_on(&ps2esdi_int);
395 reset_end = jiffies;
396 LITE_OFF;
397 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
398 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
399 (reset_end - reset_start) % HZ);
402 /* Integrated ESDI Disk and Controller has only one drive! */
403 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
404 ps2esdi_drives = 1; /* then we have only one physical disk! */
408 /* finally this part sets up some global data structures etc. */
410 ps2esdi_get_device_cfg();
412 /* some annoyance in the above routine returns TWO drives?
413 Is something else happining in the background?
414 Regaurdless we fix the # of drives again. AJK */
415 /* Integrated ESDI Disk and Controller has only one drive! */
416 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
417 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */
419 current_int_handler = ps2esdi_normal_interrupt_handler;
421 ps2esdi_gendisk.nr_real = ps2esdi_drives;
423 for (i = 0; i < ps2esdi_drives; i++) {
424 ps2esdi[i << 6].nr_sects =
425 ps2esdi_info[i].head *
426 ps2esdi_info[i].sect *
427 ps2esdi_info[i].cyl;
428 ps2esdi_valid[i] = 1;
430 for (i = 0; i < (MAX_HD << 6); i++)
431 ps2esdi_blocksizes[i] = 1024;
433 request_dma(dma_arb_level, "ed");
434 request_region(io_base, 4, "ed");
435 blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
436 } /* ps2esdi_geninit */
439 __initfunc(static void ps2esdi_get_device_cfg(void))
441 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
443 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
444 current_int_handler = ps2esdi_geometry_int_handler;
445 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
446 cmd_blk[1] = 0;
447 no_int_yet = TRUE;
448 ps2esdi_out_cmd_blk(cmd_blk);
449 if (no_int_yet)
450 sleep_on(&ps2esdi_int);
452 if (ps2esdi_drives > 1) {
453 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
454 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
455 cmd_blk[1] = 0;
456 no_int_yet = TRUE;
457 ps2esdi_out_cmd_blk(cmd_blk);
458 if (no_int_yet)
459 sleep_on(&ps2esdi_int);
460 } /* if second physical drive is present */
461 return;
464 /* strategy routine that handles most of the IO requests */
465 static void do_ps2esdi_request(void)
467 u_int block, count;
468 /* since, this routine is called with interrupts cleared - they
469 must be before it finishes */
470 sti();
472 #if 0
473 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
474 DEVICE_NAME,
475 CURRENT_DEV, MINOR(CURRENT->rq_dev),
476 CURRENT->cmd, CURRENT->sector,
477 CURRENT->nr_sectors, CURRENT->buffer);
478 #endif
480 /* standard macro that ensures that requests are really on the
481 list + sanity checks. */
482 INIT_REQUEST;
484 if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) {
485 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
486 end_request(FAIL);
487 if (CURRENT)
488 do_ps2esdi_request();
489 return;
490 } /* check for above 16Mb dmas */
491 if ((CURRENT_DEV < ps2esdi_drives) &&
492 (CURRENT->sector + CURRENT->nr_sectors <=
493 ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
494 #if 0
495 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
496 DEVICE_NAME,
497 CURRENT_DEV, MINOR(CURRENT->dev),
498 CURRENT->cmd, CURRENT->sector,
499 CURRENT->nr_sectors);
500 #endif
503 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
505 #if 0
506 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
507 #endif
508 count = CURRENT->nr_sectors;
509 switch (CURRENT->cmd) {
510 case READ:
511 ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
512 return;
513 break;
514 case WRITE:
515 ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
516 return;
517 break;
518 default:
519 printk("%s: Unknown command\n", DEVICE_NAME);
520 end_request(FAIL);
521 if (CURRENT)
522 do_ps2esdi_request();
523 break;
524 } /* handle different commands */
526 /* is request is valid */
527 else {
528 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
529 CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
530 end_request(FAIL);
531 if (CURRENT)
532 do_ps2esdi_request();
535 } /* main strategy routine */
537 /* resets the ESDI adapter */
538 static void reset_ctrl(void)
541 u_long expire;
542 u_short status;
544 /* enable interrupts on the controller */
545 status = inb(ESDI_INTRPT);
546 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
547 any interrupt pending... */
548 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
550 /* read the ESDI status port - if the controller is not busy,
551 simply do a soft reset (fast) - otherwise we'll have to do a
552 hard (slow) reset. */
553 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
554 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
555 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
557 /* soft reset */
558 else {
559 /*BA */
560 printk("%s: hard reset...\n", DEVICE_NAME);
561 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
562 expire = jiffies + 200;
563 while (time_before(jiffies, expire));
564 outb_p(1, ESDI_CONTROL);
565 } /* hard reset */
568 } /* reset the controller */
570 /* called by the strategy routine to handle read and write requests */
571 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
574 u_short track, head, cylinder, sector;
575 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
577 /* do some relevant arithmatic */
578 CURRENT->current_nr_sectors =
579 (count < (2 * MAX_16BIT / SECT_SIZE)) ? count : (2 * MAX_16BIT / SECT_SIZE);
580 track = block / ps2esdi_info[drive].sect;
581 head = track % ps2esdi_info[drive].head;
582 cylinder = track / ps2esdi_info[drive].head;
583 sector = block % ps2esdi_info[drive].sect;
585 #if 0
586 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
587 #endif
588 /* call the routine that actually fills out a command block */
589 ps2esdi_fill_cmd_block
590 (cmd_blk,
591 (cmd == READ) ? CMD_READ : CMD_WRITE,
592 cylinder, head, sector,
593 CURRENT->current_nr_sectors, drive);
595 /* send the command block to the controller */
596 if (ps2esdi_out_cmd_blk(cmd_blk)) {
597 printk("%s: Controller failed\n", DEVICE_NAME);
598 if ((++CURRENT->errors) < MAX_RETRIES)
599 return do_ps2esdi_request();
600 else {
601 end_request(FAIL);
602 if (CURRENT)
603 do_ps2esdi_request();
606 /* check for failure to put out the command block */
607 else {
608 #if 0
609 printk("%s: waiting for xfer\n", DEVICE_NAME);
610 #endif
611 /* turn disk lights on */
612 LITE_ON;
615 } /* ps2esdi_readwrite */
617 /* fill out the command block */
618 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
619 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
622 cmd_blk[0] = (drive << 5) | cmd;
623 cmd_blk[1] = length;
624 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
625 cmd_blk[3] = (cyl & 0x3E0) >> 5;
627 } /* fill out the command block */
629 /* write a command block to the controller */
630 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
633 int i, j;
634 u_char status;
636 /* enable interrupts */
637 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
639 /* do not write to the controller, if it is busy */
640 for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
641 STATUS_BUSY););
643 #if 0
644 printk("%s: i(1)=%d\n", DEVICE_NAME, i);
645 #endif
647 /* if device is still busy - then just time out */
648 if (inb(ESDI_STATUS) & STATUS_BUSY) {
649 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
650 return ERROR;
651 } /* timeout ??? */
652 /* Set up the attention register in the controller */
653 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
655 #if 0
656 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
657 #endif
659 /* one by one send each word out */
660 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
661 status = inb(ESDI_STATUS);
662 for (j = jiffies + ESDI_STAT_TIMEOUT;
663 time_after(j, jiffies) && (status & STATUS_BUSY) &&
664 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
665 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
666 #if 0
667 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
668 #endif
669 outw(*cmd_blk++, ESDI_CMD_INT);
670 } else {
671 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
672 DEVICE_NAME, status);
673 return ERROR;
675 } /* send all words out */
676 return OK;
677 } /* send out the commands */
680 /* prepare for dma - do all the necessary setup */
681 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
683 u_int tc;
685 buffer=(char *)virt_to_bus(buffer);
687 #if 0
688 printk("ps2esdi: b_wait: %p\n", CURRENT->bh->b_wait);
689 #endif
690 cli();
692 outb(dma_arb_level | DMA_MASK_CHAN, PORT_DMA_FN);
694 outb(dma_arb_level | DMA_WRITE_ADDR, PORT_DMA_FN);
695 outb((u_int) buffer & (u_int) 0xff, PORT_DMA_EX);
696 outb(((u_int) buffer >> 8) & (u_int) 0xff, PORT_DMA_EX);
697 outb(((u_int) buffer >> 16) & (u_int) 0xff, PORT_DMA_EX);
699 outb(dma_arb_level | DMA_WRITE_TC, PORT_DMA_FN);
700 tc = (length * SECT_SIZE / 2) - 1;
701 outb(tc & 0xff, PORT_DMA_EX);
702 outb((tc >> 8) & 0xff, PORT_DMA_EX);
704 outb(dma_arb_level | DMA_WRITE_MODE, PORT_DMA_FN);
705 outb(dma_xmode, PORT_DMA_EX);
707 outb(dma_arb_level | DMA_UNMASK_CHAN, PORT_DMA_FN);
709 sti();
711 } /* prepare for dma */
715 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
716 struct pt_regs *regs)
718 u_int int_ret_code;
720 if (inb(ESDI_STATUS) & STATUS_INTR) {
721 int_ret_code = inb(ESDI_INTRPT);
722 if (current_int_handler) {
723 /* Disable adapter interrupts till processing is finished */
724 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
725 current_int_handler(int_ret_code);
726 } else
727 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
728 } else {
729 return;
733 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
736 switch (int_ret_code & 0xf) {
737 case INT_RESET:
738 /*BA */
739 printk("%s: initial reset completed.\n", DEVICE_NAME);
740 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
741 wake_up(&ps2esdi_int);
742 break;
743 case INT_ATTN_ERROR:
744 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
745 int_ret_code);
746 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
747 break;
748 default:
749 printk("%s: initial reset handler received interrupt: %02X\n",
750 DEVICE_NAME, int_ret_code);
751 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
752 break;
754 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
758 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
760 u_int status, drive_num;
761 unsigned long rba;
762 int i;
764 drive_num = int_ret_code >> 5;
765 switch (int_ret_code & 0xf) {
766 case INT_CMD_COMPLETE:
767 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
768 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
769 printk("%s: timeout reading status word\n", DEVICE_NAME);
770 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
771 break;
773 status = inw(ESDI_STT_INT);
774 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
775 #define REPLY_WORDS 5 /* we already read word 0 */
776 u_short reply[REPLY_WORDS];
778 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
779 /*BA */
780 printk("%s: Device Configuration Status for drive %u\n",
781 DEVICE_NAME, drive_num);
783 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
785 printk
786 ("Config bits: %s%s%s%s%s\n",
787 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
788 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
789 ? "Zero Defect, " : "Defects Present, ",
790 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
791 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
792 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
794 rba = reply[1] | ((unsigned long) reply[2] << 16);
795 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
797 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
798 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
800 if (!ps2esdi_info[drive_num].head) {
801 ps2esdi_info[drive_num].head = 64;
802 ps2esdi_info[drive_num].sect = 32;
803 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
804 ps2esdi_info[drive_num].wpcom = 0;
805 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
806 ps2esdi_info[drive_num].ctl = 8;
807 if (tp720esdi) { /* store the retrieved parameters */
808 ps2esdi_info[0].head = reply[4] & 0Xff;
809 ps2esdi_info[0].sect = reply[4] >> 8;
810 ps2esdi_info[0].cyl = reply[3];
811 ps2esdi_info[0].wpcom = 0;
812 ps2esdi_info[0].lzone = reply[3];
813 } else {
814 ps2esdi_drives++;
817 #ifdef OBSOLETE
818 if (!ps2esdi_info[drive_num].head) {
819 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
820 ps2esdi_info[drive_num].sect = reply[4] >> 8;
821 ps2esdi_info[drive_num].cyl = reply[3];
822 ps2esdi_info[drive_num].wpcom = 0;
823 ps2esdi_info[drive_num].lzone = reply[3];
824 if (tp720esdi) { /* store the retrieved parameters */
825 ps2esdi_info[0].head = reply[4] & 0Xff;
826 ps2esdi_info[0].sect = reply[4] >> 8;
827 ps2esdi_info[0].cyl = reply[3];
828 ps2esdi_info[0].wpcom = 0;
829 ps2esdi_info[0].lzone = reply[3];
830 } else {
831 ps2esdi_drives++;
834 #endif
836 } else
837 printk("%s: failed while getting device config\n", DEVICE_NAME);
838 #undef REPLY_WORDS
839 } else
840 printk("%s: command %02X unknown by geometry handler\n",
841 DEVICE_NAME, status & 0x1f);
843 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
844 break;
846 case INT_ATTN_ERROR:
847 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
848 int_ret_code);
849 printk("%s: Device not available\n", DEVICE_NAME);
850 break;
851 case INT_CMD_ECC:
852 case INT_CMD_RETRY:
853 case INT_CMD_ECC_RETRY:
854 case INT_CMD_WARNING:
855 case INT_CMD_ABORT:
856 case INT_CMD_FAILED:
857 case INT_DMA_ERR:
858 case INT_CMD_BLK_ERR:
859 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
860 dump_cmd_complete_status(int_ret_code);
861 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
862 break;
863 default:
864 printk("%s: Unknown interrupt reason: %02X\n",
865 DEVICE_NAME, int_ret_code & 0xf);
866 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
867 break;
870 wake_up(&ps2esdi_int);
871 no_int_yet = FALSE;
872 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
876 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
878 u_int status;
879 int i;
881 switch (int_ret_code & 0x0f) {
882 case INT_TRANSFER_REQ:
883 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
884 (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16);
885 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
886 break;
888 case INT_ATTN_ERROR:
889 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
890 int_ret_code);
891 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
892 break;
894 case INT_CMD_COMPLETE:
895 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
896 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
897 printk("%s: timeout reading status word\n", DEVICE_NAME);
898 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
899 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
900 if ((++CURRENT->errors) < MAX_RETRIES)
901 do_ps2esdi_request();
902 else {
903 end_request(FAIL);
904 if (CURRENT)
905 do_ps2esdi_request();
907 break;
909 status = inw(ESDI_STT_INT);
910 switch (status & 0x1F) {
911 case (CMD_READ & 0xff):
912 case (CMD_WRITE & 0xff):
913 LITE_OFF;
914 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
915 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
916 #if 0
917 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);
918 #endif
919 ps2esdi_continue_request();
920 break;
921 default:
922 printk("%s: interrupt for unknown command %02X\n",
923 DEVICE_NAME, status & 0x1f);
924 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
925 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
926 break;
928 break;
929 case INT_CMD_ECC:
930 case INT_CMD_RETRY:
931 case INT_CMD_ECC_RETRY:
932 LITE_OFF;
933 dump_cmd_complete_status(int_ret_code);
934 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
935 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
936 ps2esdi_continue_request();
937 break;
938 case INT_CMD_WARNING:
939 case INT_CMD_ABORT:
940 case INT_CMD_FAILED:
941 case INT_DMA_ERR:
942 LITE_OFF;
943 dump_cmd_complete_status(int_ret_code);
944 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
945 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
946 if ((++CURRENT->errors) < MAX_RETRIES)
947 do_ps2esdi_request();
948 else {
949 end_request(FAIL);
950 if (CURRENT)
951 do_ps2esdi_request();
953 break;
955 case INT_CMD_BLK_ERR:
956 dump_cmd_complete_status(int_ret_code);
957 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
958 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
959 end_request(FAIL);
960 if (CURRENT)
961 do_ps2esdi_request();
962 break;
964 case INT_CMD_FORMAT:
965 printk("%s: huh ? Who issued this format command ?\n"
966 ,DEVICE_NAME);
967 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
968 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
969 break;
971 case INT_RESET:
972 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
973 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
974 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
975 break;
977 default:
978 printk("%s: Unknown interrupt reason: %02X\n",
979 DEVICE_NAME, int_ret_code & 0xf);
980 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
981 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
982 break;
985 } /* handle interrupts */
988 static void ps2esdi_continue_request(void)
990 if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
991 CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
992 CURRENT->sector += CURRENT->current_nr_sectors;
993 do_ps2esdi_request();
994 } else {
995 end_request(SUCCES);
996 if (CURRENT)
997 do_ps2esdi_request();
1003 static int ps2esdi_read_status_words(int num_words,
1004 int max_words,
1005 u_short * buffer)
1007 int i;
1009 for (; max_words && num_words; max_words--, num_words--, buffer++) {
1010 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
1011 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
1012 printk("%s: timeout reading status word\n", DEVICE_NAME);
1013 return FAIL;
1015 *buffer = inw(ESDI_STT_INT);
1017 return SUCCES;
1023 static void dump_cmd_complete_status(u_int int_ret_code)
1025 #define WAIT_FOR_STATUS \
1026 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
1027 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
1028 printk("%s: timeout reading status word\n",DEVICE_NAME); \
1029 return; \
1032 int i, word_count;
1033 u_short stat_word;
1034 u_long rba;
1036 printk("%s: Device: %u, interrupt ID: %02X\n",
1037 DEVICE_NAME, int_ret_code >> 5,
1038 int_ret_code & 0xf);
1040 WAIT_FOR_STATUS;
1041 stat_word = inw(ESDI_STT_INT);
1042 word_count = (stat_word >> 8) - 1;
1043 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1044 stat_word & 0xff);
1046 if (word_count--) {
1047 WAIT_FOR_STATUS;
1048 stat_word = inw(ESDI_STT_INT);
1049 printk("%s: command status code: %02X, command error code: %02X\n",
1050 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1052 if (word_count--) {
1053 WAIT_FOR_STATUS;
1054 stat_word = inw(ESDI_STT_INT);
1055 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1056 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1057 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1058 (stat_word & 0x0400) ? "Write Fault, " : "",
1059 (stat_word & 0x0200) ? "Track 0, " : "",
1060 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1061 stat_word >> 8);
1063 if (word_count--) {
1064 WAIT_FOR_STATUS;
1065 stat_word = inw(ESDI_STT_INT);
1066 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1068 if (word_count -= 2) {
1069 WAIT_FOR_STATUS;
1070 rba = inw(ESDI_STT_INT);
1071 WAIT_FOR_STATUS;
1072 rba |= inw(ESDI_STT_INT) << 16;
1073 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1074 (u_short) ((rba & 0x1ff80000) >> 11),
1075 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1076 } else
1077 printk("\n");
1079 if (word_count--) {
1080 WAIT_FOR_STATUS;
1081 stat_word = inw(ESDI_STT_INT);
1082 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1084 printk("\n");
1086 #undef WAIT_FOR_STATUS
1091 static int ps2esdi_open(struct inode *inode, struct file *file)
1093 int dev = DEVICE_NR(inode->i_rdev);
1095 if (dev < ps2esdi_drives) {
1096 while (!ps2esdi_valid[dev])
1097 sleep_on(&ps2esdi_wait_open);
1099 access_count[dev]++;
1101 return (0);
1102 } else
1103 return (-ENODEV);
1108 static int ps2esdi_release(struct inode *inode, struct file *file)
1110 int dev = DEVICE_NR(inode->i_rdev);
1112 if (dev < ps2esdi_drives) {
1113 sync_dev(inode->i_rdev);
1114 access_count[dev]--;
1116 return 0;
1121 static int ps2esdi_ioctl(struct inode *inode,
1122 struct file *file, u_int cmd, u_long arg)
1125 struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1126 int dev = DEVICE_NR(inode->i_rdev), err;
1128 if (inode && (dev < ps2esdi_drives))
1129 switch (cmd) {
1130 case HDIO_GETGEO:
1131 if (arg) {
1132 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1133 return (err);
1134 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1135 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1136 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1137 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1138 (long *) &geometry->start);
1140 return (0);
1142 break;
1143 case BLKRASET:
1144 if (!capable(CAP_SYS_ADMIN))
1145 return -EACCES;
1146 if (!inode->i_rdev)
1147 return -EINVAL;
1148 if (arg > 0xff)
1149 return -EINVAL;
1150 read_ahead[MAJOR(inode->i_rdev)] = arg;
1151 return 0;
1152 case BLKGETSIZE:
1153 if (arg) {
1154 if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
1155 return (err);
1156 put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
1158 return (0);
1160 break;
1161 case BLKFLSBUF:
1162 if (!capable(CAP_SYS_ADMIN))
1163 return -EACCES;
1164 if (!inode->i_rdev)
1165 return -EINVAL;
1166 fsync_dev(inode->i_rdev);
1167 invalidate_buffers(inode->i_rdev);
1168 return 0;
1170 case BLKRRPART:
1171 if (!capable(CAP_SYS_ADMIN))
1172 return -EACCES;
1173 return (ps2esdi_reread_partitions(inode->i_rdev));
1174 RO_IOCTLS(inode->i_rdev, arg);
1176 return (-EINVAL);
1181 static int ps2esdi_reread_partitions(kdev_t dev)
1183 int target = DEVICE_NR(dev);
1184 int start = target << ps2esdi_gendisk.minor_shift;
1185 int partition;
1187 cli();
1188 ps2esdi_valid[target] = (access_count[target] != 1);
1189 sti();
1190 if (ps2esdi_valid[target])
1191 return (-EBUSY);
1193 for (partition = ps2esdi_gendisk.max_p - 1;
1194 partition >= 0; partition--) {
1195 int minor = (start | partition);
1196 kdev_t devp = MKDEV(MAJOR_NR, minor);
1197 struct super_block * sb = get_super(devp);
1199 sync_dev(devp);
1200 if (sb)
1201 invalidate_inodes(sb);
1202 invalidate_buffers(devp);
1203 ps2esdi_gendisk.part[start + partition].start_sect = 0;
1204 ps2esdi_gendisk.part[start + partition].nr_sects = 0;
1207 ps2esdi_gendisk.part[start].nr_sects = ps2esdi_info[target].head *
1208 ps2esdi_info[target].cyl * ps2esdi_info[target].sect;
1209 resetup_one_dev(&ps2esdi_gendisk, target);
1211 ps2esdi_valid[target] = 1;
1212 wake_up(&ps2esdi_wait_open);
1214 return (0);
1217 void ps2esdi_reset_timer(unsigned long unused)
1220 int status;
1222 status = inb(ESDI_INTRPT);
1223 if ((status & 0xf) == INT_RESET) {
1224 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1225 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1226 reset_status = 1;
1228 wake_up(&ps2esdi_int);
1231 #endif