Import 2.1.81
[davej-history.git] / drivers / block / ps2esdi.c
blobb109192fbd0e62a2271ed614a56f1cfb7e309235
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>
48 #include <asm/system.h>
49 #include <asm/io.h>
50 #include <asm/segment.h>
51 #include <asm/dma.h>
52 #include <asm/uaccess.h>
54 #define PS2ESDI_IRQ 14
55 #define MAX_HD 1
56 #define MAX_RETRIES 5
57 #define MAX_16BIT 65536
58 #define ESDI_TIMEOUT 0xf000
59 #define ESDI_STAT_TIMEOUT 4
61 #define TYPE_0_CMD_BLK_LENGTH 2
62 #define TYPE_1_CMD_BLK_LENGTH 4
65 static void reset_ctrl(void);
67 int ps2esdi_init(void);
69 static void ps2esdi_geninit(struct gendisk *ignored);
71 static void do_ps2esdi_request(void);
73 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
75 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
76 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
78 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
80 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
82 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
83 struct pt_regs *regs);
84 static void (*current_int_handler) (u_int) = NULL;
85 static void ps2esdi_normal_interrupt_handler(u_int);
86 static void ps2esdi_initial_reset_int_handler(u_int);
87 static void ps2esdi_geometry_int_handler(u_int);
89 static void ps2esdi_continue_request(void);
91 static int ps2esdi_open(struct inode *inode, struct file *file);
93 static int ps2esdi_release(struct inode *inode, struct file *file);
95 static int ps2esdi_ioctl(struct inode *inode, struct file *file,
96 u_int cmd, u_long arg);
98 static int ps2esdi_reread_partitions(int dev);
100 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
102 static void dump_cmd_complete_status(u_int int_ret_code);
104 static void ps2esdi_get_device_cfg(void);
106 void ps2esdi_reset_timer(unsigned long unused);
108 u_int dma_arb_level; /* DMA arbitration level */
110 static struct wait_queue *ps2esdi_int = NULL, *ps2esdi_wait_open = NULL;
111 int no_int_yet;
112 static int access_count[MAX_HD] =
113 {0,};
114 static char ps2esdi_valid[MAX_HD] =
115 {0,};
116 static int ps2esdi_sizes[MAX_HD << 6] =
117 {0,};
118 static int ps2esdi_blocksizes[MAX_HD << 6] =
119 {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 =
124 {NULL, NULL, 0, 0L, ps2esdi_reset_timer};
125 static int reset_status;
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 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 /* handles boot time command line parameters */
201 __initfunc(void tp720_setup(char *str, int *ints))
203 /* no params, just sets the tp720esdi flag if it exists */
205 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
206 tp720esdi = 1;
209 __initfunc(void ed_setup(char *str, int *ints))
211 int hdind = 0;
213 /* handles 3 parameters only - corresponding to
214 1. Number of cylinders
215 2. Number of heads
216 3. Sectors/track
219 if (ints[0] != 3)
220 return;
222 /* print out the information - seen at boot time */
223 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
224 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
226 /* set the index into device specific information table */
227 if (ps2esdi_info[0].head != 0)
228 hdind = 1;
230 /* set up all the device information */
231 ps2esdi_info[hdind].head = ints[2];
232 ps2esdi_info[hdind].sect = ints[3];
233 ps2esdi_info[hdind].cyl = ints[1];
234 ps2esdi_info[hdind].wpcom = 0;
235 ps2esdi_info[hdind].lzone = ints[1];
236 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
237 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
238 ps2esdi_drives = hdind + 1; /* increment index for the next time */
239 #endif
240 } /* ed_setup */
242 static int ps2esdi_getinfo(char *buf, int slot, void *d)
244 int len = 0;
246 len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
247 dma_arb_level);
248 len += sprintf(buf + len, "IO Port: %x\n", io_base);
249 len += sprintf(buf + len, "IRQ: 14\n");
250 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
252 return len;
255 /* ps2 esdi specific initialization - called thru the gendisk chain */
256 __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
259 The first part contains the initialization code
260 for the ESDI disk subsystem. All we really do
261 is search for the POS registers of the controller
262 to do some simple setup operations. First, we
263 must ensure that the controller is installed,
264 enabled, and configured as PRIMARY. Then we must
265 determine the DMA arbitration level being used by
266 the controller so we can handle data transfer
267 operations properly. If all of this works, then
268 we will set the INIT_FLAG to a non-zero value.
271 int slot = 0, i, reset_start, reset_end;
272 u_char status;
273 unsigned short adapterID;
275 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
276 adapterID = INTG_ESDI_ID;
277 printk("%s: integrated ESDI adapter found in slot %d\n",
278 DEVICE_NAME, slot+1);
279 #ifndef MODULE
280 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
281 #endif
282 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
283 adapterID = NRML_ESDI_ID;
284 printk("%s: normal ESDI adapter found in slot %d\n",
285 DEVICE_NAME, slot+1);
286 mca_set_adapter_name(slot, "PS/2 ESDI");
287 } else {
288 return;
291 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
293 /* Found the slot - read the POS register 2 to get the necessary
294 configuration and status information. POS register 2 has the
295 following information :
296 Bit Function
297 7 reserved = 0
298 6 arbitration method
299 0 - fairness enabled
300 1 - fairness disabled, linear priority assignment
301 5-2 arbitration level
302 1 alternate address
303 1 alternate address
304 0 - use addresses 0x3510 - 0x3517
305 0 adapter enable
308 status = mca_read_stored_pos(slot, 2);
309 /* is it enabled ? */
310 if (!(status & STATUS_ENABLED)) {
311 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
312 return;
314 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
315 share with the SCSI driver */
316 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
317 SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
318 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
319 SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
321 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
322 return;
324 if (status & STATUS_ALTERNATE)
325 io_base = ALT_IO_BASE;
326 else
327 io_base = PRIMARY_IO_BASE;
329 /* get the dma arbitration level */
330 dma_arb_level = (status >> 2) & 0xf;
332 /* BA */
333 printk("%s: DMA arbitration level : %d\n",
334 DEVICE_NAME, dma_arb_level);
336 LITE_ON;
337 current_int_handler = ps2esdi_initial_reset_int_handler;
338 reset_ctrl();
339 reset_status = 0;
340 reset_start = jiffies;
341 while (!reset_status) {
342 esdi_timer.expires = 100;
343 esdi_timer.data = 0;
344 esdi_timer.next = esdi_timer.prev = NULL;
345 add_timer(&esdi_timer);
346 sleep_on(&ps2esdi_int);
348 reset_end = jiffies;
349 LITE_OFF;
350 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
351 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
352 (reset_end - reset_start) % HZ);
355 /* Integrated ESDI Disk and Controller has only one drive! */
356 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
357 ps2esdi_drives = 1; /* then we have only one physical disk! */
361 /* finally this part sets up some global data structures etc. */
363 ps2esdi_get_device_cfg();
365 /* some annoyance in the above routine returns TWO drives?
366 Is something else happining in the background?
367 Regaurdless we fix the # of drives again. AJK */
368 /* Integrated ESDI Disk and Controller has only one drive! */
369 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
370 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */
372 current_int_handler = ps2esdi_normal_interrupt_handler;
374 ps2esdi_gendisk.nr_real = ps2esdi_drives;
376 for (i = 0; i < ps2esdi_drives; i++) {
377 ps2esdi[i << 6].nr_sects =
378 ps2esdi_info[i].head *
379 ps2esdi_info[i].sect *
380 ps2esdi_info[i].cyl;
381 ps2esdi_valid[i] = 1;
383 for (i = 0; i < (MAX_HD << 6); i++)
384 ps2esdi_blocksizes[i] = 1024;
385 blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
386 } /* ps2esdi_geninit */
389 __initfunc(static void ps2esdi_get_device_cfg(void))
391 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
393 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
394 current_int_handler = ps2esdi_geometry_int_handler;
395 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
396 cmd_blk[1] = 0;
397 no_int_yet = TRUE;
398 ps2esdi_out_cmd_blk(cmd_blk);
399 if (no_int_yet)
400 sleep_on(&ps2esdi_int);
402 if (ps2esdi_drives > 1) {
403 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
404 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
405 cmd_blk[1] = 0;
406 no_int_yet = TRUE;
407 ps2esdi_out_cmd_blk(cmd_blk);
408 if (no_int_yet)
409 sleep_on(&ps2esdi_int);
410 } /* if second physical drive is present */
411 return;
414 /* strategy routine that handles most of the IO requests */
415 static void do_ps2esdi_request(void)
417 u_int block, count;
418 /* since, this routine is called with interrupts cleared - they
419 must be before it finishes */
420 sti();
422 #if 0
423 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
424 DEVICE_NAME,
425 CURRENT_DEV, MINOR(CURRENT->rq_dev),
426 CURRENT->cmd, CURRENT->sector,
427 CURRENT->nr_sectors, CURRENT->buffer);
428 #endif
430 /* standard macro that ensures that requests are really on the
431 list + sanity checks. */
432 INIT_REQUEST;
434 if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) {
435 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
436 end_request(FAIL);
437 if (CURRENT)
438 do_ps2esdi_request();
439 return;
440 } /* check for above 16Mb dmas */
441 if ((CURRENT_DEV < ps2esdi_drives) &&
442 (CURRENT->sector + CURRENT->nr_sectors <=
443 ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
444 #if 0
445 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
446 DEVICE_NAME,
447 CURRENT_DEV, MINOR(CURRENT->dev),
448 CURRENT->cmd, CURRENT->sector,
449 CURRENT->nr_sectors);
450 #endif
453 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
455 #if 0
456 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
457 #endif
458 count = CURRENT->nr_sectors;
459 switch (CURRENT->cmd) {
460 case READ:
461 ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
462 return;
463 break;
464 case WRITE:
465 ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
466 return;
467 break;
468 default:
469 printk("%s: Unknown command\n", DEVICE_NAME);
470 end_request(FAIL);
471 if (CURRENT)
472 do_ps2esdi_request();
473 break;
474 } /* handle different commands */
476 /* is request is valid */
477 else {
478 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
479 CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
480 end_request(FAIL);
481 if (CURRENT)
482 do_ps2esdi_request();
485 } /* main strategy routine */
487 /* resets the ESDI adapter */
488 static void reset_ctrl(void)
491 u_long expire;
492 u_short status;
494 /* enable interrupts on the controller */
495 status = inb(ESDI_INTRPT);
496 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
497 any interrupt pending... */
498 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
500 /* read the ESDI status port - if the controller is not busy,
501 simply do a soft reset (fast) - otherwise we'll have to do a
502 hard (slow) reset. */
503 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
504 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
505 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
507 /* soft reset */
508 else {
509 /*BA */
510 printk("%s: hard reset...\n", DEVICE_NAME);
511 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
512 expire = jiffies + 200;
513 while (jiffies < expire);
514 outb_p(1, ESDI_CONTROL);
515 } /* hard reset */
518 } /* reset the controller */
520 /* called by the strategy routine to handle read and write requests */
521 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
524 u_short track, head, cylinder, sector;
525 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
527 /* do some relevant arithmatic */
528 CURRENT->current_nr_sectors =
529 (count < (2 * MAX_16BIT / SECT_SIZE)) ? count : (2 * MAX_16BIT / SECT_SIZE);
530 track = block / ps2esdi_info[drive].sect;
531 head = track % ps2esdi_info[drive].head;
532 cylinder = track / ps2esdi_info[drive].head;
533 sector = block % ps2esdi_info[drive].sect;
535 #if 0
536 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
537 #endif
538 /* call the routine that actually fills out a command block */
539 ps2esdi_fill_cmd_block
540 (cmd_blk,
541 (cmd == READ) ? CMD_READ : CMD_WRITE,
542 cylinder, head, sector,
543 CURRENT->current_nr_sectors, drive);
545 /* send the command block to the controller */
546 if (ps2esdi_out_cmd_blk(cmd_blk)) {
547 printk("%s: Controller failed\n", DEVICE_NAME);
548 if ((++CURRENT->errors) < MAX_RETRIES)
549 return do_ps2esdi_request();
550 else {
551 end_request(FAIL);
552 if (CURRENT)
553 do_ps2esdi_request();
556 /* check for failure to put out the command block */
557 else {
558 #if 0
559 printk("%s: waiting for xfer\n", DEVICE_NAME);
560 #endif
561 /* turn disk lights on */
562 LITE_ON;
565 } /* ps2esdi_readwrite */
567 /* fill out the command block */
568 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
569 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
572 cmd_blk[0] = (drive << 5) | cmd;
573 cmd_blk[1] = length;
574 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
575 cmd_blk[3] = (cyl & 0x3E0) >> 5;
577 } /* fill out the command block */
579 /* write a command block to the controller */
580 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
583 int i, j;
584 u_char status;
586 /* enable interrupts */
587 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
589 /* do not write to the controller, if it is busy */
590 for (i = jiffies + ESDI_STAT_TIMEOUT; (i > jiffies) && (inb(ESDI_STATUS) &
591 STATUS_BUSY););
593 #if 0
594 printk("%s: i(1)=%d\n", DEVICE_NAME, i);
595 #endif
597 /* if device is still busy - then just time out */
598 if (inb(ESDI_STATUS) & STATUS_BUSY) {
599 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
600 return ERROR;
601 } /* timeout ??? */
602 /* Set up the attention register in the controller */
603 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
605 #if 0
606 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
607 #endif
609 /* one by one send each word out */
610 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
611 status = inb(ESDI_STATUS);
612 for (j = jiffies + ESDI_STAT_TIMEOUT;
613 (j > jiffies) && (status & STATUS_BUSY) &&
614 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
615 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
616 #if 0
617 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
618 #endif
619 outw(*cmd_blk++, ESDI_CMD_INT);
620 } else {
621 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
622 DEVICE_NAME, status);
623 return ERROR;
625 } /* send all words out */
626 return OK;
627 } /* send out the commands */
630 /* prepare for dma - do all the necessary setup */
631 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
633 u_int tc;
635 buffer=(char *)virt_to_bus(buffer);
637 #if 0
638 printk("ps2esdi: b_wait: %p\n", CURRENT->bh->b_wait);
639 #endif
640 cli();
642 outb(dma_arb_level | DMA_MASK_CHAN, PORT_DMA_FN);
644 outb(dma_arb_level | DMA_WRITE_ADDR, PORT_DMA_FN);
645 outb((u_int) buffer & (u_int) 0xff, PORT_DMA_EX);
646 outb(((u_int) buffer >> 8) & (u_int) 0xff, PORT_DMA_EX);
647 outb(((u_int) buffer >> 16) & (u_int) 0xff, PORT_DMA_EX);
649 outb(dma_arb_level | DMA_WRITE_TC, PORT_DMA_FN);
650 tc = (length * SECT_SIZE / 2) - 1;
651 outb(tc & 0xff, PORT_DMA_EX);
652 outb((tc >> 8) & 0xff, PORT_DMA_EX);
654 outb(dma_arb_level | DMA_WRITE_MODE, PORT_DMA_FN);
655 outb(dma_xmode, PORT_DMA_EX);
657 outb(dma_arb_level | DMA_UNMASK_CHAN, PORT_DMA_FN);
659 sti();
661 } /* prepare for dma */
665 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
666 struct pt_regs *regs)
668 u_int int_ret_code;
670 if (inb(ESDI_STATUS) & STATUS_INTR) {
671 int_ret_code = inb(ESDI_INTRPT);
672 if (current_int_handler) {
673 /* Disable adapter interrupts till processing is finished */
674 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
675 current_int_handler(int_ret_code);
676 } else
677 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
678 } else {
679 return;
683 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
686 switch (int_ret_code & 0xf) {
687 case INT_RESET:
688 /*BA */
689 printk("%s: initial reset completed.\n", DEVICE_NAME);
690 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
691 wake_up(&ps2esdi_int);
692 break;
693 case INT_ATTN_ERROR:
694 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
695 int_ret_code);
696 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
697 break;
698 default:
699 printk("%s: initial reset handler received interrupt: %02X\n",
700 DEVICE_NAME, int_ret_code);
701 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
702 break;
704 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
708 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
710 u_int status, drive_num;
711 unsigned long rba;
712 int i;
714 drive_num = int_ret_code >> 5;
715 switch (int_ret_code & 0xf) {
716 case INT_CMD_COMPLETE:
717 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
718 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
719 printk("%s: timeout reading status word\n", DEVICE_NAME);
720 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
721 break;
723 status = inw(ESDI_STT_INT);
724 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
725 #define REPLY_WORDS 5 /* we already read word 0 */
726 u_short reply[REPLY_WORDS];
728 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
729 /*BA */
730 printk("%s: Device Configuration Status for drive %u\n",
731 DEVICE_NAME, drive_num);
733 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
735 printk
736 ("Config bits: %s%s%s%s%s\n",
737 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
738 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
739 ? "Zero Defect, " : "Defects Present, ",
740 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
741 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
742 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
744 rba = reply[1] | ((unsigned long) reply[2] << 16);
745 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
747 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
748 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
750 if (!ps2esdi_info[drive_num].head) {
751 ps2esdi_info[drive_num].head = 64;
752 ps2esdi_info[drive_num].sect = 32;
753 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
754 ps2esdi_info[drive_num].wpcom = 0;
755 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
756 ps2esdi_info[drive_num].ctl = 8;
757 if (tp720esdi) { /* store the retrieved parameters */
758 ps2esdi_info[0].head = reply[4] & 0Xff;
759 ps2esdi_info[0].sect = reply[4] >> 8;
760 ps2esdi_info[0].cyl = reply[3];
761 ps2esdi_info[0].wpcom = 0;
762 ps2esdi_info[0].lzone = reply[3];
763 } else {
764 ps2esdi_drives++;
767 #ifdef OBSOLETE
768 if (!ps2esdi_info[drive_num].head) {
769 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
770 ps2esdi_info[drive_num].sect = reply[4] >> 8;
771 ps2esdi_info[drive_num].cyl = reply[3];
772 ps2esdi_info[drive_num].wpcom = 0;
773 ps2esdi_info[drive_num].lzone = reply[3];
774 if (tp720esdi) { /* store the retrieved parameters */
775 ps2esdi_info[0].head = reply[4] & 0Xff;
776 ps2esdi_info[0].sect = reply[4] >> 8;
777 ps2esdi_info[0].cyl = reply[3];
778 ps2esdi_info[0].wpcom = 0;
779 ps2esdi_info[0].lzone = reply[3];
780 } else {
781 ps2esdi_drives++;
784 #endif
786 } else
787 printk("%s: failed while getting device config\n", DEVICE_NAME);
788 #undef REPLY_WORDS
789 } else
790 printk("%s: command %02X unknown by geometry handler\n",
791 DEVICE_NAME, status & 0x1f);
793 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
794 break;
796 case INT_ATTN_ERROR:
797 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
798 int_ret_code);
799 printk("%s: Device not available\n", DEVICE_NAME);
800 break;
801 case INT_CMD_ECC:
802 case INT_CMD_RETRY:
803 case INT_CMD_ECC_RETRY:
804 case INT_CMD_WARNING:
805 case INT_CMD_ABORT:
806 case INT_CMD_FAILED:
807 case INT_DMA_ERR:
808 case INT_CMD_BLK_ERR:
809 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
810 dump_cmd_complete_status(int_ret_code);
811 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
812 break;
813 default:
814 printk("%s: Unknown interrupt reason: %02X\n",
815 DEVICE_NAME, int_ret_code & 0xf);
816 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
817 break;
820 wake_up(&ps2esdi_int);
821 no_int_yet = FALSE;
822 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
826 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
828 u_int status;
829 int i;
831 switch (int_ret_code & 0x0f) {
832 case INT_TRANSFER_REQ:
833 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
834 (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16);
835 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
836 break;
838 case INT_ATTN_ERROR:
839 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
840 int_ret_code);
841 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
842 break;
844 case INT_CMD_COMPLETE:
845 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
846 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
847 printk("%s: timeout reading status word\n", DEVICE_NAME);
848 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
849 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
850 if ((++CURRENT->errors) < MAX_RETRIES)
851 do_ps2esdi_request();
852 else {
853 end_request(FAIL);
854 if (CURRENT)
855 do_ps2esdi_request();
857 break;
859 status = inw(ESDI_STT_INT);
860 switch (status & 0x1F) {
861 case (CMD_READ & 0xff):
862 case (CMD_WRITE & 0xff):
863 LITE_OFF;
864 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
865 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
866 #if 0
867 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);
868 #endif
869 ps2esdi_continue_request();
870 break;
871 default:
872 printk("%s: interrupt for unknown command %02X\n",
873 DEVICE_NAME, status & 0x1f);
874 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
875 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
876 break;
878 break;
879 case INT_CMD_ECC:
880 case INT_CMD_RETRY:
881 case INT_CMD_ECC_RETRY:
882 LITE_OFF;
883 dump_cmd_complete_status(int_ret_code);
884 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
885 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
886 ps2esdi_continue_request();
887 break;
888 case INT_CMD_WARNING:
889 case INT_CMD_ABORT:
890 case INT_CMD_FAILED:
891 case INT_DMA_ERR:
892 LITE_OFF;
893 dump_cmd_complete_status(int_ret_code);
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();
898 else {
899 end_request(FAIL);
900 if (CURRENT)
901 do_ps2esdi_request();
903 break;
905 case INT_CMD_BLK_ERR:
906 dump_cmd_complete_status(int_ret_code);
907 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
908 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
909 end_request(FAIL);
910 if (CURRENT)
911 do_ps2esdi_request();
912 break;
914 case INT_CMD_FORMAT:
915 printk("%s: huh ? Who issued this format command ?\n"
916 ,DEVICE_NAME);
917 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
918 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
919 break;
921 case INT_RESET:
922 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
923 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
924 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
925 break;
927 default:
928 printk("%s: Unknown interrupt reason: %02X\n",
929 DEVICE_NAME, int_ret_code & 0xf);
930 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
931 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
932 break;
935 } /* handle interrupts */
938 static void ps2esdi_continue_request(void)
940 if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
941 CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
942 CURRENT->sector += CURRENT->current_nr_sectors;
943 do_ps2esdi_request();
944 } else {
945 end_request(SUCCES);
946 if (CURRENT)
947 do_ps2esdi_request();
953 static int ps2esdi_read_status_words(int num_words,
954 int max_words,
955 u_short * buffer)
957 int i;
959 for (; max_words && num_words; max_words--, num_words--, buffer++) {
960 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
961 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
962 printk("%s: timeout reading status word\n", DEVICE_NAME);
963 return FAIL;
965 *buffer = inw(ESDI_STT_INT);
967 return SUCCES;
973 static void dump_cmd_complete_status(u_int int_ret_code)
975 #define WAIT_FOR_STATUS \
976 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
977 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
978 printk("%s: timeout reading status word\n",DEVICE_NAME); \
979 return; \
982 int i, word_count;
983 u_short stat_word;
984 u_long rba;
986 printk("%s: Device: %u, interrupt ID: %02X\n",
987 DEVICE_NAME, int_ret_code >> 5,
988 int_ret_code & 0xf);
990 WAIT_FOR_STATUS;
991 stat_word = inw(ESDI_STT_INT);
992 word_count = (stat_word >> 8) - 1;
993 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
994 stat_word & 0xff);
996 if (word_count--) {
997 WAIT_FOR_STATUS;
998 stat_word = inw(ESDI_STT_INT);
999 printk("%s: command status code: %02X, command error code: %02X\n",
1000 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1002 if (word_count--) {
1003 WAIT_FOR_STATUS;
1004 stat_word = inw(ESDI_STT_INT);
1005 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1006 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1007 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1008 (stat_word & 0x0400) ? "Write Fault, " : "",
1009 (stat_word & 0x0200) ? "Track 0, " : "",
1010 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1011 stat_word >> 8);
1013 if (word_count--) {
1014 WAIT_FOR_STATUS;
1015 stat_word = inw(ESDI_STT_INT);
1016 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1018 if (word_count -= 2) {
1019 WAIT_FOR_STATUS;
1020 rba = inw(ESDI_STT_INT);
1021 WAIT_FOR_STATUS;
1022 rba |= inw(ESDI_STT_INT) << 16;
1023 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1024 (u_short) ((rba & 0x1ff80000) >> 11),
1025 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1026 } else
1027 printk("\n");
1029 if (word_count--) {
1030 WAIT_FOR_STATUS;
1031 stat_word = inw(ESDI_STT_INT);
1032 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1034 printk("\n");
1036 #undef WAIT_FOR_STATUS
1041 static int ps2esdi_open(struct inode *inode, struct file *file)
1043 int dev = DEVICE_NR(inode->i_rdev);
1045 if (dev < ps2esdi_drives) {
1046 while (!ps2esdi_valid[dev])
1047 sleep_on(&ps2esdi_wait_open);
1049 access_count[dev]++;
1051 return (0);
1052 } else
1053 return (-ENODEV);
1058 static int ps2esdi_release(struct inode *inode, struct file *file)
1060 int dev = DEVICE_NR(inode->i_rdev);
1062 if (dev < ps2esdi_drives) {
1063 sync_dev(dev);
1064 access_count[dev]--;
1066 return 0;
1071 static int ps2esdi_ioctl(struct inode *inode,
1072 struct file *file, u_int cmd, u_long arg)
1075 struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1076 int dev = DEVICE_NR(inode->i_rdev), err;
1078 if (inode && (dev < ps2esdi_drives))
1079 switch (cmd) {
1080 case HDIO_GETGEO:
1081 if (arg) {
1082 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1083 return (err);
1084 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1085 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1086 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1087 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1088 (long *) &geometry->start);
1090 return (0);
1092 break;
1093 case BLKRASET:
1094 if (!suser())
1095 return -EACCES;
1096 if (!inode->i_rdev)
1097 return -EINVAL;
1098 if (arg > 0xff)
1099 return -EINVAL;
1100 read_ahead[MAJOR(inode->i_rdev)] = arg;
1101 return 0;
1102 case BLKGETSIZE:
1103 if (arg) {
1104 if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
1105 return (err);
1106 put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
1108 return (0);
1110 break;
1111 case BLKFLSBUF:
1112 if (!suser())
1113 return -EACCES;
1114 if (!inode->i_rdev)
1115 return -EINVAL;
1116 fsync_dev(inode->i_rdev);
1117 invalidate_buffers(inode->i_rdev);
1118 return 0;
1120 case BLKRRPART:
1121 return (ps2esdi_reread_partitions(inode->i_rdev));
1122 RO_IOCTLS(inode->i_rdev, arg);
1124 return (-EINVAL);
1129 static int ps2esdi_reread_partitions(int dev)
1131 int target = DEVICE_NR(dev);
1132 int start = target << ps2esdi_gendisk.minor_shift;
1133 int partition;
1135 cli();
1136 ps2esdi_valid[target] = (access_count[target] != 1);
1137 sti();
1138 if (ps2esdi_valid[target])
1139 return (-EBUSY);
1141 for (partition = ps2esdi_gendisk.max_p - 1;
1142 partition >= 0; partition--) {
1143 int minor = (start | partition);
1144 kdev_t devp = MKDEV(MAJOR_NR, minor);
1145 struct super_block * sb = get_super(devp);
1147 sync_dev(devp);
1148 if (sb)
1149 invalidate_inodes(sb);
1150 invalidate_buffers(devp);
1151 ps2esdi_gendisk.part[start + partition].start_sect = 0;
1152 ps2esdi_gendisk.part[start + partition].nr_sects = 0;
1155 ps2esdi_gendisk.part[start].nr_sects = ps2esdi_info[target].head *
1156 ps2esdi_info[target].cyl * ps2esdi_info[target].sect;
1157 resetup_one_dev(&ps2esdi_gendisk, target);
1159 ps2esdi_valid[target] = 1;
1160 wake_up(&ps2esdi_wait_open);
1162 return (0);
1165 void ps2esdi_reset_timer(unsigned long unused)
1168 int status;
1170 status = inb(ESDI_INTRPT);
1171 if ((status & 0xf) == INT_RESET) {
1172 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1173 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1174 reset_status = 1;
1176 wake_up(&ps2esdi_int);
1179 #endif