Import 2.3.46pre5
[davej-history.git] / drivers / block / ps2esdi.c
blob305c89a0039b86cab4b6eadaa2434b6ad028fbf6
1 /* ps2esdi driver based on assembler code by Arindam Banerji,
2 written by Peter De Schrijver */
3 /* Reassuring note to IBM : This driver was NOT developed by vice-versa
4 engineering the PS/2's BIOS */
5 /* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those
6 other lovely fish out there... */
7 /* This code was written during the long and boring WINA
8 elections 1994 */
9 /* Thanks to Arindam Banerij for giving me the source of his driver */
10 /* This code may be freely distributed and modified in any way,
11 as long as these notes remain intact */
13 /* Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */
14 /* Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be)
15 Thanks to Arindam Banerij for sending me the docs of the adapter */
17 /* BA Modified for ThinkPad 720 by Boris Ashkinazi */
18 /* (bash@vnet.ibm.com) 08/08/95 */
20 /* Modified further for ThinkPad-720C by Uri Blumenthal */
21 /* (uri@watson.ibm.com) Sep 11, 1995 */
23 /* TODO :
24 + Timeouts
25 + Get disk parameters
26 + DMA above 16MB
27 + reset after read/write error
30 #include <linux/config.h>
31 #include <linux/major.h>
33 #ifdef CONFIG_BLK_DEV_PS2
35 #define MAJOR_NR PS2ESDI_MAJOR
37 #include <linux/errno.h>
38 #include <linux/sched.h>
39 #include <linux/mm.h>
40 #include <linux/fs.h>
41 #include <linux/kernel.h>
42 #include <linux/genhd.h>
43 #include <linux/ps2esdi.h>
44 #include <linux/devfs_fs_kernel.h>
45 #include <linux/blk.h>
46 #include <linux/blkpg.h>
47 #include <linux/mca.h>
48 #include <linux/init.h>
49 #include <linux/ioport.h>
51 #include <asm/system.h>
52 #include <asm/io.h>
53 #include <asm/segment.h>
54 #include <asm/dma.h>
55 #include <asm/uaccess.h>
57 #define PS2ESDI_IRQ 14
58 #define MAX_HD 1
59 #define MAX_RETRIES 5
60 #define MAX_16BIT 65536
61 #define ESDI_TIMEOUT 0xf000
62 #define ESDI_STAT_TIMEOUT 4
64 #define TYPE_0_CMD_BLK_LENGTH 2
65 #define TYPE_1_CMD_BLK_LENGTH 4
68 static void reset_ctrl(void);
70 int ps2esdi_init(void);
72 static void ps2esdi_geninit(void);
74 static void do_ps2esdi_request(request_queue_t * q);
76 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count);
78 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
79 u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
81 static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
83 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
85 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
86 struct pt_regs *regs);
87 static void (*current_int_handler) (u_int) = NULL;
88 static void ps2esdi_normal_interrupt_handler(u_int);
89 static void ps2esdi_initial_reset_int_handler(u_int);
90 static void ps2esdi_geometry_int_handler(u_int);
92 static void ps2esdi_continue_request(void);
94 static int ps2esdi_open(struct inode *inode, struct file *file);
96 static int ps2esdi_release(struct inode *inode, struct file *file);
98 static int ps2esdi_ioctl(struct inode *inode, struct file *file,
99 u_int cmd, u_long arg);
101 static int ps2esdi_reread_partitions(kdev_t dev);
103 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
105 static void dump_cmd_complete_status(u_int int_ret_code);
107 static void ps2esdi_get_device_cfg(void);
109 void ps2esdi_reset_timer(unsigned long unused);
111 u_int dma_arb_level; /* DMA arbitration level */
113 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
114 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
116 int no_int_yet;
117 static int access_count[MAX_HD] = {0,};
118 static char ps2esdi_valid[MAX_HD] = {0,};
119 static int ps2esdi_sizes[MAX_HD << 6] = {0,};
120 static int ps2esdi_blocksizes[MAX_HD << 6] = {0,};
121 static int ps2esdi_drives = 0;
122 static struct hd_struct ps2esdi[MAX_HD << 6];
123 static u_short io_base;
124 static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer};
125 static int reset_status;
126 static int ps2esdi_slot = -1;
127 int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */
128 int intg_esdi = 0; /* If integrated adapter */
129 struct ps2esdi_i_struct {
130 unsigned int head, sect, cyl, wpcom, lzone, ctl;
133 #if 0
134 #if 0 /* try both - I don't know which one is better... UB */
135 struct ps2esdi_i_struct ps2esdi_info[] =
137 {4, 48, 1553, 0, 0, 0},
138 {0, 0, 0, 0, 0, 0}};
139 #else
140 struct ps2esdi_i_struct ps2esdi_info[] =
142 {64, 32, 161, 0, 0, 0},
143 {0, 0, 0, 0, 0, 0}};
144 #endif
145 #endif
146 struct ps2esdi_i_struct ps2esdi_info[] =
148 {0, 0, 0, 0, 0, 0},
149 {0, 0, 0, 0, 0, 0}};
151 static struct block_device_operations ps2esdi_fops =
153 open: ps2esdi_open,
154 release: ps2esdi_release,
155 ioctl: ps2esdi_ioctl,
158 static struct gendisk ps2esdi_gendisk =
160 MAJOR_NR, /* Major number */
161 "ed", /* Major name */
162 6, /* Bits to shift to get real from partition */
163 1 << 6, /* Number of partitions per real disk */
164 ps2esdi, /* hd struct */
165 ps2esdi_sizes, /* block sizes */
166 0, /* number */
167 (void *) ps2esdi_info, /* internal */
168 NULL, /* next */
169 &ps2esdi_fops, /* file operations */
172 /* initialization routine called by ll_rw_blk.c */
173 int __init ps2esdi_init(void)
176 /* register the device - pass the name, major number and operations
177 vector . */
178 if (devfs_register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
179 printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR);
180 return -1;
182 /* set up some global information - indicating device specific info */
183 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
184 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
186 /* some minor housekeeping - setup the global gendisk structure */
187 ps2esdi_gendisk.next = gendisk_head;
188 gendisk_head = &ps2esdi_gendisk;
189 ps2esdi_geninit();
190 return 0;
191 } /* ps2esdi_init */
193 #ifdef MODULE
195 int cyl[2] = {-1,-1};
196 int head[2] = {-1, -1};
197 int sect[2] = {-1, -1};
199 MODULE_PARM(tp720esdi, "i");
200 MODULE_PARM(cyl, "i");
201 MODULE_PARM(head, "i");
202 MODULE_PARM(track, "i");
204 int init_module(void) {
205 int drive;
207 for(drive = 0; drive <= 1; drive++) {
208 struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
210 if (cyl[drive] != -1) {
211 info->cyl = info->lzone = cyl[drive];
212 info->wpcom = 0;
214 if (head[drive] != -1) {
215 info->head = head[drive];
216 info->ctl = (head[drive] > 8 ? 8 : 0);
218 if (sect[drive] != -1) info->sect = sect[drive];
220 return ps2esdi_init();
223 void
224 cleanup_module(void)
226 if(ps2esdi_slot)
228 mca_mark_as_unused(ps2esdi_slot);
229 mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
231 release_region(io_base, 4);
232 free_dma(dma_arb_level);
233 free_irq(PS2ESDI_IRQ, NULL)
234 devfs_unregister_blkdev(MAJOR_NR, "ed");
236 #endif /* MODULE */
238 /* handles boot time command line parameters */
239 void __init tp720_setup(char *str, int *ints)
241 /* no params, just sets the tp720esdi flag if it exists */
243 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
244 tp720esdi = 1;
247 void __init ed_setup(char *str, int *ints)
249 int hdind = 0;
251 /* handles 3 parameters only - corresponding to
252 1. Number of cylinders
253 2. Number of heads
254 3. Sectors/track
257 if (ints[0] != 3)
258 return;
260 /* print out the information - seen at boot time */
261 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
262 DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
264 /* set the index into device specific information table */
265 if (ps2esdi_info[0].head != 0)
266 hdind = 1;
268 /* set up all the device information */
269 ps2esdi_info[hdind].head = ints[2];
270 ps2esdi_info[hdind].sect = ints[3];
271 ps2esdi_info[hdind].cyl = ints[1];
272 ps2esdi_info[hdind].wpcom = 0;
273 ps2esdi_info[hdind].lzone = ints[1];
274 ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
275 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
276 ps2esdi_drives = hdind + 1; /* increment index for the next time */
277 #endif
278 } /* ed_setup */
280 static int ps2esdi_getinfo(char *buf, int slot, void *d)
282 int len = 0;
284 len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
285 dma_arb_level);
286 len += sprintf(buf + len, "IO Port: %x\n", io_base);
287 len += sprintf(buf + len, "IRQ: 14\n");
288 len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
290 return len;
293 /* ps2 esdi specific initialization - called thru the gendisk chain */
294 static void __init ps2esdi_geninit(void)
297 The first part contains the initialization code
298 for the ESDI disk subsystem. All we really do
299 is search for the POS registers of the controller
300 to do some simple setup operations. First, we
301 must ensure that the controller is installed,
302 enabled, and configured as PRIMARY. Then we must
303 determine the DMA arbitration level being used by
304 the controller so we can handle data transfer
305 operations properly. If all of this works, then
306 we will set the INIT_FLAG to a non-zero value.
309 int slot = 0, i, reset_start, reset_end;
310 u_char status;
311 unsigned short adapterID;
313 if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
314 adapterID = INTG_ESDI_ID;
315 printk("%s: integrated ESDI adapter found in slot %d\n",
316 DEVICE_NAME, slot+1);
317 #ifndef MODULE
318 mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
319 #endif
320 } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
321 adapterID = NRML_ESDI_ID;
322 printk("%s: normal ESDI adapter found in slot %d\n",
323 DEVICE_NAME, slot+1);
324 mca_set_adapter_name(slot, "PS/2 ESDI");
325 } else {
326 return;
329 ps2esdi_slot = slot;
330 mca_mark_as_used(slot);
331 mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
333 /* Found the slot - read the POS register 2 to get the necessary
334 configuration and status information. POS register 2 has the
335 following information :
336 Bit Function
337 7 reserved = 0
338 6 arbitration method
339 0 - fairness enabled
340 1 - fairness disabled, linear priority assignment
341 5-2 arbitration level
342 1 alternate address
343 1 alternate address
344 0 - use addresses 0x3510 - 0x3517
345 0 adapter enable
348 status = mca_read_stored_pos(slot, 2);
349 /* is it enabled ? */
350 if (!(status & STATUS_ENABLED)) {
351 printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
352 return;
354 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
355 share with the SCSI driver */
356 if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
357 SA_INTERRUPT | SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
358 && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
359 SA_SHIRQ, "PS/2 ESDI", &ps2esdi_gendisk)
361 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
362 return;
364 if (status & STATUS_ALTERNATE)
365 io_base = ALT_IO_BASE;
366 else
367 io_base = PRIMARY_IO_BASE;
369 /* get the dma arbitration level */
370 dma_arb_level = (status >> 2) & 0xf;
372 /* BA */
373 printk("%s: DMA arbitration level : %d\n",
374 DEVICE_NAME, dma_arb_level);
376 LITE_ON;
377 current_int_handler = ps2esdi_initial_reset_int_handler;
378 reset_ctrl();
379 reset_status = 0;
380 reset_start = jiffies;
381 while (!reset_status) {
382 esdi_timer.expires = HZ;
383 esdi_timer.data = 0;
384 esdi_timer.next = esdi_timer.prev = NULL;
385 add_timer(&esdi_timer);
386 sleep_on(&ps2esdi_int);
388 reset_end = jiffies;
389 LITE_OFF;
390 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
391 DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
392 (reset_end - reset_start) % HZ);
395 /* Integrated ESDI Disk and Controller has only one drive! */
396 if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
397 ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1;
402 /* finally this part sets up some global data structures etc. */
404 ps2esdi_get_device_cfg();
406 /* some annoyance in the above routine returns TWO drives?
407 Is something else happining in the background?
408 Regaurdless we fix the # of drives again. AJK */
409 /* Integrated ESDI Disk and Controller has only one drive! */
410 if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */
411 ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */
413 current_int_handler = ps2esdi_normal_interrupt_handler;
415 ps2esdi_gendisk.nr_real = ps2esdi_drives;
417 for (i = 0; i < (MAX_HD << 6); i++)
418 ps2esdi_blocksizes[i] = 1024;
420 request_dma(dma_arb_level, "ed");
421 request_region(io_base, 4, "ed");
422 blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
424 for (i = 0; i < ps2esdi_drives; i++) {
425 register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6,
426 &ps2esdi_fops,
427 ps2esdi_info[i].head * ps2esdi_info[i].sect *
428 ps2esdi_info[i].cyl);
429 ps2esdi_valid[i] = 1;
433 static void __init ps2esdi_get_device_cfg(void)
435 u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
437 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
438 current_int_handler = ps2esdi_geometry_int_handler;
439 cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
440 cmd_blk[1] = 0;
441 no_int_yet = TRUE;
442 ps2esdi_out_cmd_blk(cmd_blk);
443 if (no_int_yet)
444 sleep_on(&ps2esdi_int);
446 if (ps2esdi_drives > 1) {
447 printk("%s: Drive 1\n", DEVICE_NAME); /*BA */
448 cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
449 cmd_blk[1] = 0;
450 no_int_yet = TRUE;
451 ps2esdi_out_cmd_blk(cmd_blk);
452 if (no_int_yet)
453 sleep_on(&ps2esdi_int);
454 } /* if second physical drive is present */
455 return;
458 /* strategy routine that handles most of the IO requests */
459 static void do_ps2esdi_request(request_queue_t * q)
461 u_int block, count;
462 /* since, this routine is called with interrupts cleared - they
463 must be before it finishes */
464 sti();
466 #if 0
467 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
468 DEVICE_NAME,
469 CURRENT_DEV, MINOR(CURRENT->rq_dev),
470 CURRENT->cmd, CURRENT->sector,
471 CURRENT->nr_sectors, CURRENT->buffer);
472 #endif
474 /* standard macro that ensures that requests are really on the
475 list + sanity checks. */
476 INIT_REQUEST;
478 if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) {
479 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
480 end_request(FAIL);
481 if (!QUEUE_EMPTY)
482 do_ps2esdi_request(q);
483 return;
484 } /* check for above 16Mb dmas */
485 if ((CURRENT_DEV < ps2esdi_drives) &&
486 (CURRENT->sector + CURRENT->nr_sectors <=
487 ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
488 #if 0
489 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
490 DEVICE_NAME,
491 CURRENT_DEV, MINOR(CURRENT->dev),
492 CURRENT->cmd, CURRENT->sector,
493 CURRENT->nr_sectors);
494 #endif
497 block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
499 #if 0
500 printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
501 #endif
502 count = CURRENT->nr_sectors;
503 switch (CURRENT->cmd) {
504 case READ:
505 ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
506 return;
507 break;
508 case WRITE:
509 ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
510 return;
511 break;
512 default:
513 printk("%s: Unknown command\n", DEVICE_NAME);
514 end_request(FAIL);
515 if (!QUEUE_EMPTY)
516 do_ps2esdi_request(q);
517 break;
518 } /* handle different commands */
520 /* is request is valid */
521 else {
522 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
523 CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
524 end_request(FAIL);
525 if (!QUEUE_EMPTY)
526 do_ps2esdi_request(q);
529 } /* main strategy routine */
531 /* resets the ESDI adapter */
532 static void reset_ctrl(void)
535 u_long expire;
536 u_short status;
538 /* enable interrupts on the controller */
539 status = inb(ESDI_INTRPT);
540 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have
541 any interrupt pending... */
542 outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
544 /* read the ESDI status port - if the controller is not busy,
545 simply do a soft reset (fast) - otherwise we'll have to do a
546 hard (slow) reset. */
547 if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
548 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
549 outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
551 /* soft reset */
552 else {
553 /*BA */
554 printk("%s: hard reset...\n", DEVICE_NAME);
555 outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
556 expire = jiffies + 2*HZ;
557 while (time_before(jiffies, expire));
558 outb_p(1, ESDI_CONTROL);
559 } /* hard reset */
562 } /* reset the controller */
564 /* called by the strategy routine to handle read and write requests */
565 static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
568 u_short track, head, cylinder, sector;
569 u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
571 /* do some relevant arithmatic */
572 CURRENT->current_nr_sectors =
573 (count < (2 * MAX_16BIT / SECT_SIZE)) ? count : (2 * MAX_16BIT / SECT_SIZE);
574 track = block / ps2esdi_info[drive].sect;
575 head = track % ps2esdi_info[drive].head;
576 cylinder = track / ps2esdi_info[drive].head;
577 sector = block % ps2esdi_info[drive].sect;
579 #if 0
580 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
581 #endif
582 /* call the routine that actually fills out a command block */
583 ps2esdi_fill_cmd_block
584 (cmd_blk,
585 (cmd == READ) ? CMD_READ : CMD_WRITE,
586 cylinder, head, sector,
587 CURRENT->current_nr_sectors, drive);
589 /* send the command block to the controller */
590 if (ps2esdi_out_cmd_blk(cmd_blk)) {
591 printk("%s: Controller failed\n", DEVICE_NAME);
592 if ((++CURRENT->errors) < MAX_RETRIES)
593 return do_ps2esdi_request(NULL);
594 else {
595 end_request(FAIL);
596 if (!QUEUE_EMPTY)
597 do_ps2esdi_request(NULL);
600 /* check for failure to put out the command block */
601 else {
602 #if 0
603 printk("%s: waiting for xfer\n", DEVICE_NAME);
604 #endif
605 /* turn disk lights on */
606 LITE_ON;
609 } /* ps2esdi_readwrite */
611 /* fill out the command block */
612 static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
613 u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
616 cmd_blk[0] = (drive << 5) | cmd;
617 cmd_blk[1] = length;
618 cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
619 cmd_blk[3] = (cyl & 0x3E0) >> 5;
621 } /* fill out the command block */
623 /* write a command block to the controller */
624 static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
627 int i, j;
628 u_char status;
630 /* enable interrupts */
631 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
633 /* do not write to the controller, if it is busy */
634 for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
635 STATUS_BUSY););
637 #if 0
638 printk("%s: i(1)=%d\n", DEVICE_NAME, i);
639 #endif
641 /* if device is still busy - then just time out */
642 if (inb(ESDI_STATUS) & STATUS_BUSY) {
643 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
644 return ERROR;
645 } /* timeout ??? */
646 /* Set up the attention register in the controller */
647 outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
649 #if 0
650 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
651 #endif
653 /* one by one send each word out */
654 for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
655 status = inb(ESDI_STATUS);
656 for (j = jiffies + ESDI_STAT_TIMEOUT;
657 time_after(j, jiffies) && (status & STATUS_BUSY) &&
658 (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
659 if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
660 #if 0
661 printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
662 #endif
663 outw(*cmd_blk++, ESDI_CMD_INT);
664 } else {
665 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
666 DEVICE_NAME, status);
667 return ERROR;
669 } /* send all words out */
670 return OK;
671 } /* send out the commands */
674 /* prepare for dma - do all the necessary setup */
675 static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
677 u_int tc;
679 buffer=(char *)virt_to_bus(buffer);
681 #if 0
682 printk("ps2esdi: b_wait: %p\n", CURRENT->bh->b_wait);
683 #endif
684 cli();
686 outb(dma_arb_level | DMA_MASK_CHAN, PORT_DMA_FN);
688 outb(dma_arb_level | DMA_WRITE_ADDR, PORT_DMA_FN);
689 outb((u_int) buffer & (u_int) 0xff, PORT_DMA_EX);
690 outb(((u_int) buffer >> 8) & (u_int) 0xff, PORT_DMA_EX);
691 outb(((u_int) buffer >> 16) & (u_int) 0xff, PORT_DMA_EX);
693 outb(dma_arb_level | DMA_WRITE_TC, PORT_DMA_FN);
694 tc = (length * SECT_SIZE / 2) - 1;
695 outb(tc & 0xff, PORT_DMA_EX);
696 outb((tc >> 8) & 0xff, PORT_DMA_EX);
698 outb(dma_arb_level | DMA_WRITE_MODE, PORT_DMA_FN);
699 outb(dma_xmode, PORT_DMA_EX);
701 outb(dma_arb_level | DMA_UNMASK_CHAN, PORT_DMA_FN);
703 sti();
705 } /* prepare for dma */
709 static void ps2esdi_interrupt_handler(int irq, void *dev_id,
710 struct pt_regs *regs)
712 u_int int_ret_code;
714 if (inb(ESDI_STATUS) & STATUS_INTR) {
715 int_ret_code = inb(ESDI_INTRPT);
716 if (current_int_handler) {
717 /* Disable adapter interrupts till processing is finished */
718 outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
719 current_int_handler(int_ret_code);
720 } else
721 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
722 } else {
723 return;
727 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
730 switch (int_ret_code & 0xf) {
731 case INT_RESET:
732 /*BA */
733 printk("%s: initial reset completed.\n", DEVICE_NAME);
734 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
735 wake_up(&ps2esdi_int);
736 break;
737 case INT_ATTN_ERROR:
738 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
739 int_ret_code);
740 printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
741 break;
742 default:
743 printk("%s: initial reset handler received interrupt: %02X\n",
744 DEVICE_NAME, int_ret_code);
745 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
746 break;
748 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
752 static void ps2esdi_geometry_int_handler(u_int int_ret_code)
754 u_int status, drive_num;
755 unsigned long rba;
756 int i;
758 drive_num = int_ret_code >> 5;
759 switch (int_ret_code & 0xf) {
760 case INT_CMD_COMPLETE:
761 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
762 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
763 printk("%s: timeout reading status word\n", DEVICE_NAME);
764 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
765 break;
767 status = inw(ESDI_STT_INT);
768 if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
769 #define REPLY_WORDS 5 /* we already read word 0 */
770 u_short reply[REPLY_WORDS];
772 if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
773 /*BA */
774 printk("%s: Device Configuration Status for drive %u\n",
775 DEVICE_NAME, drive_num);
777 printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
779 printk
780 ("Config bits: %s%s%s%s%s\n",
781 (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
782 ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
783 ? "Zero Defect, " : "Defects Present, ",
784 (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
785 (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
786 (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
788 rba = reply[1] | ((unsigned long) reply[2] << 16);
789 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
791 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
792 DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
794 if (!ps2esdi_info[drive_num].head) {
795 ps2esdi_info[drive_num].head = 64;
796 ps2esdi_info[drive_num].sect = 32;
797 ps2esdi_info[drive_num].cyl = rba / (64 * 32);
798 ps2esdi_info[drive_num].wpcom = 0;
799 ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
800 ps2esdi_info[drive_num].ctl = 8;
801 if (tp720esdi) { /* store the retrieved parameters */
802 ps2esdi_info[0].head = reply[4] & 0Xff;
803 ps2esdi_info[0].sect = reply[4] >> 8;
804 ps2esdi_info[0].cyl = reply[3];
805 ps2esdi_info[0].wpcom = 0;
806 ps2esdi_info[0].lzone = reply[3];
807 } else {
808 if (!intg_esdi)
809 ps2esdi_drives++;
812 #ifdef OBSOLETE
813 if (!ps2esdi_info[drive_num].head) {
814 ps2esdi_info[drive_num].head = reply[4] & 0Xff;
815 ps2esdi_info[drive_num].sect = reply[4] >> 8;
816 ps2esdi_info[drive_num].cyl = reply[3];
817 ps2esdi_info[drive_num].wpcom = 0;
818 ps2esdi_info[drive_num].lzone = reply[3];
819 if (tp720esdi) { /* store the retrieved parameters */
820 ps2esdi_info[0].head = reply[4] & 0Xff;
821 ps2esdi_info[0].sect = reply[4] >> 8;
822 ps2esdi_info[0].cyl = reply[3];
823 ps2esdi_info[0].wpcom = 0;
824 ps2esdi_info[0].lzone = reply[3];
825 } else {
826 ps2esdi_drives++;
829 #endif
831 } else
832 printk("%s: failed while getting device config\n", DEVICE_NAME);
833 #undef REPLY_WORDS
834 } else
835 printk("%s: command %02X unknown by geometry handler\n",
836 DEVICE_NAME, status & 0x1f);
838 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
839 break;
841 case INT_ATTN_ERROR:
842 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
843 int_ret_code);
844 printk("%s: Device not available\n", DEVICE_NAME);
845 break;
846 case INT_CMD_ECC:
847 case INT_CMD_RETRY:
848 case INT_CMD_ECC_RETRY:
849 case INT_CMD_WARNING:
850 case INT_CMD_ABORT:
851 case INT_CMD_FAILED:
852 case INT_DMA_ERR:
853 case INT_CMD_BLK_ERR:
854 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
855 dump_cmd_complete_status(int_ret_code);
856 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
857 break;
858 default:
859 printk("%s: Unknown interrupt reason: %02X\n",
860 DEVICE_NAME, int_ret_code & 0xf);
861 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
862 break;
865 wake_up(&ps2esdi_int);
866 no_int_yet = FALSE;
867 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
871 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
873 u_int status;
874 int i;
876 switch (int_ret_code & 0x0f) {
877 case INT_TRANSFER_REQ:
878 ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
879 (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16);
880 outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
881 break;
883 case INT_ATTN_ERROR:
884 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
885 int_ret_code);
886 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
887 break;
889 case INT_CMD_COMPLETE:
890 for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
891 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
892 printk("%s: timeout reading status word\n", DEVICE_NAME);
893 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
894 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
895 if ((++CURRENT->errors) < MAX_RETRIES)
896 do_ps2esdi_request(NULL);
897 else {
898 end_request(FAIL);
899 if (!QUEUE_EMPTY)
900 do_ps2esdi_request(NULL);
902 break;
904 status = inw(ESDI_STT_INT);
905 switch (status & 0x1F) {
906 case (CMD_READ & 0xff):
907 case (CMD_WRITE & 0xff):
908 LITE_OFF;
909 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
910 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
911 #if 0
912 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);
913 #endif
914 ps2esdi_continue_request();
915 break;
916 default:
917 printk("%s: interrupt for unknown command %02X\n",
918 DEVICE_NAME, status & 0x1f);
919 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
920 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
921 break;
923 break;
924 case INT_CMD_ECC:
925 case INT_CMD_RETRY:
926 case INT_CMD_ECC_RETRY:
927 LITE_OFF;
928 dump_cmd_complete_status(int_ret_code);
929 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
930 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
931 ps2esdi_continue_request();
932 break;
933 case INT_CMD_WARNING:
934 case INT_CMD_ABORT:
935 case INT_CMD_FAILED:
936 case INT_DMA_ERR:
937 LITE_OFF;
938 dump_cmd_complete_status(int_ret_code);
939 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
940 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
941 if ((++CURRENT->errors) < MAX_RETRIES)
942 do_ps2esdi_request(NULL);
943 else {
944 end_request(FAIL);
945 if (!QUEUE_EMPTY)
946 do_ps2esdi_request(NULL);
948 break;
950 case INT_CMD_BLK_ERR:
951 dump_cmd_complete_status(int_ret_code);
952 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
953 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
954 end_request(FAIL);
955 if (!QUEUE_EMPTY)
956 do_ps2esdi_request(NULL);
957 break;
959 case INT_CMD_FORMAT:
960 printk("%s: huh ? Who issued this format command ?\n"
961 ,DEVICE_NAME);
962 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
963 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
964 break;
966 case INT_RESET:
967 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
968 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
969 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
970 break;
972 default:
973 printk("%s: Unknown interrupt reason: %02X\n",
974 DEVICE_NAME, int_ret_code & 0xf);
975 outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
976 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
977 break;
980 } /* handle interrupts */
983 static void ps2esdi_continue_request(void)
985 if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
986 CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
987 CURRENT->sector += CURRENT->current_nr_sectors;
988 do_ps2esdi_request(NULL);
989 } else {
990 end_request(SUCCES);
991 if (!QUEUE_EMPTY)
992 do_ps2esdi_request(NULL);
998 static int ps2esdi_read_status_words(int num_words,
999 int max_words,
1000 u_short * buffer)
1002 int i;
1004 for (; max_words && num_words; max_words--, num_words--, buffer++) {
1005 for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
1006 if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
1007 printk("%s: timeout reading status word\n", DEVICE_NAME);
1008 return FAIL;
1010 *buffer = inw(ESDI_STT_INT);
1012 return SUCCES;
1018 static void dump_cmd_complete_status(u_int int_ret_code)
1020 #define WAIT_FOR_STATUS \
1021 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
1022 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
1023 printk("%s: timeout reading status word\n",DEVICE_NAME); \
1024 return; \
1027 int i, word_count;
1028 u_short stat_word;
1029 u_long rba;
1031 printk("%s: Device: %u, interrupt ID: %02X\n",
1032 DEVICE_NAME, int_ret_code >> 5,
1033 int_ret_code & 0xf);
1035 WAIT_FOR_STATUS;
1036 stat_word = inw(ESDI_STT_INT);
1037 word_count = (stat_word >> 8) - 1;
1038 printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
1039 stat_word & 0xff);
1041 if (word_count--) {
1042 WAIT_FOR_STATUS;
1043 stat_word = inw(ESDI_STT_INT);
1044 printk("%s: command status code: %02X, command error code: %02X\n",
1045 DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
1047 if (word_count--) {
1048 WAIT_FOR_STATUS;
1049 stat_word = inw(ESDI_STT_INT);
1050 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
1051 (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
1052 (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
1053 (stat_word & 0x0400) ? "Write Fault, " : "",
1054 (stat_word & 0x0200) ? "Track 0, " : "",
1055 (stat_word & 0x0100) ? "Seek or command complete, " : "",
1056 stat_word >> 8);
1058 if (word_count--) {
1059 WAIT_FOR_STATUS;
1060 stat_word = inw(ESDI_STT_INT);
1061 printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
1063 if (word_count -= 2) {
1064 WAIT_FOR_STATUS;
1065 rba = inw(ESDI_STT_INT);
1066 WAIT_FOR_STATUS;
1067 rba |= inw(ESDI_STT_INT) << 16;
1068 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1069 (u_short) ((rba & 0x1ff80000) >> 11),
1070 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
1071 } else
1072 printk("\n");
1074 if (word_count--) {
1075 WAIT_FOR_STATUS;
1076 stat_word = inw(ESDI_STT_INT);
1077 printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
1079 printk("\n");
1081 #undef WAIT_FOR_STATUS
1086 static int ps2esdi_open(struct inode *inode, struct file *file)
1088 int dev = DEVICE_NR(inode->i_rdev);
1090 if (dev < ps2esdi_drives) {
1091 while (!ps2esdi_valid[dev])
1092 sleep_on(&ps2esdi_wait_open);
1094 access_count[dev]++;
1096 return (0);
1097 } else
1098 return (-ENODEV);
1103 static int ps2esdi_release(struct inode *inode, struct file *file)
1105 int dev = DEVICE_NR(inode->i_rdev);
1107 if (dev < ps2esdi_drives) {
1108 access_count[dev]--;
1110 return 0;
1115 static int ps2esdi_ioctl(struct inode *inode,
1116 struct file *file, u_int cmd, u_long arg)
1119 struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
1120 int dev = DEVICE_NR(inode->i_rdev), err;
1122 if (inode && (dev < ps2esdi_drives))
1123 switch (cmd) {
1124 case HDIO_GETGEO:
1125 if (arg) {
1126 if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
1127 return (err);
1128 put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
1129 put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
1130 put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
1131 put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
1132 (long *) &geometry->start);
1134 return (0);
1136 break;
1138 case BLKGETSIZE:
1139 if (arg) {
1140 if ((err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))))
1141 return (err);
1142 put_user(ps2esdi[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
1144 return (0);
1146 break;
1148 case BLKRRPART:
1149 if (!capable(CAP_SYS_ADMIN))
1150 return -EACCES;
1151 return (ps2esdi_reread_partitions(inode->i_rdev));
1153 case BLKROSET:
1154 case BLKROGET:
1155 case BLKRASET:
1156 case BLKRAGET:
1157 case BLKFLSBUF:
1158 case BLKPG:
1159 return blk_ioctl(inode->i_rdev, cmd, arg);
1161 return (-EINVAL);
1166 static int ps2esdi_reread_partitions(kdev_t dev)
1168 int target = DEVICE_NR(dev);
1169 int start = target << ps2esdi_gendisk.minor_shift;
1170 int partition;
1172 cli();
1173 ps2esdi_valid[target] = (access_count[target] != 1);
1174 sti();
1175 if (ps2esdi_valid[target])
1176 return (-EBUSY);
1178 for (partition = ps2esdi_gendisk.max_p - 1;
1179 partition >= 0; partition--) {
1180 int minor = (start | partition);
1181 kdev_t devp = MKDEV(MAJOR_NR, minor);
1182 struct super_block * sb = get_super(devp);
1184 sync_dev(devp);
1185 if (sb)
1186 invalidate_inodes(sb);
1187 invalidate_buffers(devp);
1188 ps2esdi_gendisk.part[start + partition].start_sect = 0;
1189 ps2esdi_gendisk.part[start + partition].nr_sects = 0;
1192 grok_partitions(&ps2esdi_gendisk, target, 1<<6,
1193 ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect);
1195 ps2esdi_valid[target] = 1;
1196 wake_up(&ps2esdi_wait_open);
1198 return (0);
1201 void ps2esdi_reset_timer(unsigned long unused)
1204 int status;
1206 status = inb(ESDI_INTRPT);
1207 if ((status & 0xf) == INT_RESET) {
1208 outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
1209 outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
1210 reset_status = 1;
1212 wake_up(&ps2esdi_int);
1215 #endif