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/mca.h>
46 #include <linux/init.h>
48 #include <asm/system.h>
50 #include <asm/segment.h>
52 #include <asm/uaccess.h>
54 #define PS2ESDI_IRQ 14
57 #define MAX_16BIT 65536
58 #define ESDI_TIMEOUT 0xf000
59 #define ESDI_STAT_TIMEOUT 4
61 #define TYPE_0_CMD_BLK_LENGTH 2
62 #define TYPE_1_CMD_BLK_LENGTH 4
65 static void reset_ctrl(void);
67 int ps2esdi_init(void);
69 static void ps2esdi_geninit(struct gendisk
*ignored
);
71 static void do_ps2esdi_request(void);
73 static void ps2esdi_readwrite(int cmd
, u_char drive
, u_int block
, u_int count
);
75 static void ps2esdi_fill_cmd_block(u_short
* cmd_blk
, u_short cmd
,
76 u_short cyl
, u_short head
, u_short sector
, u_short length
, u_char drive
);
78 static int ps2esdi_out_cmd_blk(u_short
* cmd_blk
);
80 static void ps2esdi_prep_dma(char *buffer
, u_short length
, u_char dma_xmode
);
82 static void ps2esdi_interrupt_handler(int irq
, void *dev_id
,
83 struct pt_regs
*regs
);
84 static void (*current_int_handler
) (u_int
) = NULL
;
85 static void ps2esdi_normal_interrupt_handler(u_int
);
86 static void ps2esdi_initial_reset_int_handler(u_int
);
87 static void ps2esdi_geometry_int_handler(u_int
);
89 static void ps2esdi_continue_request(void);
91 static int ps2esdi_open(struct inode
*inode
, struct file
*file
);
93 static int ps2esdi_release(struct inode
*inode
, struct file
*file
);
95 static int ps2esdi_ioctl(struct inode
*inode
, struct file
*file
,
96 u_int cmd
, u_long arg
);
98 static int ps2esdi_reread_partitions(int dev
);
100 static int ps2esdi_read_status_words(int num_words
, int max_words
, u_short
* buffer
);
102 static void dump_cmd_complete_status(u_int int_ret_code
);
104 static void ps2esdi_get_device_cfg(void);
106 void ps2esdi_reset_timer(unsigned long unused
);
108 u_int dma_arb_level
; /* DMA arbitration level */
110 static struct wait_queue
*ps2esdi_int
= NULL
, *ps2esdi_wait_open
= NULL
;
112 static int access_count
[MAX_HD
] =
114 static char ps2esdi_valid
[MAX_HD
] =
116 static int ps2esdi_sizes
[MAX_HD
<< 6] =
118 static int ps2esdi_blocksizes
[MAX_HD
<< 6] =
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
;
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 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 */
157 ps2esdi_ioctl
, /* ioctl */
159 ps2esdi_open
, /* open */
160 ps2esdi_release
, /* release */
161 block_fsync
/* fsync */
164 static struct gendisk ps2esdi_gendisk
=
166 MAJOR_NR
, /* Major number */
167 "ed", /* Major name */
168 6, /* Bits to shift to get real from partition */
169 1 << 6, /* Number of partitions per real disk */
170 MAX_HD
, /* maximum number of real disks */
171 ps2esdi_geninit
, /* init function */
172 ps2esdi
, /* hd struct */
173 ps2esdi_sizes
, /* block sizes */
175 (void *) ps2esdi_info
, /* internal */
179 /* initialization routine called by ll_rw_blk.c */
180 __initfunc(int ps2esdi_init(void))
183 /* register the device - pass the name, major number and operations
185 if (register_blkdev(MAJOR_NR
, "ed", &ps2esdi_fops
)) {
186 printk("%s: Unable to get major number %d\n", DEVICE_NAME
, MAJOR_NR
);
189 /* set up some global information - indicating device specific info */
190 blk_dev
[MAJOR_NR
].request_fn
= DEVICE_REQUEST
;
191 read_ahead
[MAJOR_NR
] = 8; /* 8 sector (4kB) read ahead */
193 /* some minor housekeeping - setup the global gendisk structure */
194 ps2esdi_gendisk
.next
= gendisk_head
;
195 gendisk_head
= &ps2esdi_gendisk
;
200 /* handles boot time command line parameters */
201 __initfunc(void tp720_setup(char *str
, int *ints
))
203 /* no params, just sets the tp720esdi flag if it exists */
205 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME
);
209 __initfunc(void ed_setup(char *str
, int *ints
))
213 /* handles 3 parameters only - corresponding to
214 1. Number of cylinders
222 /* print out the information - seen at boot time */
223 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
224 DEVICE_NAME
, ints
[0], ints
[1], ints
[2], ints
[3]);
226 /* set the index into device specific information table */
227 if (ps2esdi_info
[0].head
!= 0)
230 /* set up all the device information */
231 ps2esdi_info
[hdind
].head
= ints
[2];
232 ps2esdi_info
[hdind
].sect
= ints
[3];
233 ps2esdi_info
[hdind
].cyl
= ints
[1];
234 ps2esdi_info
[hdind
].wpcom
= 0;
235 ps2esdi_info
[hdind
].lzone
= ints
[1];
236 ps2esdi_info
[hdind
].ctl
= (ints
[2] > 8 ? 8 : 0);
237 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
238 ps2esdi_drives
= hdind
+ 1; /* increment index for the next time */
242 static int ps2esdi_getinfo(char *buf
, int slot
, void *d
)
246 len
+= sprintf(buf
+ len
, "DMA Arbitration Level: %d\n",
248 len
+= sprintf(buf
+ len
, "IO Port: %x\n", io_base
);
249 len
+= sprintf(buf
+ len
, "IRQ: 14\n");
250 len
+= sprintf(buf
+ len
, "Drives: %d\n", ps2esdi_drives
);
255 /* ps2 esdi specific initialization - called thru the gendisk chain */
256 __initfunc(static void ps2esdi_geninit(struct gendisk
*ignored
))
259 The first part contains the initialization code
260 for the ESDI disk subsystem. All we really do
261 is search for the POS registers of the controller
262 to do some simple setup operations. First, we
263 must ensure that the controller is installed,
264 enabled, and configured as PRIMARY. Then we must
265 determine the DMA arbitration level being used by
266 the controller so we can handle data transfer
267 operations properly. If all of this works, then
268 we will set the INIT_FLAG to a non-zero value.
271 int slot
= 0, i
, reset_start
, reset_end
;
273 unsigned short adapterID
;
275 if ((slot
= mca_find_adapter(INTG_ESDI_ID
, 0)) != MCA_NOTFOUND
) {
276 adapterID
= INTG_ESDI_ID
;
277 printk("%s: integrated ESDI adapter found in slot %d\n",
278 DEVICE_NAME
, slot
+1);
280 mca_set_adapter_name(slot
, "PS/2 Integrated ESDI");
282 } else if ((slot
= mca_find_adapter(NRML_ESDI_ID
, 0)) != -1) {
283 adapterID
= NRML_ESDI_ID
;
284 printk("%s: normal ESDI adapter found in slot %d\n",
285 DEVICE_NAME
, slot
+1);
286 mca_set_adapter_name(slot
, "PS/2 ESDI");
291 mca_set_adapter_procfn(slot
, (MCA_ProcFn
) ps2esdi_getinfo
, NULL
);
293 /* Found the slot - read the POS register 2 to get the necessary
294 configuration and status information. POS register 2 has the
295 following information :
300 1 - fairness disabled, linear priority assignment
301 5-2 arbitration level
304 0 - use addresses 0x3510 - 0x3517
308 status
= mca_read_stored_pos(slot
, 2);
309 /* is it enabled ? */
310 if (!(status
& STATUS_ENABLED
)) {
311 printk("%s: ESDI adapter disabled\n", DEVICE_NAME
);
314 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
315 share with the SCSI driver */
316 if (request_irq(PS2ESDI_IRQ
, ps2esdi_interrupt_handler
,
317 SA_INTERRUPT
| SA_SHIRQ
, "PS/2 ESDI", &ps2esdi_gendisk
)
318 && request_irq(PS2ESDI_IRQ
, ps2esdi_interrupt_handler
,
319 SA_SHIRQ
, "PS/2 ESDI", &ps2esdi_gendisk
)
321 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME
, PS2ESDI_IRQ
);
324 if (status
& STATUS_ALTERNATE
)
325 io_base
= ALT_IO_BASE
;
327 io_base
= PRIMARY_IO_BASE
;
329 /* get the dma arbitration level */
330 dma_arb_level
= (status
>> 2) & 0xf;
333 printk("%s: DMA arbitration level : %d\n",
334 DEVICE_NAME
, dma_arb_level
);
337 current_int_handler
= ps2esdi_initial_reset_int_handler
;
340 reset_start
= jiffies
;
341 while (!reset_status
) {
342 esdi_timer
.expires
= 100;
344 esdi_timer
.next
= esdi_timer
.prev
= NULL
;
345 add_timer(&esdi_timer
);
346 sleep_on(&ps2esdi_int
);
350 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
351 DEVICE_NAME
, reset_end
- reset_start
, (reset_end
- reset_start
) / HZ
,
352 (reset_end
- reset_start
) % HZ
);
355 /* Integrated ESDI Disk and Controller has only one drive! */
356 if (adapterID
== INTG_ESDI_ID
) /* if not "normal" PS2 ESDI adapter */
357 ps2esdi_drives
= 1; /* then we have only one physical disk! */
361 /* finally this part sets up some global data structures etc. */
363 ps2esdi_get_device_cfg();
365 /* some annoyance in the above routine returns TWO drives?
366 Is something else happining in the background?
367 Regaurdless we fix the # of drives again. AJK */
368 /* Integrated ESDI Disk and Controller has only one drive! */
369 if (adapterID
== INTG_ESDI_ID
) /* if not "normal" PS2 ESDI adapter */
370 ps2esdi_drives
= 1; /* Not three or two, ONE DAMNIT! */
372 current_int_handler
= ps2esdi_normal_interrupt_handler
;
374 ps2esdi_gendisk
.nr_real
= ps2esdi_drives
;
376 for (i
= 0; i
< ps2esdi_drives
; i
++) {
377 ps2esdi
[i
<< 6].nr_sects
=
378 ps2esdi_info
[i
].head
*
379 ps2esdi_info
[i
].sect
*
381 ps2esdi_valid
[i
] = 1;
383 for (i
= 0; i
< (MAX_HD
<< 6); i
++)
384 ps2esdi_blocksizes
[i
] = 1024;
385 blksize_size
[MAJOR_NR
] = ps2esdi_blocksizes
;
386 } /* ps2esdi_geninit */
389 __initfunc(static void ps2esdi_get_device_cfg(void))
391 u_short cmd_blk
[TYPE_0_CMD_BLK_LENGTH
];
393 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME
);
394 current_int_handler
= ps2esdi_geometry_int_handler
;
395 cmd_blk
[0] = CMD_GET_DEV_CONFIG
| 0x600;
398 ps2esdi_out_cmd_blk(cmd_blk
);
400 sleep_on(&ps2esdi_int
);
402 if (ps2esdi_drives
> 1) {
403 printk("%s: Drive 1\n", DEVICE_NAME
); /*BA */
404 cmd_blk
[0] = CMD_GET_DEV_CONFIG
| (1 << 5) | 0x600;
407 ps2esdi_out_cmd_blk(cmd_blk
);
409 sleep_on(&ps2esdi_int
);
410 } /* if second physical drive is present */
414 /* strategy routine that handles most of the IO requests */
415 static void do_ps2esdi_request(void)
418 /* since, this routine is called with interrupts cleared - they
419 must be before it finishes */
423 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
425 CURRENT_DEV
, MINOR(CURRENT
->rq_dev
),
426 CURRENT
->cmd
, CURRENT
->sector
,
427 CURRENT
->nr_sectors
, CURRENT
->buffer
);
430 /* standard macro that ensures that requests are really on the
431 list + sanity checks. */
434 if (virt_to_bus(CURRENT
->buffer
+ CURRENT
->nr_sectors
* 512) > 16 * MB
) {
435 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME
);
438 do_ps2esdi_request();
440 } /* check for above 16Mb dmas */
441 if ((CURRENT_DEV
< ps2esdi_drives
) &&
442 (CURRENT
->sector
+ CURRENT
->nr_sectors
<=
443 ps2esdi
[MINOR(CURRENT
->rq_dev
)].nr_sects
)) {
445 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
447 CURRENT_DEV
, MINOR(CURRENT
->dev
),
448 CURRENT
->cmd
, CURRENT
->sector
,
449 CURRENT
->nr_sectors
);
453 block
= CURRENT
->sector
+ ps2esdi
[MINOR(CURRENT
->rq_dev
)].start_sect
;
456 printk("%s: blocknumber : %d\n", DEVICE_NAME
, block
);
458 count
= CURRENT
->nr_sectors
;
459 switch (CURRENT
->cmd
) {
461 ps2esdi_readwrite(READ
, CURRENT_DEV
, block
, count
);
465 ps2esdi_readwrite(WRITE
, CURRENT_DEV
, block
, count
);
469 printk("%s: Unknown command\n", DEVICE_NAME
);
472 do_ps2esdi_request();
474 } /* handle different commands */
476 /* is request is valid */
478 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives
,
479 CURRENT
->sector
, ps2esdi
[MINOR(CURRENT
->rq_dev
)].nr_sects
);
482 do_ps2esdi_request();
485 } /* main strategy routine */
487 /* resets the ESDI adapter */
488 static void reset_ctrl(void)
494 /* enable interrupts on the controller */
495 status
= inb(ESDI_INTRPT
);
496 outb((status
& 0xe0) | ATT_EOI
, ESDI_ATTN
); /* to be sure we don't have
497 any interrupt pending... */
498 outb_p(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
500 /* read the ESDI status port - if the controller is not busy,
501 simply do a soft reset (fast) - otherwise we'll have to do a
502 hard (slow) reset. */
503 if (!(inb_p(ESDI_STATUS
) & STATUS_BUSY
)) {
504 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME
);
505 outb_p(CTRL_SOFT_RESET
, ESDI_ATTN
);
510 printk("%s: hard reset...\n", DEVICE_NAME
);
511 outb_p(CTRL_HARD_RESET
, ESDI_CONTROL
);
512 expire
= jiffies
+ 200;
513 while (jiffies
< expire
);
514 outb_p(1, ESDI_CONTROL
);
518 } /* reset the controller */
520 /* called by the strategy routine to handle read and write requests */
521 static void ps2esdi_readwrite(int cmd
, u_char drive
, u_int block
, u_int count
)
524 u_short track
, head
, cylinder
, sector
;
525 u_short cmd_blk
[TYPE_1_CMD_BLK_LENGTH
];
527 /* do some relevant arithmatic */
528 CURRENT
->current_nr_sectors
=
529 (count
< (2 * MAX_16BIT
/ SECT_SIZE
)) ? count
: (2 * MAX_16BIT
/ SECT_SIZE
);
530 track
= block
/ ps2esdi_info
[drive
].sect
;
531 head
= track
% ps2esdi_info
[drive
].head
;
532 cylinder
= track
/ ps2esdi_info
[drive
].head
;
533 sector
= block
% ps2esdi_info
[drive
].sect
;
536 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME
, cylinder
, head
, sector
);
538 /* call the routine that actually fills out a command block */
539 ps2esdi_fill_cmd_block
541 (cmd
== READ
) ? CMD_READ
: CMD_WRITE
,
542 cylinder
, head
, sector
,
543 CURRENT
->current_nr_sectors
, drive
);
545 /* send the command block to the controller */
546 if (ps2esdi_out_cmd_blk(cmd_blk
)) {
547 printk("%s: Controller failed\n", DEVICE_NAME
);
548 if ((++CURRENT
->errors
) < MAX_RETRIES
)
549 return do_ps2esdi_request();
553 do_ps2esdi_request();
556 /* check for failure to put out the command block */
559 printk("%s: waiting for xfer\n", DEVICE_NAME
);
561 /* turn disk lights on */
565 } /* ps2esdi_readwrite */
567 /* fill out the command block */
568 static void ps2esdi_fill_cmd_block(u_short
* cmd_blk
, u_short cmd
,
569 u_short cyl
, u_short head
, u_short sector
, u_short length
, u_char drive
)
572 cmd_blk
[0] = (drive
<< 5) | cmd
;
574 cmd_blk
[2] = ((cyl
& 0x1f) << 11) | (head
<< 5) | sector
;
575 cmd_blk
[3] = (cyl
& 0x3E0) >> 5;
577 } /* fill out the command block */
579 /* write a command block to the controller */
580 static int ps2esdi_out_cmd_blk(u_short
* cmd_blk
)
586 /* enable interrupts */
587 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
589 /* do not write to the controller, if it is busy */
590 for (i
= jiffies
+ ESDI_STAT_TIMEOUT
; (i
> jiffies
) && (inb(ESDI_STATUS
) &
594 printk("%s: i(1)=%d\n", DEVICE_NAME
, i
);
597 /* if device is still busy - then just time out */
598 if (inb(ESDI_STATUS
) & STATUS_BUSY
) {
599 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME
);
602 /* Set up the attention register in the controller */
603 outb(((*cmd_blk
) & 0xE0) | 1, ESDI_ATTN
);
606 printk("%s: sending %d words to controller\n", DEVICE_NAME
, (((*cmd_blk
) >> 14) + 1) << 1);
609 /* one by one send each word out */
610 for (i
= (((*cmd_blk
) >> 14) + 1) << 1; i
; i
--) {
611 status
= inb(ESDI_STATUS
);
612 for (j
= jiffies
+ ESDI_STAT_TIMEOUT
;
613 (j
> jiffies
) && (status
& STATUS_BUSY
) &&
614 (status
& STATUS_CMD_INF
); status
= inb(ESDI_STATUS
));
615 if ((status
& (STATUS_BUSY
| STATUS_CMD_INF
)) == STATUS_BUSY
) {
617 printk("%s: sending %04X\n", DEVICE_NAME
, *cmd_blk
);
619 outw(*cmd_blk
++, ESDI_CMD_INT
);
621 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
622 DEVICE_NAME
, status
);
625 } /* send all words out */
627 } /* send out the commands */
630 /* prepare for dma - do all the necessary setup */
631 static void ps2esdi_prep_dma(char *buffer
, u_short length
, u_char dma_xmode
)
635 buffer
=(char *)virt_to_bus(buffer
);
638 printk("ps2esdi: b_wait: %p\n", CURRENT
->bh
->b_wait
);
642 outb(dma_arb_level
| DMA_MASK_CHAN
, PORT_DMA_FN
);
644 outb(dma_arb_level
| DMA_WRITE_ADDR
, PORT_DMA_FN
);
645 outb((u_int
) buffer
& (u_int
) 0xff, PORT_DMA_EX
);
646 outb(((u_int
) buffer
>> 8) & (u_int
) 0xff, PORT_DMA_EX
);
647 outb(((u_int
) buffer
>> 16) & (u_int
) 0xff, PORT_DMA_EX
);
649 outb(dma_arb_level
| DMA_WRITE_TC
, PORT_DMA_FN
);
650 tc
= (length
* SECT_SIZE
/ 2) - 1;
651 outb(tc
& 0xff, PORT_DMA_EX
);
652 outb((tc
>> 8) & 0xff, PORT_DMA_EX
);
654 outb(dma_arb_level
| DMA_WRITE_MODE
, PORT_DMA_FN
);
655 outb(dma_xmode
, PORT_DMA_EX
);
657 outb(dma_arb_level
| DMA_UNMASK_CHAN
, PORT_DMA_FN
);
661 } /* prepare for dma */
665 static void ps2esdi_interrupt_handler(int irq
, void *dev_id
,
666 struct pt_regs
*regs
)
670 if (inb(ESDI_STATUS
) & STATUS_INTR
) {
671 int_ret_code
= inb(ESDI_INTRPT
);
672 if (current_int_handler
) {
673 /* Disable adapter interrupts till processing is finished */
674 outb(CTRL_DISABLE_INTR
, ESDI_CONTROL
);
675 current_int_handler(int_ret_code
);
677 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME
);
683 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code
)
686 switch (int_ret_code
& 0xf) {
689 printk("%s: initial reset completed.\n", DEVICE_NAME
);
690 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
691 wake_up(&ps2esdi_int
);
694 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
696 printk("%s: status: %02x\n", DEVICE_NAME
, inb(ESDI_STATUS
));
699 printk("%s: initial reset handler received interrupt: %02X\n",
700 DEVICE_NAME
, int_ret_code
);
701 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
704 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
708 static void ps2esdi_geometry_int_handler(u_int int_ret_code
)
710 u_int status
, drive_num
;
714 drive_num
= int_ret_code
>> 5;
715 switch (int_ret_code
& 0xf) {
716 case INT_CMD_COMPLETE
:
717 for (i
= ESDI_TIMEOUT
; i
& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
718 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
719 printk("%s: timeout reading status word\n", DEVICE_NAME
);
720 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
723 status
= inw(ESDI_STT_INT
);
724 if ((status
& 0x1F) == CMD_GET_DEV_CONFIG
) {
725 #define REPLY_WORDS 5 /* we already read word 0 */
726 u_short reply
[REPLY_WORDS
];
728 if (ps2esdi_read_status_words((status
>> 8) - 1, REPLY_WORDS
, reply
)) {
730 printk("%s: Device Configuration Status for drive %u\n",
731 DEVICE_NAME
, drive_num
);
733 printk("%s: Spares/cyls: %u", DEVICE_NAME
, reply
[0] >> 8);
736 ("Config bits: %s%s%s%s%s\n",
737 (reply
[0] & CONFIG_IS
) ? "Invalid Secondary, " : "",
738 ((reply
[0] & CONFIG_ZD
) && !(reply
[0] & CONFIG_IS
))
739 ? "Zero Defect, " : "Defects Present, ",
740 (reply
[0] & CONFIG_SF
) ? "Skewed Format, " : "",
741 (reply
[0] & CONFIG_FR
) ? "Removable, " : "Non-Removable, ",
742 (reply
[0] & CONFIG_RT
) ? "No Retries" : "Retries");
744 rba
= reply
[1] | ((unsigned long) reply
[2] << 16);
745 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME
, rba
);
747 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
748 DEVICE_NAME
, reply
[3], reply
[4] >> 8, reply
[4] & 0xff);
750 if (!ps2esdi_info
[drive_num
].head
) {
751 ps2esdi_info
[drive_num
].head
= 64;
752 ps2esdi_info
[drive_num
].sect
= 32;
753 ps2esdi_info
[drive_num
].cyl
= rba
/ (64 * 32);
754 ps2esdi_info
[drive_num
].wpcom
= 0;
755 ps2esdi_info
[drive_num
].lzone
= ps2esdi_info
[drive_num
].cyl
;
756 ps2esdi_info
[drive_num
].ctl
= 8;
757 if (tp720esdi
) { /* store the retrieved parameters */
758 ps2esdi_info
[0].head
= reply
[4] & 0Xff;
759 ps2esdi_info
[0].sect
= reply
[4] >> 8;
760 ps2esdi_info
[0].cyl
= reply
[3];
761 ps2esdi_info
[0].wpcom
= 0;
762 ps2esdi_info
[0].lzone
= reply
[3];
768 if (!ps2esdi_info
[drive_num
].head
) {
769 ps2esdi_info
[drive_num
].head
= reply
[4] & 0Xff;
770 ps2esdi_info
[drive_num
].sect
= reply
[4] >> 8;
771 ps2esdi_info
[drive_num
].cyl
= reply
[3];
772 ps2esdi_info
[drive_num
].wpcom
= 0;
773 ps2esdi_info
[drive_num
].lzone
= reply
[3];
774 if (tp720esdi
) { /* store the retrieved parameters */
775 ps2esdi_info
[0].head
= reply
[4] & 0Xff;
776 ps2esdi_info
[0].sect
= reply
[4] >> 8;
777 ps2esdi_info
[0].cyl
= reply
[3];
778 ps2esdi_info
[0].wpcom
= 0;
779 ps2esdi_info
[0].lzone
= reply
[3];
787 printk("%s: failed while getting device config\n", DEVICE_NAME
);
790 printk("%s: command %02X unknown by geometry handler\n",
791 DEVICE_NAME
, status
& 0x1f);
793 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
797 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
799 printk("%s: Device not available\n", DEVICE_NAME
);
803 case INT_CMD_ECC_RETRY
:
804 case INT_CMD_WARNING
:
808 case INT_CMD_BLK_ERR
:
809 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME
);
810 dump_cmd_complete_status(int_ret_code
);
811 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
814 printk("%s: Unknown interrupt reason: %02X\n",
815 DEVICE_NAME
, int_ret_code
& 0xf);
816 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
820 wake_up(&ps2esdi_int
);
822 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
826 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code
)
831 switch (int_ret_code
& 0x0f) {
832 case INT_TRANSFER_REQ
:
833 ps2esdi_prep_dma(CURRENT
->buffer
, CURRENT
->current_nr_sectors
,
834 (CURRENT
->cmd
== READ
) ? DMA_READ_16
: DMA_WRITE_16
);
835 outb(CTRL_ENABLE_DMA
| CTRL_ENABLE_INTR
, ESDI_CONTROL
);
839 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
841 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
844 case INT_CMD_COMPLETE
:
845 for (i
= ESDI_TIMEOUT
; i
& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
846 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
847 printk("%s: timeout reading status word\n", DEVICE_NAME
);
848 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
849 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
850 if ((++CURRENT
->errors
) < MAX_RETRIES
)
851 do_ps2esdi_request();
855 do_ps2esdi_request();
859 status
= inw(ESDI_STT_INT
);
860 switch (status
& 0x1F) {
861 case (CMD_READ
& 0xff):
862 case (CMD_WRITE
& 0xff):
864 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
865 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
867 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT
->bh
->b_wait
);
869 ps2esdi_continue_request();
872 printk("%s: interrupt for unknown command %02X\n",
873 DEVICE_NAME
, status
& 0x1f);
874 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
875 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
881 case INT_CMD_ECC_RETRY
:
883 dump_cmd_complete_status(int_ret_code
);
884 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
885 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
886 ps2esdi_continue_request();
888 case INT_CMD_WARNING
:
893 dump_cmd_complete_status(int_ret_code
);
894 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
895 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
896 if ((++CURRENT
->errors
) < MAX_RETRIES
)
897 do_ps2esdi_request();
901 do_ps2esdi_request();
905 case INT_CMD_BLK_ERR
:
906 dump_cmd_complete_status(int_ret_code
);
907 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
908 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
911 do_ps2esdi_request();
915 printk("%s: huh ? Who issued this format command ?\n"
917 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
918 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
922 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
923 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
924 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
928 printk("%s: Unknown interrupt reason: %02X\n",
929 DEVICE_NAME
, int_ret_code
& 0xf);
930 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
931 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
935 } /* handle interrupts */
938 static void ps2esdi_continue_request(void)
940 if (CURRENT
->nr_sectors
-= CURRENT
->current_nr_sectors
) {
941 CURRENT
->buffer
+= CURRENT
->current_nr_sectors
* SECT_SIZE
;
942 CURRENT
->sector
+= CURRENT
->current_nr_sectors
;
943 do_ps2esdi_request();
947 do_ps2esdi_request();
953 static int ps2esdi_read_status_words(int num_words
,
959 for (; max_words
&& num_words
; max_words
--, num_words
--, buffer
++) {
960 for (i
= ESDI_TIMEOUT
; i
&& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
961 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
962 printk("%s: timeout reading status word\n", DEVICE_NAME
);
965 *buffer
= inw(ESDI_STT_INT
);
973 static void dump_cmd_complete_status(u_int int_ret_code
)
975 #define WAIT_FOR_STATUS \
976 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
977 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
978 printk("%s: timeout reading status word\n",DEVICE_NAME); \
986 printk("%s: Device: %u, interrupt ID: %02X\n",
987 DEVICE_NAME
, int_ret_code
>> 5,
991 stat_word
= inw(ESDI_STT_INT
);
992 word_count
= (stat_word
>> 8) - 1;
993 printk("%s: %u status words, command: %02X\n", DEVICE_NAME
, word_count
,
998 stat_word
= inw(ESDI_STT_INT
);
999 printk("%s: command status code: %02X, command error code: %02X\n",
1000 DEVICE_NAME
, stat_word
>> 8, stat_word
& 0xff);
1004 stat_word
= inw(ESDI_STT_INT
);
1005 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME
,
1006 (stat_word
& 0x1000) ? "Ready, " : "Not Ready, ",
1007 (stat_word
& 0x0800) ? "Selected, " : "Not Selected, ",
1008 (stat_word
& 0x0400) ? "Write Fault, " : "",
1009 (stat_word
& 0x0200) ? "Track 0, " : "",
1010 (stat_word
& 0x0100) ? "Seek or command complete, " : "",
1015 stat_word
= inw(ESDI_STT_INT
);
1016 printk("%s: Blocks to do: %u", DEVICE_NAME
, stat_word
);
1018 if (word_count
-= 2) {
1020 rba
= inw(ESDI_STT_INT
);
1022 rba
|= inw(ESDI_STT_INT
) << 16;
1023 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1024 (u_short
) ((rba
& 0x1ff80000) >> 11),
1025 (u_short
) ((rba
& 0x7E0) >> 5), (u_short
) (rba
& 0x1f));
1031 stat_word
= inw(ESDI_STT_INT
);
1032 printk("%s: Blocks required ECC: %u", DEVICE_NAME
, stat_word
);
1036 #undef WAIT_FOR_STATUS
1041 static int ps2esdi_open(struct inode
*inode
, struct file
*file
)
1043 int dev
= DEVICE_NR(inode
->i_rdev
);
1045 if (dev
< ps2esdi_drives
) {
1046 while (!ps2esdi_valid
[dev
])
1047 sleep_on(&ps2esdi_wait_open
);
1049 access_count
[dev
]++;
1058 static int ps2esdi_release(struct inode
*inode
, struct file
*file
)
1060 int dev
= DEVICE_NR(inode
->i_rdev
);
1062 if (dev
< ps2esdi_drives
) {
1064 access_count
[dev
]--;
1071 static int ps2esdi_ioctl(struct inode
*inode
,
1072 struct file
*file
, u_int cmd
, u_long arg
)
1075 struct ps2esdi_geometry
*geometry
= (struct ps2esdi_geometry
*) arg
;
1076 int dev
= DEVICE_NR(inode
->i_rdev
), err
;
1078 if (inode
&& (dev
< ps2esdi_drives
))
1082 if ((err
= verify_area(VERIFY_WRITE
, geometry
, sizeof(*geometry
))))
1084 put_user(ps2esdi_info
[dev
].head
, (char *) &geometry
->heads
);
1085 put_user(ps2esdi_info
[dev
].sect
, (char *) &geometry
->sectors
);
1086 put_user(ps2esdi_info
[dev
].cyl
, (short *) &geometry
->cylinders
);
1087 put_user(ps2esdi
[MINOR(inode
->i_rdev
)].start_sect
,
1088 (long *) &geometry
->start
);
1100 read_ahead
[MAJOR(inode
->i_rdev
)] = arg
;
1104 if ((err
= verify_area(VERIFY_WRITE
, (long *) arg
, sizeof(long))))
1106 put_user(ps2esdi
[MINOR(inode
->i_rdev
)].nr_sects
, (long *) arg
);
1116 fsync_dev(inode
->i_rdev
);
1117 invalidate_buffers(inode
->i_rdev
);
1121 return (ps2esdi_reread_partitions(inode
->i_rdev
));
1122 RO_IOCTLS(inode
->i_rdev
, arg
);
1129 static int ps2esdi_reread_partitions(int dev
)
1131 int target
= DEVICE_NR(dev
);
1132 int start
= target
<< ps2esdi_gendisk
.minor_shift
;
1136 ps2esdi_valid
[target
] = (access_count
[target
] != 1);
1138 if (ps2esdi_valid
[target
])
1141 for (partition
= ps2esdi_gendisk
.max_p
- 1;
1142 partition
>= 0; partition
--) {
1143 int minor
= (start
| partition
);
1144 kdev_t devp
= MKDEV(MAJOR_NR
, minor
);
1145 struct super_block
* sb
= get_super(devp
);
1149 invalidate_inodes(sb
);
1150 invalidate_buffers(devp
);
1151 ps2esdi_gendisk
.part
[start
+ partition
].start_sect
= 0;
1152 ps2esdi_gendisk
.part
[start
+ partition
].nr_sects
= 0;
1155 ps2esdi_gendisk
.part
[start
].nr_sects
= ps2esdi_info
[target
].head
*
1156 ps2esdi_info
[target
].cyl
* ps2esdi_info
[target
].sect
;
1157 resetup_one_dev(&ps2esdi_gendisk
, target
);
1159 ps2esdi_valid
[target
] = 1;
1160 wake_up(&ps2esdi_wait_open
);
1165 void ps2esdi_reset_timer(unsigned long unused
)
1170 status
= inb(ESDI_INTRPT
);
1171 if ((status
& 0xf) == INT_RESET
) {
1172 outb((status
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
1173 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
1176 wake_up(&ps2esdi_int
);