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
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 */
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>
41 #include <linux/kernel.h>
42 #include <linux/genhd.h>
43 #include <linux/ps2esdi.h>
44 #include <linux/blk.h>
45 #include <linux/blkpg.h>
46 #include <linux/mca.h>
47 #include <linux/init.h>
48 #include <linux/ioport.h>
50 #include <asm/system.h>
52 #include <asm/segment.h>
54 #include <asm/uaccess.h>
56 #define PS2ESDI_IRQ 14
59 #define MAX_16BIT 65536
60 #define ESDI_TIMEOUT 0xf000
61 #define ESDI_STAT_TIMEOUT 4
63 #define TYPE_0_CMD_BLK_LENGTH 2
64 #define TYPE_1_CMD_BLK_LENGTH 4
67 static void reset_ctrl(void);
69 int ps2esdi_init(void);
71 static void ps2esdi_geninit(struct gendisk
*ignored
);
73 static void do_ps2esdi_request(request_queue_t
* q
);
75 static void ps2esdi_readwrite(int cmd
, u_char drive
, u_int block
, u_int count
);
77 static void ps2esdi_fill_cmd_block(u_short
* cmd_blk
, u_short cmd
,
78 u_short cyl
, u_short head
, u_short sector
, u_short length
, u_char drive
);
80 static int ps2esdi_out_cmd_blk(u_short
* cmd_blk
);
82 static void ps2esdi_prep_dma(char *buffer
, u_short length
, u_char dma_xmode
);
84 static void ps2esdi_interrupt_handler(int irq
, void *dev_id
,
85 struct pt_regs
*regs
);
86 static void (*current_int_handler
) (u_int
) = NULL
;
87 static void ps2esdi_normal_interrupt_handler(u_int
);
88 static void ps2esdi_initial_reset_int_handler(u_int
);
89 static void ps2esdi_geometry_int_handler(u_int
);
91 static void ps2esdi_continue_request(void);
93 static int ps2esdi_open(struct inode
*inode
, struct file
*file
);
95 static int ps2esdi_release(struct inode
*inode
, struct file
*file
);
97 static int ps2esdi_ioctl(struct inode
*inode
, struct file
*file
,
98 u_int cmd
, u_long arg
);
100 static int ps2esdi_reread_partitions(kdev_t dev
);
102 static int ps2esdi_read_status_words(int num_words
, int max_words
, u_short
* buffer
);
104 static void dump_cmd_complete_status(u_int int_ret_code
);
106 static void ps2esdi_get_device_cfg(void);
108 void ps2esdi_reset_timer(unsigned long unused
);
110 u_int dma_arb_level
; /* DMA arbitration level */
112 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int
);
113 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open
);
116 static int access_count
[MAX_HD
] = {0,};
117 static char ps2esdi_valid
[MAX_HD
] = {0,};
118 static int ps2esdi_sizes
[MAX_HD
<< 6] = {0,};
119 static int ps2esdi_blocksizes
[MAX_HD
<< 6] = {0,};
120 static int ps2esdi_drives
= 0;
121 static struct hd_struct ps2esdi
[MAX_HD
<< 6];
122 static u_short io_base
;
123 static struct timer_list esdi_timer
= {NULL
, NULL
, 0, 0L, ps2esdi_reset_timer
};
124 static int reset_status
;
125 static int ps2esdi_slot
= -1;
126 int tp720esdi
= 0; /* Is it Integrated ESDI of ThinkPad-720? */
127 int intg_esdi
= 0; /* If integrated adapter */
128 struct ps2esdi_i_struct
{
129 unsigned int head
, sect
, cyl
, wpcom
, lzone
, ctl
;
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},
139 struct ps2esdi_i_struct ps2esdi_info
[] =
141 {64, 32, 161, 0, 0, 0},
145 struct ps2esdi_i_struct ps2esdi_info
[] =
150 static struct block_device_operations ps2esdi_fops
=
153 release
: ps2esdi_release
,
154 ioctl
: ps2esdi_ioctl
,
157 static struct gendisk ps2esdi_gendisk
=
159 MAJOR_NR
, /* Major number */
160 "ed", /* Major name */
161 6, /* Bits to shift to get real from partition */
162 1 << 6, /* Number of partitions per real disk */
163 MAX_HD
, /* maximum number of real disks */
164 ps2esdi_geninit
, /* init function */
165 ps2esdi
, /* hd struct */
166 ps2esdi_sizes
, /* block sizes */
168 (void *) ps2esdi_info
, /* internal */
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
178 if (register_blkdev(MAJOR_NR
, "ed", &ps2esdi_fops
)) {
179 printk("%s: Unable to get major number %d\n", DEVICE_NAME
, MAJOR_NR
);
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
;
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) {
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
];
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();
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 unregister_blkdev(MAJOR_NR
, "ed");
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
);
247 void __init
ed_setup(char *str
, int *ints
)
251 /* handles 3 parameters only - corresponding to
252 1. Number of cylinders
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)
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 */
280 static int ps2esdi_getinfo(char *buf
, int slot
, void *d
)
284 len
+= sprintf(buf
+ len
, "DMA Arbitration Level: %d\n",
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
);
293 /* ps2 esdi specific initialization - called thru the gendisk chain */
294 static void __init
ps2esdi_geninit(struct gendisk
*ignored
)
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
;
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);
318 mca_set_adapter_name(slot
, "PS/2 Integrated ESDI");
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");
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 :
340 1 - fairness disabled, linear priority assignment
341 5-2 arbitration level
344 0 - use addresses 0x3510 - 0x3517
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
);
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
);
364 if (status
& STATUS_ALTERNATE
)
365 io_base
= ALT_IO_BASE
;
367 io_base
= PRIMARY_IO_BASE
;
369 /* get the dma arbitration level */
370 dma_arb_level
= (status
>> 2) & 0xf;
373 printk("%s: DMA arbitration level : %d\n",
374 DEVICE_NAME
, dma_arb_level
);
377 current_int_handler
= ps2esdi_initial_reset_int_handler
;
380 reset_start
= jiffies
;
381 while (!reset_status
) {
382 esdi_timer
.expires
= HZ
;
384 esdi_timer
.next
= esdi_timer
.prev
= NULL
;
385 add_timer(&esdi_timer
);
386 sleep_on(&ps2esdi_int
);
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
< ps2esdi_drives
; i
++) {
418 ps2esdi
[i
<< 6].nr_sects
=
419 ps2esdi_info
[i
].head
*
420 ps2esdi_info
[i
].sect
*
422 ps2esdi_valid
[i
] = 1;
424 for (i
= 0; i
< (MAX_HD
<< 6); i
++)
425 ps2esdi_blocksizes
[i
] = 1024;
427 request_dma(dma_arb_level
, "ed");
428 request_region(io_base
, 4, "ed");
429 blksize_size
[MAJOR_NR
] = ps2esdi_blocksizes
;
430 } /* ps2esdi_geninit */
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;
442 ps2esdi_out_cmd_blk(cmd_blk
);
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;
451 ps2esdi_out_cmd_blk(cmd_blk
);
453 sleep_on(&ps2esdi_int
);
454 } /* if second physical drive is present */
458 /* strategy routine that handles most of the IO requests */
459 static void do_ps2esdi_request(request_queue_t
* q
)
462 /* since, this routine is called with interrupts cleared - they
463 must be before it finishes */
467 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
469 CURRENT_DEV
, MINOR(CURRENT
->rq_dev
),
470 CURRENT
->cmd
, CURRENT
->sector
,
471 CURRENT
->nr_sectors
, CURRENT
->buffer
);
474 /* standard macro that ensures that requests are really on the
475 list + sanity checks. */
478 if (virt_to_bus(CURRENT
->buffer
+ CURRENT
->nr_sectors
* 512) > 16 * MB
) {
479 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME
);
482 do_ps2esdi_request(q
);
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
)) {
489 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
491 CURRENT_DEV
, MINOR(CURRENT
->dev
),
492 CURRENT
->cmd
, CURRENT
->sector
,
493 CURRENT
->nr_sectors
);
497 block
= CURRENT
->sector
+ ps2esdi
[MINOR(CURRENT
->rq_dev
)].start_sect
;
500 printk("%s: blocknumber : %d\n", DEVICE_NAME
, block
);
502 count
= CURRENT
->nr_sectors
;
503 switch (CURRENT
->cmd
) {
505 ps2esdi_readwrite(READ
, CURRENT_DEV
, block
, count
);
509 ps2esdi_readwrite(WRITE
, CURRENT_DEV
, block
, count
);
513 printk("%s: Unknown command\n", DEVICE_NAME
);
516 do_ps2esdi_request(q
);
518 } /* handle different commands */
520 /* is request is valid */
522 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives
,
523 CURRENT
->sector
, ps2esdi
[MINOR(CURRENT
->rq_dev
)].nr_sects
);
526 do_ps2esdi_request(q
);
529 } /* main strategy routine */
531 /* resets the ESDI adapter */
532 static void reset_ctrl(void)
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
);
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
);
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
;
580 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME
, cylinder
, head
, sector
);
582 /* call the routine that actually fills out a command block */
583 ps2esdi_fill_cmd_block
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
);
597 do_ps2esdi_request(NULL
);
600 /* check for failure to put out the command block */
603 printk("%s: waiting for xfer\n", DEVICE_NAME
);
605 /* turn disk lights 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
;
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
)
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
) &
638 printk("%s: i(1)=%d\n", DEVICE_NAME
, i
);
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
);
646 /* Set up the attention register in the controller */
647 outb(((*cmd_blk
) & 0xE0) | 1, ESDI_ATTN
);
650 printk("%s: sending %d words to controller\n", DEVICE_NAME
, (((*cmd_blk
) >> 14) + 1) << 1);
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
) {
661 printk("%s: sending %04X\n", DEVICE_NAME
, *cmd_blk
);
663 outw(*cmd_blk
++, ESDI_CMD_INT
);
665 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
666 DEVICE_NAME
, status
);
669 } /* send all words out */
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
)
679 buffer
=(char *)virt_to_bus(buffer
);
682 printk("ps2esdi: b_wait: %p\n", CURRENT
->bh
->b_wait
);
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
);
705 } /* prepare for dma */
709 static void ps2esdi_interrupt_handler(int irq
, void *dev_id
,
710 struct pt_regs
*regs
)
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
);
721 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME
);
727 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code
)
730 switch (int_ret_code
& 0xf) {
733 printk("%s: initial reset completed.\n", DEVICE_NAME
);
734 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
735 wake_up(&ps2esdi_int
);
738 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
740 printk("%s: status: %02x\n", DEVICE_NAME
, inb(ESDI_STATUS
));
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
);
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
;
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
);
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
)) {
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);
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];
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];
832 printk("%s: failed while getting device config\n", DEVICE_NAME
);
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
);
842 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
844 printk("%s: Device not available\n", DEVICE_NAME
);
848 case INT_CMD_ECC_RETRY
:
849 case INT_CMD_WARNING
:
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
);
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
);
865 wake_up(&ps2esdi_int
);
867 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
871 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code
)
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
);
884 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
886 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
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
);
900 do_ps2esdi_request(NULL
);
904 status
= inw(ESDI_STT_INT
);
905 switch (status
& 0x1F) {
906 case (CMD_READ
& 0xff):
907 case (CMD_WRITE
& 0xff):
909 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
910 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
912 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT
->bh
->b_wait
);
914 ps2esdi_continue_request();
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
);
926 case INT_CMD_ECC_RETRY
:
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();
933 case INT_CMD_WARNING
:
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
);
946 do_ps2esdi_request(NULL
);
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
);
956 do_ps2esdi_request(NULL
);
960 printk("%s: huh ? Who issued this format command ?\n"
962 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
963 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
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
);
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
);
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
);
992 do_ps2esdi_request(NULL
);
998 static int ps2esdi_read_status_words(int num_words
,
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
);
1010 *buffer
= inw(ESDI_STT_INT
);
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); \
1031 printk("%s: Device: %u, interrupt ID: %02X\n",
1032 DEVICE_NAME
, int_ret_code
>> 5,
1033 int_ret_code
& 0xf);
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
,
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);
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, " : "",
1060 stat_word
= inw(ESDI_STT_INT
);
1061 printk("%s: Blocks to do: %u", DEVICE_NAME
, stat_word
);
1063 if (word_count
-= 2) {
1065 rba
= inw(ESDI_STT_INT
);
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));
1076 stat_word
= inw(ESDI_STT_INT
);
1077 printk("%s: Blocks required ECC: %u", DEVICE_NAME
, stat_word
);
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
]++;
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
]--;
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
))
1126 if ((err
= verify_area(VERIFY_WRITE
, geometry
, sizeof(*geometry
))))
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
);
1140 if ((err
= verify_area(VERIFY_WRITE
, (long *) arg
, sizeof(long))))
1142 put_user(ps2esdi
[MINOR(inode
->i_rdev
)].nr_sects
, (long *) arg
);
1149 if (!capable(CAP_SYS_ADMIN
))
1151 return (ps2esdi_reread_partitions(inode
->i_rdev
));
1159 return blk_ioctl(inode
->i_rdev
, cmd
, arg
);
1166 static int ps2esdi_reread_partitions(kdev_t dev
)
1168 int target
= DEVICE_NR(dev
);
1169 int start
= target
<< ps2esdi_gendisk
.minor_shift
;
1173 ps2esdi_valid
[target
] = (access_count
[target
] != 1);
1175 if (ps2esdi_valid
[target
])
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
);
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 ps2esdi_gendisk
.part
[start
].nr_sects
= ps2esdi_info
[target
].head
*
1193 ps2esdi_info
[target
].cyl
* ps2esdi_info
[target
].sect
;
1194 resetup_one_dev(&ps2esdi_gendisk
, target
);
1196 ps2esdi_valid
[target
] = 1;
1197 wake_up(&ps2esdi_wait_open
);
1202 void ps2esdi_reset_timer(unsigned long unused
)
1207 status
= inb(ESDI_INTRPT
);
1208 if ((status
& 0xf) == INT_RESET
) {
1209 outb((status
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
1210 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
1213 wake_up(&ps2esdi_int
);