Import 2.1.118
[davej-history.git] / drivers / block / ps2esdi.c
blobe56616a773abad97d536ada55601f7823f162798
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(kdev_t 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 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 /* handles boot time command line parameters */
202 __initfunc(void tp720_setup(char *str, int *ints))
204 /* no params, just sets the tp720esdi flag if it exists */
206 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
207 tp720esdi = 1;
210 __initfunc(void ed_setup(char *str, int *ints))
212 int hdind = 0;
214 /* handles 3 parameters only - corresponding to
215 1. Number of cylinders
216 2. Number of heads
217 3. Sectors/track
220 if (ints[0] != 3)
221 return;
223 /* print out the information - seen at boot time */
224 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
225 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
227 /* set the index into device specific information table */
228 if (ps2esdi_info[0].head != 0)
229 hdind = 1;
231 /* set up all the device information */
232 ps2esdi_info[hdind].head = ints[2];
233 ps2esdi_info[hdind].sect = ints[3];
234 ps2esdi_info[hdind].cyl = ints[1];
235 ps2esdi_info[hdind].wpcom = 0;
236 ps2esdi_info[hdind].lzone = ints[1];
237 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
238 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
239 ps2esdi_drives = hdind + 1; /* increment index for the next time */
240 #endif
241 } /* ed_setup */
243 static int ps2esdi_getinfo(char *buf, int slot, void *d)
245 int len = 0;
247 len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
248 dma_arb_level);
249 len += sprintf(buf + len, "IO Port: %x\n", io_base);
250 len += sprintf(buf + len, "IRQ: 14\n");
251 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
253 return len;
256 /* ps2 esdi specific initialization - called thru the gendisk chain */
257 __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
260 The first part contains the initialization code
261 for the ESDI disk subsystem. All we really do
262 is search for the POS registers of the controller
263 to do some simple setup operations. First, we
264 must ensure that the controller is installed,
265 enabled, and configured as PRIMARY. Then we must
266 determine the DMA arbitration level being used by
267 the controller so we can handle data transfer
268 operations properly. If all of this works, then
269 we will set the INIT_FLAG to a non-zero value.
272 int slot = 0, i, reset_start, reset_end;
273 u_char status;
274 unsigned short adapterID;
276 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
277 adapterID = INTG_ESDI_ID;
278 printk("%s: integrated ESDI adapter found in slot %d\n",
279 DEVICE_NAME, slot+1);
280 #ifndef MODULE
281 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
282 #endif
283 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
284 adapterID = NRML_ESDI_ID;
285 printk("%s: normal ESDI adapter found in slot %d\n",
286 DEVICE_NAME, slot+1);
287 mca_set_adapter_name(slot, "PS/2 ESDI");
288 } else {
289 return;
292 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
294 /* Found the slot - read the POS register 2 to get the necessary
295 configuration and status information. POS register 2 has the
296 following information :
297 Bit Function
298 7 reserved = 0
299 6 arbitration method
300 0 - fairness enabled
301 1 - fairness disabled, linear priority assignment
302 5-2 arbitration level
303 1 alternate address
304 1 alternate address
305 0 - use addresses 0x3510 - 0x3517
306 0 adapter enable
309 status = mca_read_stored_pos(slot, 2);
310 /* is it enabled ? */
311 if (!(status & STATUS_ENABLED)) {
312 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
313 return;
315 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
316 share with the SCSI driver */
317 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
318 SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
319 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
320 SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
322 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
323 return;
325 if (status & STATUS_ALTERNATE)
326 io_base = ALT_IO_BASE;
327 else
328 io_base = PRIMARY_IO_BASE;
330 /* get the dma arbitration level */
331 dma_arb_level = (status >> 2) & 0xf;
333 /* BA */
334 printk("%s: DMA arbitration level : %d\n",
335 DEVICE_NAME, dma_arb_level);
337 LITE_ON;
338 current_int_handler = ps2esdi_initial_reset_int_handler;
339 reset_ctrl();
340 reset_status = 0;
341 reset_start = jiffies;
342 while (!reset_status) {
343 esdi_timer.expires = 100;
344 esdi_timer.data = 0;
345 esdi_timer.next = esdi_timer.prev = NULL;
346 add_timer(&esdi_timer);
347 sleep_on(&ps2esdi_int);
349 reset_end = jiffies;
350 LITE_OFF;
351 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
352 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
353 (reset_end - reset_start) % HZ);
356 /* Integrated ESDI Disk and Controller has only one drive! */
357 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
358 ps2esdi_drives = 1; /* then we have only one physical disk! */
362 /* finally this part sets up some global data structures etc. */
364 ps2esdi_get_device_cfg();
366 /* some annoyance in the above routine returns TWO drives?
367 Is something else happining in the background?
368 Regaurdless we fix the # of drives again. AJK */
369 /* Integrated ESDI Disk and Controller has only one drive! */
370 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
371 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */
373 current_int_handler = ps2esdi_normal_interrupt_handler;
375 ps2esdi_gendisk.nr_real = ps2esdi_drives;
377 for (i = 0; i < ps2esdi_drives; i++) {
378 ps2esdi[i << 6].nr_sects =
379 ps2esdi_info[i].head *
380 ps2esdi_info[i].sect *
381 ps2esdi_info[i].cyl;
382 ps2esdi_valid[i] = 1;
384 for (i = 0; i < (MAX_HD << 6); i++)
385 ps2esdi_blocksizes[i] = 1024;
386 blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
387 } /* ps2esdi_geninit */
390 __initfunc(static void ps2esdi_get_device_cfg(void))
392 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
394 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
395 current_int_handler = ps2esdi_geometry_int_handler;
396 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
397 cmd_blk[1] = 0;
398 no_int_yet = TRUE;
399 ps2esdi_out_cmd_blk(cmd_blk);
400 if (no_int_yet)
401 sleep_on(&ps2esdi_int);
403 if (ps2esdi_drives > 1) {
404 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
405 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
406 cmd_blk[1] = 0;
407 no_int_yet = TRUE;
408 ps2esdi_out_cmd_blk(cmd_blk);
409 if (no_int_yet)
410 sleep_on(&ps2esdi_int);
411 } /* if second physical drive is present */
412 return;
415 /* strategy routine that handles most of the IO requests */
416 static void do_ps2esdi_request(void)
418 u_int block, count;
419 /* since, this routine is called with interrupts cleared - they
420 must be before it finishes */
421 sti();
423 #if 0
424 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
425 DEVICE_NAME,
426 CURRENT_DEV, MINOR(CURRENT->rq_dev),
427 CURRENT->cmd, CURRENT->sector,
428 CURRENT->nr_sectors, CURRENT->buffer);
429 #endif
431 /* standard macro that ensures that requests are really on the
432 list + sanity checks. */
433 INIT_REQUEST;
435 if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) {
436 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
437 end_request(FAIL);
438 if (CURRENT)
439 do_ps2esdi_request();
440 return;
441 } /* check for above 16Mb dmas */
442 if ((CURRENT_DEV < ps2esdi_drives) &&
443 (CURRENT->sector + CURRENT->nr_sectors <=
444 ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
445 #if 0
446 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
447 DEVICE_NAME,
448 CURRENT_DEV, MINOR(CURRENT->dev),
449 CURRENT->cmd, CURRENT->sector,
450 CURRENT->nr_sectors);
451 #endif
454 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
456 #if 0
457 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
458 #endif
459 count = CURRENT->nr_sectors;
460 switch (CURRENT->cmd) {
461 case READ:
462 ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
463 return;
464 break;
465 case WRITE:
466 ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
467 return;
468 break;
469 default:
470 printk("%s: Unknown command\n", DEVICE_NAME);
471 end_request(FAIL);
472 if (CURRENT)
473 do_ps2esdi_request();
474 break;
475 } /* handle different commands */
477 /* is request is valid */
478 else {
479 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
480 CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
481 end_request(FAIL);
482 if (CURRENT)
483 do_ps2esdi_request();
486 } /* main strategy routine */
488 /* resets the ESDI adapter */
489 static void reset_ctrl(void)
492 u_long expire;
493 u_short status;
495 /* enable interrupts on the controller */
496 status = inb(ESDI_INTRPT);
497 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
498 any interrupt pending... */
499 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
501 /* read the ESDI status port - if the controller is not busy,
502 simply do a soft reset (fast) - otherwise we'll have to do a
503 hard (slow) reset. */
504 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
505 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
506 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
508 /* soft reset */
509 else {
510 /*BA */
511 printk("%s: hard reset...\n", DEVICE_NAME);
512 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
513 expire = jiffies + 200;
514 while (jiffies < expire);
515 outb_p(1, ESDI_CONTROL);
516 } /* hard reset */
519 } /* reset the controller */
521 /* called by the strategy routine to handle read and write requests */
522 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
525 u_short track, head, cylinder, sector;
526 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
528 /* do some relevant arithmatic */
529 CURRENT->current_nr_sectors =
530 (count < (2 * MAX_16BIT / SECT_SIZE)) ? count : (2 * MAX_16BIT / SECT_SIZE);
531 track = block / ps2esdi_info[drive].sect;
532 head = track % ps2esdi_info[drive].head;
533 cylinder = track / ps2esdi_info[drive].head;
534 sector = block % ps2esdi_info[drive].sect;
536 #if 0
537 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
538 #endif
539 /* call the routine that actually fills out a command block */
540 ps2esdi_fill_cmd_block
541 (cmd_blk,
542 (cmd == READ) ? CMD_READ : CMD_WRITE,
543 cylinder, head, sector,
544 CURRENT->current_nr_sectors, drive);
546 /* send the command block to the controller */
547 if (ps2esdi_out_cmd_blk(cmd_blk)) {
548 printk("%s: Controller failed\n", DEVICE_NAME);
549 if ((++CURRENT->errors) < MAX_RETRIES)
550 return do_ps2esdi_request();
551 else {
552 end_request(FAIL);
553 if (CURRENT)
554 do_ps2esdi_request();
557 /* check for failure to put out the command block */
558 else {
559 #if 0
560 printk("%s: waiting for xfer\n", DEVICE_NAME);
561 #endif
562 /* turn disk lights on */
563 LITE_ON;
566 } /* ps2esdi_readwrite */
568 /* fill out the command block */
569 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
570 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
573 cmd_blk[0] = (drive << 5) | cmd;
574 cmd_blk[1] = length;
575 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
576 cmd_blk[3] = (cyl & 0x3E0) >> 5;
578 } /* fill out the command block */
580 /* write a command block to the controller */
581 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
584 int i, j;
585 u_char status;
587 /* enable interrupts */
588 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
590 /* do not write to the controller, if it is busy */
591 for (i = jiffies + ESDI_STAT_TIMEOUT; (i > jiffies) && (inb(ESDI_STATUS) &
592 STATUS_BUSY););
594 #if 0
595 printk("%s: i(1)=%d\n", DEVICE_NAME, i);
596 #endif
598 /* if device is still busy - then just time out */
599 if (inb(ESDI_STATUS) & STATUS_BUSY) {
600 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
601 return ERROR;
602 } /* timeout ??? */
603 /* Set up the attention register in the controller */
604 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
606 #if 0
607 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
608 #endif
610 /* one by one send each word out */
611 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
612 status = inb(ESDI_STATUS);
613 for (j = jiffies + ESDI_STAT_TIMEOUT;
614 (j > jiffies) && (status & STATUS_BUSY) &&
615 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
616 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
617 #if 0
618 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
619 #endif
620 outw(*cmd_blk++, ESDI_CMD_INT);
621 } else {
622 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
623 DEVICE_NAME, status);
624 return ERROR;
626 } /* send all words out */
627 return OK;
628 } /* send out the commands */
631 /* prepare for dma - do all the necessary setup */
632 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
634 u_int tc;
636 buffer=(char *)virt_to_bus(buffer);
638 #if 0
639 printk("ps2esdi: b_wait: %p\n", CURRENT->bh->b_wait);
640 #endif
641 cli();
643 outb(dma_arb_level | DMA_MASK_CHAN, PORT_DMA_FN);
645 outb(dma_arb_level | DMA_WRITE_ADDR, PORT_DMA_FN);
646 outb((u_int) buffer & (u_int) 0xff, PORT_DMA_EX);
647 outb(((u_int) buffer >> 8) & (u_int) 0xff, PORT_DMA_EX);
648 outb(((u_int) buffer >> 16) & (u_int) 0xff, PORT_DMA_EX);
650 outb(dma_arb_level | DMA_WRITE_TC, PORT_DMA_FN);
651 tc = (length * SECT_SIZE / 2) - 1;
652 outb(tc & 0xff, PORT_DMA_EX);
653 outb((tc >> 8) & 0xff, PORT_DMA_EX);
655 outb(dma_arb_level | DMA_WRITE_MODE, PORT_DMA_FN);
656 outb(dma_xmode, PORT_DMA_EX);
658 outb(dma_arb_level | DMA_UNMASK_CHAN, PORT_DMA_FN);
660 sti();
662 } /* prepare for dma */
666 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
667 struct pt_regs *regs)
669 u_int int_ret_code;
671 if (inb(ESDI_STATUS) & STATUS_INTR) {
672 int_ret_code = inb(ESDI_INTRPT);
673 if (current_int_handler) {
674 /* Disable adapter interrupts till processing is finished */
675 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
676 current_int_handler(int_ret_code);
677 } else
678 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
679 } else {
680 return;
684 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
687 switch (int_ret_code & 0xf) {
688 case INT_RESET:
689 /*BA */
690 printk("%s: initial reset completed.\n", DEVICE_NAME);
691 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
692 wake_up(&ps2esdi_int);
693 break;
694 case INT_ATTN_ERROR:
695 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
696 int_ret_code);
697 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
698 break;
699 default:
700 printk("%s: initial reset handler received interrupt: %02X\n",
701 DEVICE_NAME, int_ret_code);
702 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
703 break;
705 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
709 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
711 u_int status, drive_num;
712 unsigned long rba;
713 int i;
715 drive_num = int_ret_code >> 5;
716 switch (int_ret_code & 0xf) {
717 case INT_CMD_COMPLETE:
718 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
719 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
720 printk("%s: timeout reading status word\n", DEVICE_NAME);
721 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
722 break;
724 status = inw(ESDI_STT_INT);
725 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
726 #define REPLY_WORDS 5 /* we already read word 0 */
727 u_short reply[REPLY_WORDS];
729 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
730 /*BA */
731 printk("%s: Device Configuration Status for drive %u\n",
732 DEVICE_NAME, drive_num);
734 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
736 printk
737 ("Config bits: %s%s%s%s%s\n",
738 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
739 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
740 ? "Zero Defect, " : "Defects Present, ",
741 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
742 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
743 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
745 rba = reply[1] | ((unsigned long) reply[2] << 16);
746 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
748 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
749 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
751 if (!ps2esdi_info[drive_num].head) {
752 ps2esdi_info[drive_num].head = 64;
753 ps2esdi_info[drive_num].sect = 32;
754 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
755 ps2esdi_info[drive_num].wpcom = 0;
756 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
757 ps2esdi_info[drive_num].ctl = 8;
758 if (tp720esdi) { /* store the retrieved parameters */
759 ps2esdi_info[0].head = reply[4] & 0Xff;
760 ps2esdi_info[0].sect = reply[4] >> 8;
761 ps2esdi_info[0].cyl = reply[3];
762 ps2esdi_info[0].wpcom = 0;
763 ps2esdi_info[0].lzone = reply[3];
764 } else {
765 ps2esdi_drives++;
768 #ifdef OBSOLETE
769 if (!ps2esdi_info[drive_num].head) {
770 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
771 ps2esdi_info[drive_num].sect = reply[4] >> 8;
772 ps2esdi_info[drive_num].cyl = reply[3];
773 ps2esdi_info[drive_num].wpcom = 0;
774 ps2esdi_info[drive_num].lzone = reply[3];
775 if (tp720esdi) { /* store the retrieved parameters */
776 ps2esdi_info[0].head = reply[4] & 0Xff;
777 ps2esdi_info[0].sect = reply[4] >> 8;
778 ps2esdi_info[0].cyl = reply[3];
779 ps2esdi_info[0].wpcom = 0;
780 ps2esdi_info[0].lzone = reply[3];
781 } else {
782 ps2esdi_drives++;
785 #endif
787 } else
788 printk("%s: failed while getting device config\n", DEVICE_NAME);
789 #undef REPLY_WORDS
790 } else
791 printk("%s: command %02X unknown by geometry handler\n",
792 DEVICE_NAME, status & 0x1f);
794 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
795 break;
797 case INT_ATTN_ERROR:
798 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
799 int_ret_code);
800 printk("%s: Device not available\n", DEVICE_NAME);
801 break;
802 case INT_CMD_ECC:
803 case INT_CMD_RETRY:
804 case INT_CMD_ECC_RETRY:
805 case INT_CMD_WARNING:
806 case INT_CMD_ABORT:
807 case INT_CMD_FAILED:
808 case INT_DMA_ERR:
809 case INT_CMD_BLK_ERR:
810 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
811 dump_cmd_complete_status(int_ret_code);
812 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
813 break;
814 default:
815 printk("%s: Unknown interrupt reason: %02X\n",
816 DEVICE_NAME, int_ret_code & 0xf);
817 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
818 break;
821 wake_up(&ps2esdi_int);
822 no_int_yet = FALSE;
823 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
827 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
829 u_int status;
830 int i;
832 switch (int_ret_code & 0x0f) {
833 case INT_TRANSFER_REQ:
834 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
835 (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16);
836 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
837 break;
839 case INT_ATTN_ERROR:
840 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
841 int_ret_code);
842 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
843 break;
845 case INT_CMD_COMPLETE:
846 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
847 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
848 printk("%s: timeout reading status word\n", DEVICE_NAME);
849 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
850 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
851 if ((++CURRENT->errors) < MAX_RETRIES)
852 do_ps2esdi_request();
853 else {
854 end_request(FAIL);
855 if (CURRENT)
856 do_ps2esdi_request();
858 break;
860 status = inw(ESDI_STT_INT);
861 switch (status & 0x1F) {
862 case (CMD_READ & 0xff):
863 case (CMD_WRITE & 0xff):
864 LITE_OFF;
865 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
866 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
867 #if 0
868 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);
869 #endif
870 ps2esdi_continue_request();
871 break;
872 default:
873 printk("%s: interrupt for unknown command %02X\n",
874 DEVICE_NAME, status & 0x1f);
875 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
876 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
877 break;
879 break;
880 case INT_CMD_ECC:
881 case INT_CMD_RETRY:
882 case INT_CMD_ECC_RETRY:
883 LITE_OFF;
884 dump_cmd_complete_status(int_ret_code);
885 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
886 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
887 ps2esdi_continue_request();
888 break;
889 case INT_CMD_WARNING:
890 case INT_CMD_ABORT:
891 case INT_CMD_FAILED:
892 case INT_DMA_ERR:
893 LITE_OFF;
894 dump_cmd_complete_status(int_ret_code);
895 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
896 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
897 if ((++CURRENT->errors) < MAX_RETRIES)
898 do_ps2esdi_request();
899 else {
900 end_request(FAIL);
901 if (CURRENT)
902 do_ps2esdi_request();
904 break;
906 case INT_CMD_BLK_ERR:
907 dump_cmd_complete_status(int_ret_code);
908 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
909 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
910 end_request(FAIL);
911 if (CURRENT)
912 do_ps2esdi_request();
913 break;
915 case INT_CMD_FORMAT:
916 printk("%s: huh ? Who issued this format command ?\n"
917 ,DEVICE_NAME);
918 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
919 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
920 break;
922 case INT_RESET:
923 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
924 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
925 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
926 break;
928 default:
929 printk("%s: Unknown interrupt reason: %02X\n",
930 DEVICE_NAME, int_ret_code & 0xf);
931 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
932 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
933 break;
936 } /* handle interrupts */
939 static void ps2esdi_continue_request(void)
941 if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
942 CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
943 CURRENT->sector += CURRENT->current_nr_sectors;
944 do_ps2esdi_request();
945 } else {
946 end_request(SUCCES);
947 if (CURRENT)
948 do_ps2esdi_request();
954 static int ps2esdi_read_status_words(int num_words,
955 int max_words,
956 u_short * buffer)
958 int i;
960 for (; max_words && num_words; max_words--, num_words--, buffer++) {
961 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
962 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
963 printk("%s: timeout reading status word\n", DEVICE_NAME);
964 return FAIL;
966 *buffer = inw(ESDI_STT_INT);
968 return SUCCES;
974 static void dump_cmd_complete_status(u_int int_ret_code)
976 #define WAIT_FOR_STATUS \
977 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
978 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
979 printk("%s: timeout reading status word\n",DEVICE_NAME); \
980 return; \
983 int i, word_count;
984 u_short stat_word;
985 u_long rba;
987 printk("%s: Device: %u, interrupt ID: %02X\n",
988 DEVICE_NAME, int_ret_code >> 5,
989 int_ret_code & 0xf);
991 WAIT_FOR_STATUS;
992 stat_word = inw(ESDI_STT_INT);
993 word_count = (stat_word >> 8) - 1;
994 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
995 stat_word & 0xff);
997 if (word_count--) {
998 WAIT_FOR_STATUS;
999 stat_word = inw(ESDI_STT_INT);
1000 printk("%s: command status code: %02X, command error code: %02X\n",
1001 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1003 if (word_count--) {
1004 WAIT_FOR_STATUS;
1005 stat_word = inw(ESDI_STT_INT);
1006 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1007 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1008 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1009 (stat_word & 0x0400) ? "Write Fault, " : "",
1010 (stat_word & 0x0200) ? "Track 0, " : "",
1011 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1012 stat_word >> 8);
1014 if (word_count--) {
1015 WAIT_FOR_STATUS;
1016 stat_word = inw(ESDI_STT_INT);
1017 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1019 if (word_count -= 2) {
1020 WAIT_FOR_STATUS;
1021 rba = inw(ESDI_STT_INT);
1022 WAIT_FOR_STATUS;
1023 rba |= inw(ESDI_STT_INT) << 16;
1024 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1025 (u_short) ((rba & 0x1ff80000) >> 11),
1026 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1027 } else
1028 printk("\n");
1030 if (word_count--) {
1031 WAIT_FOR_STATUS;
1032 stat_word = inw(ESDI_STT_INT);
1033 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1035 printk("\n");
1037 #undef WAIT_FOR_STATUS
1042 static int ps2esdi_open(struct inode *inode, struct file *file)
1044 int dev = DEVICE_NR(inode->i_rdev);
1046 if (dev < ps2esdi_drives) {
1047 while (!ps2esdi_valid[dev])
1048 sleep_on(&ps2esdi_wait_open);
1050 access_count[dev]++;
1052 return (0);
1053 } else
1054 return (-ENODEV);
1059 static int ps2esdi_release(struct inode *inode, struct file *file)
1061 int dev = DEVICE_NR(inode->i_rdev);
1063 if (dev < ps2esdi_drives) {
1064 sync_dev(inode->i_rdev);
1065 access_count[dev]--;
1067 return 0;
1072 static int ps2esdi_ioctl(struct inode *inode,
1073 struct file *file, u_int cmd, u_long arg)
1076 struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1077 int dev = DEVICE_NR(inode->i_rdev), err;
1079 if (inode && (dev < ps2esdi_drives))
1080 switch (cmd) {
1081 case HDIO_GETGEO:
1082 if (arg) {
1083 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1084 return (err);
1085 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1086 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1087 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1088 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1089 (long *) &geometry->start);
1091 return (0);
1093 break;
1094 case BLKRASET:
1095 if (!capable(CAP_SYS_ADMIN))
1096 return -EACCES;
1097 if (!inode->i_rdev)
1098 return -EINVAL;
1099 if (arg > 0xff)
1100 return -EINVAL;
1101 read_ahead[MAJOR(inode->i_rdev)] = arg;
1102 return 0;
1103 case BLKGETSIZE:
1104 if (arg) {
1105 if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
1106 return (err);
1107 put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
1109 return (0);
1111 break;
1112 case BLKFLSBUF:
1113 if (!capable(CAP_SYS_ADMIN))
1114 return -EACCES;
1115 if (!inode->i_rdev)
1116 return -EINVAL;
1117 fsync_dev(inode->i_rdev);
1118 invalidate_buffers(inode->i_rdev);
1119 return 0;
1121 case BLKRRPART:
1122 if (!capable(CAP_SYS_ADMIN))
1123 return -EACCES;
1124 return (ps2esdi_reread_partitions(inode->i_rdev));
1125 RO_IOCTLS(inode->i_rdev, arg);
1127 return (-EINVAL);
1132 static int ps2esdi_reread_partitions(kdev_t dev)
1134 int target = DEVICE_NR(dev);
1135 int start = target << ps2esdi_gendisk.minor_shift;
1136 int partition;
1138 cli();
1139 ps2esdi_valid[target] = (access_count[target] != 1);
1140 sti();
1141 if (ps2esdi_valid[target])
1142 return (-EBUSY);
1144 for (partition = ps2esdi_gendisk.max_p - 1;
1145 partition >= 0; partition--) {
1146 int minor = (start | partition);
1147 kdev_t devp = MKDEV(MAJOR_NR, minor);
1148 struct super_block * sb = get_super(devp);
1150 sync_dev(devp);
1151 if (sb)
1152 invalidate_inodes(sb);
1153 invalidate_buffers(devp);
1154 ps2esdi_gendisk.part[start + partition].start_sect = 0;
1155 ps2esdi_gendisk.part[start + partition].nr_sects = 0;
1158 ps2esdi_gendisk.part[start].nr_sects = ps2esdi_info[target].head *
1159 ps2esdi_info[target].cyl * ps2esdi_info[target].sect;
1160 resetup_one_dev(&ps2esdi_gendisk, target);
1162 ps2esdi_valid[target] = 1;
1163 wake_up(&ps2esdi_wait_open);
1165 return (0);
1168 void ps2esdi_reset_timer(unsigned long unused)
1171 int status;
1173 status = inb(ESDI_INTRPT);
1174 if ((status & 0xf) == INT_RESET) {
1175 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1176 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1177 reset_status = 1;
1179 wake_up(&ps2esdi_int);
1182 #endif