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(kdev_t dev
);
100 static int ps2esdi_read_status_words(int num_words
, int max_words
, u_short
* buffer
);
102 static void dump_cmd_complete_status(u_int int_ret_code
);
104 static void ps2esdi_get_device_cfg(void);
106 void ps2esdi_reset_timer(unsigned long unused
);
108 u_int dma_arb_level
; /* DMA arbitration level */
110 static struct wait_queue
*ps2esdi_int
= NULL
, *ps2esdi_wait_open
= NULL
;
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 */
161 ps2esdi_release
, /* release */
162 block_fsync
/* fsync */
165 static struct gendisk ps2esdi_gendisk
=
167 MAJOR_NR
, /* Major number */
168 "ed", /* Major name */
169 6, /* Bits to shift to get real from partition */
170 1 << 6, /* Number of partitions per real disk */
171 MAX_HD
, /* maximum number of real disks */
172 ps2esdi_geninit
, /* init function */
173 ps2esdi
, /* hd struct */
174 ps2esdi_sizes
, /* block sizes */
176 (void *) ps2esdi_info
, /* internal */
180 /* initialization routine called by ll_rw_blk.c */
181 __initfunc(int ps2esdi_init(void))
184 /* register the device - pass the name, major number and operations
186 if (register_blkdev(MAJOR_NR
, "ed", &ps2esdi_fops
)) {
187 printk("%s: Unable to get major number %d\n", DEVICE_NAME
, MAJOR_NR
);
190 /* set up some global information - indicating device specific info */
191 blk_dev
[MAJOR_NR
].request_fn
= DEVICE_REQUEST
;
192 read_ahead
[MAJOR_NR
] = 8; /* 8 sector (4kB) read ahead */
194 /* some minor housekeeping - setup the global gendisk structure */
195 ps2esdi_gendisk
.next
= gendisk_head
;
196 gendisk_head
= &ps2esdi_gendisk
;
201 /* handles boot time command line parameters */
202 __initfunc(void tp720_setup(char *str
, int *ints
))
204 /* no params, just sets the tp720esdi flag if it exists */
206 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME
);
210 __initfunc(void ed_setup(char *str
, int *ints
))
214 /* handles 3 parameters only - corresponding to
215 1. Number of cylinders
223 /* print out the information - seen at boot time */
224 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
225 DEVICE_NAME
, ints
[0], ints
[1], ints
[2], ints
[3]);
227 /* set the index into device specific information table */
228 if (ps2esdi_info
[0].head
!= 0)
231 /* set up all the device information */
232 ps2esdi_info
[hdind
].head
= ints
[2];
233 ps2esdi_info
[hdind
].sect
= ints
[3];
234 ps2esdi_info
[hdind
].cyl
= ints
[1];
235 ps2esdi_info
[hdind
].wpcom
= 0;
236 ps2esdi_info
[hdind
].lzone
= ints
[1];
237 ps2esdi_info
[hdind
].ctl
= (ints
[2] > 8 ? 8 : 0);
238 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
239 ps2esdi_drives
= hdind
+ 1; /* increment index for the next time */
243 static int ps2esdi_getinfo(char *buf
, int slot
, void *d
)
247 len
+= sprintf(buf
+ len
, "DMA Arbitration Level: %d\n",
249 len
+= sprintf(buf
+ len
, "IO Port: %x\n", io_base
);
250 len
+= sprintf(buf
+ len
, "IRQ: 14\n");
251 len
+= sprintf(buf
+ len
, "Drives: %d\n", ps2esdi_drives
);
256 /* ps2 esdi specific initialization - called thru the gendisk chain */
257 __initfunc(static void ps2esdi_geninit(struct gendisk
*ignored
))
260 The first part contains the initialization code
261 for the ESDI disk subsystem. All we really do
262 is search for the POS registers of the controller
263 to do some simple setup operations. First, we
264 must ensure that the controller is installed,
265 enabled, and configured as PRIMARY. Then we must
266 determine the DMA arbitration level being used by
267 the controller so we can handle data transfer
268 operations properly. If all of this works, then
269 we will set the INIT_FLAG to a non-zero value.
272 int slot
= 0, i
, reset_start
, reset_end
;
274 unsigned short adapterID
;
276 if ((slot
= mca_find_adapter(INTG_ESDI_ID
, 0)) != MCA_NOTFOUND
) {
277 adapterID
= INTG_ESDI_ID
;
278 printk("%s: integrated ESDI adapter found in slot %d\n",
279 DEVICE_NAME
, slot
+1);
281 mca_set_adapter_name(slot
, "PS/2 Integrated ESDI");
283 } else if ((slot
= mca_find_adapter(NRML_ESDI_ID
, 0)) != -1) {
284 adapterID
= NRML_ESDI_ID
;
285 printk("%s: normal ESDI adapter found in slot %d\n",
286 DEVICE_NAME
, slot
+1);
287 mca_set_adapter_name(slot
, "PS/2 ESDI");
292 mca_set_adapter_procfn(slot
, (MCA_ProcFn
) ps2esdi_getinfo
, NULL
);
294 /* Found the slot - read the POS register 2 to get the necessary
295 configuration and status information. POS register 2 has the
296 following information :
301 1 - fairness disabled, linear priority assignment
302 5-2 arbitration level
305 0 - use addresses 0x3510 - 0x3517
309 status
= mca_read_stored_pos(slot
, 2);
310 /* is it enabled ? */
311 if (!(status
& STATUS_ENABLED
)) {
312 printk("%s: ESDI adapter disabled\n", DEVICE_NAME
);
315 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
316 share with the SCSI driver */
317 if (request_irq(PS2ESDI_IRQ
, ps2esdi_interrupt_handler
,
318 SA_INTERRUPT
| SA_SHIRQ
, "PS/2 ESDI", &ps2esdi_gendisk
)
319 && request_irq(PS2ESDI_IRQ
, ps2esdi_interrupt_handler
,
320 SA_SHIRQ
, "PS/2 ESDI", &ps2esdi_gendisk
)
322 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME
, PS2ESDI_IRQ
);
325 if (status
& STATUS_ALTERNATE
)
326 io_base
= ALT_IO_BASE
;
328 io_base
= PRIMARY_IO_BASE
;
330 /* get the dma arbitration level */
331 dma_arb_level
= (status
>> 2) & 0xf;
334 printk("%s: DMA arbitration level : %d\n",
335 DEVICE_NAME
, dma_arb_level
);
338 current_int_handler
= ps2esdi_initial_reset_int_handler
;
341 reset_start
= jiffies
;
342 while (!reset_status
) {
343 esdi_timer
.expires
= 100;
345 esdi_timer
.next
= esdi_timer
.prev
= NULL
;
346 add_timer(&esdi_timer
);
347 sleep_on(&ps2esdi_int
);
351 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
352 DEVICE_NAME
, reset_end
- reset_start
, (reset_end
- reset_start
) / HZ
,
353 (reset_end
- reset_start
) % HZ
);
356 /* Integrated ESDI Disk and Controller has only one drive! */
357 if (adapterID
== INTG_ESDI_ID
) /* if not "normal" PS2 ESDI adapter */
358 ps2esdi_drives
= 1; /* then we have only one physical disk! */
362 /* finally this part sets up some global data structures etc. */
364 ps2esdi_get_device_cfg();
366 /* some annoyance in the above routine returns TWO drives?
367 Is something else happining in the background?
368 Regaurdless we fix the # of drives again. AJK */
369 /* Integrated ESDI Disk and Controller has only one drive! */
370 if (adapterID
== INTG_ESDI_ID
) /* if not "normal" PS2 ESDI adapter */
371 ps2esdi_drives
= 1; /* Not three or two, ONE DAMNIT! */
373 current_int_handler
= ps2esdi_normal_interrupt_handler
;
375 ps2esdi_gendisk
.nr_real
= ps2esdi_drives
;
377 for (i
= 0; i
< ps2esdi_drives
; i
++) {
378 ps2esdi
[i
<< 6].nr_sects
=
379 ps2esdi_info
[i
].head
*
380 ps2esdi_info
[i
].sect
*
382 ps2esdi_valid
[i
] = 1;
384 for (i
= 0; i
< (MAX_HD
<< 6); i
++)
385 ps2esdi_blocksizes
[i
] = 1024;
386 blksize_size
[MAJOR_NR
] = ps2esdi_blocksizes
;
387 } /* ps2esdi_geninit */
390 __initfunc(static void ps2esdi_get_device_cfg(void))
392 u_short cmd_blk
[TYPE_0_CMD_BLK_LENGTH
];
394 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME
);
395 current_int_handler
= ps2esdi_geometry_int_handler
;
396 cmd_blk
[0] = CMD_GET_DEV_CONFIG
| 0x600;
399 ps2esdi_out_cmd_blk(cmd_blk
);
401 sleep_on(&ps2esdi_int
);
403 if (ps2esdi_drives
> 1) {
404 printk("%s: Drive 1\n", DEVICE_NAME
); /*BA */
405 cmd_blk
[0] = CMD_GET_DEV_CONFIG
| (1 << 5) | 0x600;
408 ps2esdi_out_cmd_blk(cmd_blk
);
410 sleep_on(&ps2esdi_int
);
411 } /* if second physical drive is present */
415 /* strategy routine that handles most of the IO requests */
416 static void do_ps2esdi_request(void)
419 /* since, this routine is called with interrupts cleared - they
420 must be before it finishes */
424 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
426 CURRENT_DEV
, MINOR(CURRENT
->rq_dev
),
427 CURRENT
->cmd
, CURRENT
->sector
,
428 CURRENT
->nr_sectors
, CURRENT
->buffer
);
431 /* standard macro that ensures that requests are really on the
432 list + sanity checks. */
435 if (virt_to_bus(CURRENT
->buffer
+ CURRENT
->nr_sectors
* 512) > 16 * MB
) {
436 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME
);
439 do_ps2esdi_request();
441 } /* check for above 16Mb dmas */
442 if ((CURRENT_DEV
< ps2esdi_drives
) &&
443 (CURRENT
->sector
+ CURRENT
->nr_sectors
<=
444 ps2esdi
[MINOR(CURRENT
->rq_dev
)].nr_sects
)) {
446 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
448 CURRENT_DEV
, MINOR(CURRENT
->dev
),
449 CURRENT
->cmd
, CURRENT
->sector
,
450 CURRENT
->nr_sectors
);
454 block
= CURRENT
->sector
+ ps2esdi
[MINOR(CURRENT
->rq_dev
)].start_sect
;
457 printk("%s: blocknumber : %d\n", DEVICE_NAME
, block
);
459 count
= CURRENT
->nr_sectors
;
460 switch (CURRENT
->cmd
) {
462 ps2esdi_readwrite(READ
, CURRENT_DEV
, block
, count
);
466 ps2esdi_readwrite(WRITE
, CURRENT_DEV
, block
, count
);
470 printk("%s: Unknown command\n", DEVICE_NAME
);
473 do_ps2esdi_request();
475 } /* handle different commands */
477 /* is request is valid */
479 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives
,
480 CURRENT
->sector
, ps2esdi
[MINOR(CURRENT
->rq_dev
)].nr_sects
);
483 do_ps2esdi_request();
486 } /* main strategy routine */
488 /* resets the ESDI adapter */
489 static void reset_ctrl(void)
495 /* enable interrupts on the controller */
496 status
= inb(ESDI_INTRPT
);
497 outb((status
& 0xe0) | ATT_EOI
, ESDI_ATTN
); /* to be sure we don't have
498 any interrupt pending... */
499 outb_p(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
501 /* read the ESDI status port - if the controller is not busy,
502 simply do a soft reset (fast) - otherwise we'll have to do a
503 hard (slow) reset. */
504 if (!(inb_p(ESDI_STATUS
) & STATUS_BUSY
)) {
505 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME
);
506 outb_p(CTRL_SOFT_RESET
, ESDI_ATTN
);
511 printk("%s: hard reset...\n", DEVICE_NAME
);
512 outb_p(CTRL_HARD_RESET
, ESDI_CONTROL
);
513 expire
= jiffies
+ 200;
514 while (jiffies
< expire
);
515 outb_p(1, ESDI_CONTROL
);
519 } /* reset the controller */
521 /* called by the strategy routine to handle read and write requests */
522 static void ps2esdi_readwrite(int cmd
, u_char drive
, u_int block
, u_int count
)
525 u_short track
, head
, cylinder
, sector
;
526 u_short cmd_blk
[TYPE_1_CMD_BLK_LENGTH
];
528 /* do some relevant arithmatic */
529 CURRENT
->current_nr_sectors
=
530 (count
< (2 * MAX_16BIT
/ SECT_SIZE
)) ? count
: (2 * MAX_16BIT
/ SECT_SIZE
);
531 track
= block
/ ps2esdi_info
[drive
].sect
;
532 head
= track
% ps2esdi_info
[drive
].head
;
533 cylinder
= track
/ ps2esdi_info
[drive
].head
;
534 sector
= block
% ps2esdi_info
[drive
].sect
;
537 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME
, cylinder
, head
, sector
);
539 /* call the routine that actually fills out a command block */
540 ps2esdi_fill_cmd_block
542 (cmd
== READ
) ? CMD_READ
: CMD_WRITE
,
543 cylinder
, head
, sector
,
544 CURRENT
->current_nr_sectors
, drive
);
546 /* send the command block to the controller */
547 if (ps2esdi_out_cmd_blk(cmd_blk
)) {
548 printk("%s: Controller failed\n", DEVICE_NAME
);
549 if ((++CURRENT
->errors
) < MAX_RETRIES
)
550 return do_ps2esdi_request();
554 do_ps2esdi_request();
557 /* check for failure to put out the command block */
560 printk("%s: waiting for xfer\n", DEVICE_NAME
);
562 /* turn disk lights on */
566 } /* ps2esdi_readwrite */
568 /* fill out the command block */
569 static void ps2esdi_fill_cmd_block(u_short
* cmd_blk
, u_short cmd
,
570 u_short cyl
, u_short head
, u_short sector
, u_short length
, u_char drive
)
573 cmd_blk
[0] = (drive
<< 5) | cmd
;
575 cmd_blk
[2] = ((cyl
& 0x1f) << 11) | (head
<< 5) | sector
;
576 cmd_blk
[3] = (cyl
& 0x3E0) >> 5;
578 } /* fill out the command block */
580 /* write a command block to the controller */
581 static int ps2esdi_out_cmd_blk(u_short
* cmd_blk
)
587 /* enable interrupts */
588 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
590 /* do not write to the controller, if it is busy */
591 for (i
= jiffies
+ ESDI_STAT_TIMEOUT
; (i
> jiffies
) && (inb(ESDI_STATUS
) &
595 printk("%s: i(1)=%d\n", DEVICE_NAME
, i
);
598 /* if device is still busy - then just time out */
599 if (inb(ESDI_STATUS
) & STATUS_BUSY
) {
600 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME
);
603 /* Set up the attention register in the controller */
604 outb(((*cmd_blk
) & 0xE0) | 1, ESDI_ATTN
);
607 printk("%s: sending %d words to controller\n", DEVICE_NAME
, (((*cmd_blk
) >> 14) + 1) << 1);
610 /* one by one send each word out */
611 for (i
= (((*cmd_blk
) >> 14) + 1) << 1; i
; i
--) {
612 status
= inb(ESDI_STATUS
);
613 for (j
= jiffies
+ ESDI_STAT_TIMEOUT
;
614 (j
> jiffies
) && (status
& STATUS_BUSY
) &&
615 (status
& STATUS_CMD_INF
); status
= inb(ESDI_STATUS
));
616 if ((status
& (STATUS_BUSY
| STATUS_CMD_INF
)) == STATUS_BUSY
) {
618 printk("%s: sending %04X\n", DEVICE_NAME
, *cmd_blk
);
620 outw(*cmd_blk
++, ESDI_CMD_INT
);
622 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
623 DEVICE_NAME
, status
);
626 } /* send all words out */
628 } /* send out the commands */
631 /* prepare for dma - do all the necessary setup */
632 static void ps2esdi_prep_dma(char *buffer
, u_short length
, u_char dma_xmode
)
636 buffer
=(char *)virt_to_bus(buffer
);
639 printk("ps2esdi: b_wait: %p\n", CURRENT
->bh
->b_wait
);
643 outb(dma_arb_level
| DMA_MASK_CHAN
, PORT_DMA_FN
);
645 outb(dma_arb_level
| DMA_WRITE_ADDR
, PORT_DMA_FN
);
646 outb((u_int
) buffer
& (u_int
) 0xff, PORT_DMA_EX
);
647 outb(((u_int
) buffer
>> 8) & (u_int
) 0xff, PORT_DMA_EX
);
648 outb(((u_int
) buffer
>> 16) & (u_int
) 0xff, PORT_DMA_EX
);
650 outb(dma_arb_level
| DMA_WRITE_TC
, PORT_DMA_FN
);
651 tc
= (length
* SECT_SIZE
/ 2) - 1;
652 outb(tc
& 0xff, PORT_DMA_EX
);
653 outb((tc
>> 8) & 0xff, PORT_DMA_EX
);
655 outb(dma_arb_level
| DMA_WRITE_MODE
, PORT_DMA_FN
);
656 outb(dma_xmode
, PORT_DMA_EX
);
658 outb(dma_arb_level
| DMA_UNMASK_CHAN
, PORT_DMA_FN
);
662 } /* prepare for dma */
666 static void ps2esdi_interrupt_handler(int irq
, void *dev_id
,
667 struct pt_regs
*regs
)
671 if (inb(ESDI_STATUS
) & STATUS_INTR
) {
672 int_ret_code
= inb(ESDI_INTRPT
);
673 if (current_int_handler
) {
674 /* Disable adapter interrupts till processing is finished */
675 outb(CTRL_DISABLE_INTR
, ESDI_CONTROL
);
676 current_int_handler(int_ret_code
);
678 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME
);
684 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code
)
687 switch (int_ret_code
& 0xf) {
690 printk("%s: initial reset completed.\n", DEVICE_NAME
);
691 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
692 wake_up(&ps2esdi_int
);
695 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
697 printk("%s: status: %02x\n", DEVICE_NAME
, inb(ESDI_STATUS
));
700 printk("%s: initial reset handler received interrupt: %02X\n",
701 DEVICE_NAME
, int_ret_code
);
702 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
705 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
709 static void ps2esdi_geometry_int_handler(u_int int_ret_code
)
711 u_int status
, drive_num
;
715 drive_num
= int_ret_code
>> 5;
716 switch (int_ret_code
& 0xf) {
717 case INT_CMD_COMPLETE
:
718 for (i
= ESDI_TIMEOUT
; i
& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
719 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
720 printk("%s: timeout reading status word\n", DEVICE_NAME
);
721 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
724 status
= inw(ESDI_STT_INT
);
725 if ((status
& 0x1F) == CMD_GET_DEV_CONFIG
) {
726 #define REPLY_WORDS 5 /* we already read word 0 */
727 u_short reply
[REPLY_WORDS
];
729 if (ps2esdi_read_status_words((status
>> 8) - 1, REPLY_WORDS
, reply
)) {
731 printk("%s: Device Configuration Status for drive %u\n",
732 DEVICE_NAME
, drive_num
);
734 printk("%s: Spares/cyls: %u", DEVICE_NAME
, reply
[0] >> 8);
737 ("Config bits: %s%s%s%s%s\n",
738 (reply
[0] & CONFIG_IS
) ? "Invalid Secondary, " : "",
739 ((reply
[0] & CONFIG_ZD
) && !(reply
[0] & CONFIG_IS
))
740 ? "Zero Defect, " : "Defects Present, ",
741 (reply
[0] & CONFIG_SF
) ? "Skewed Format, " : "",
742 (reply
[0] & CONFIG_FR
) ? "Removable, " : "Non-Removable, ",
743 (reply
[0] & CONFIG_RT
) ? "No Retries" : "Retries");
745 rba
= reply
[1] | ((unsigned long) reply
[2] << 16);
746 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME
, rba
);
748 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
749 DEVICE_NAME
, reply
[3], reply
[4] >> 8, reply
[4] & 0xff);
751 if (!ps2esdi_info
[drive_num
].head
) {
752 ps2esdi_info
[drive_num
].head
= 64;
753 ps2esdi_info
[drive_num
].sect
= 32;
754 ps2esdi_info
[drive_num
].cyl
= rba
/ (64 * 32);
755 ps2esdi_info
[drive_num
].wpcom
= 0;
756 ps2esdi_info
[drive_num
].lzone
= ps2esdi_info
[drive_num
].cyl
;
757 ps2esdi_info
[drive_num
].ctl
= 8;
758 if (tp720esdi
) { /* store the retrieved parameters */
759 ps2esdi_info
[0].head
= reply
[4] & 0Xff;
760 ps2esdi_info
[0].sect
= reply
[4] >> 8;
761 ps2esdi_info
[0].cyl
= reply
[3];
762 ps2esdi_info
[0].wpcom
= 0;
763 ps2esdi_info
[0].lzone
= reply
[3];
769 if (!ps2esdi_info
[drive_num
].head
) {
770 ps2esdi_info
[drive_num
].head
= reply
[4] & 0Xff;
771 ps2esdi_info
[drive_num
].sect
= reply
[4] >> 8;
772 ps2esdi_info
[drive_num
].cyl
= reply
[3];
773 ps2esdi_info
[drive_num
].wpcom
= 0;
774 ps2esdi_info
[drive_num
].lzone
= reply
[3];
775 if (tp720esdi
) { /* store the retrieved parameters */
776 ps2esdi_info
[0].head
= reply
[4] & 0Xff;
777 ps2esdi_info
[0].sect
= reply
[4] >> 8;
778 ps2esdi_info
[0].cyl
= reply
[3];
779 ps2esdi_info
[0].wpcom
= 0;
780 ps2esdi_info
[0].lzone
= reply
[3];
788 printk("%s: failed while getting device config\n", DEVICE_NAME
);
791 printk("%s: command %02X unknown by geometry handler\n",
792 DEVICE_NAME
, status
& 0x1f);
794 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
798 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
800 printk("%s: Device not available\n", DEVICE_NAME
);
804 case INT_CMD_ECC_RETRY
:
805 case INT_CMD_WARNING
:
809 case INT_CMD_BLK_ERR
:
810 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME
);
811 dump_cmd_complete_status(int_ret_code
);
812 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
815 printk("%s: Unknown interrupt reason: %02X\n",
816 DEVICE_NAME
, int_ret_code
& 0xf);
817 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
821 wake_up(&ps2esdi_int
);
823 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
827 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code
)
832 switch (int_ret_code
& 0x0f) {
833 case INT_TRANSFER_REQ
:
834 ps2esdi_prep_dma(CURRENT
->buffer
, CURRENT
->current_nr_sectors
,
835 (CURRENT
->cmd
== READ
) ? DMA_READ_16
: DMA_WRITE_16
);
836 outb(CTRL_ENABLE_DMA
| CTRL_ENABLE_INTR
, ESDI_CONTROL
);
840 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
842 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
845 case INT_CMD_COMPLETE
:
846 for (i
= ESDI_TIMEOUT
; i
& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
847 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
848 printk("%s: timeout reading status word\n", DEVICE_NAME
);
849 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
850 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
851 if ((++CURRENT
->errors
) < MAX_RETRIES
)
852 do_ps2esdi_request();
856 do_ps2esdi_request();
860 status
= inw(ESDI_STT_INT
);
861 switch (status
& 0x1F) {
862 case (CMD_READ
& 0xff):
863 case (CMD_WRITE
& 0xff):
865 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
866 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
868 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT
->bh
->b_wait
);
870 ps2esdi_continue_request();
873 printk("%s: interrupt for unknown command %02X\n",
874 DEVICE_NAME
, status
& 0x1f);
875 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
876 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
882 case INT_CMD_ECC_RETRY
:
884 dump_cmd_complete_status(int_ret_code
);
885 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
886 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
887 ps2esdi_continue_request();
889 case INT_CMD_WARNING
:
894 dump_cmd_complete_status(int_ret_code
);
895 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
896 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
897 if ((++CURRENT
->errors
) < MAX_RETRIES
)
898 do_ps2esdi_request();
902 do_ps2esdi_request();
906 case INT_CMD_BLK_ERR
:
907 dump_cmd_complete_status(int_ret_code
);
908 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
909 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
912 do_ps2esdi_request();
916 printk("%s: huh ? Who issued this format command ?\n"
918 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
919 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
923 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
924 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
925 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
929 printk("%s: Unknown interrupt reason: %02X\n",
930 DEVICE_NAME
, int_ret_code
& 0xf);
931 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
932 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
936 } /* handle interrupts */
939 static void ps2esdi_continue_request(void)
941 if (CURRENT
->nr_sectors
-= CURRENT
->current_nr_sectors
) {
942 CURRENT
->buffer
+= CURRENT
->current_nr_sectors
* SECT_SIZE
;
943 CURRENT
->sector
+= CURRENT
->current_nr_sectors
;
944 do_ps2esdi_request();
948 do_ps2esdi_request();
954 static int ps2esdi_read_status_words(int num_words
,
960 for (; max_words
&& num_words
; max_words
--, num_words
--, buffer
++) {
961 for (i
= ESDI_TIMEOUT
; i
&& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
962 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
963 printk("%s: timeout reading status word\n", DEVICE_NAME
);
966 *buffer
= inw(ESDI_STT_INT
);
974 static void dump_cmd_complete_status(u_int int_ret_code
)
976 #define WAIT_FOR_STATUS \
977 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
978 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
979 printk("%s: timeout reading status word\n",DEVICE_NAME); \
987 printk("%s: Device: %u, interrupt ID: %02X\n",
988 DEVICE_NAME
, int_ret_code
>> 5,
992 stat_word
= inw(ESDI_STT_INT
);
993 word_count
= (stat_word
>> 8) - 1;
994 printk("%s: %u status words, command: %02X\n", DEVICE_NAME
, word_count
,
999 stat_word
= inw(ESDI_STT_INT
);
1000 printk("%s: command status code: %02X, command error code: %02X\n",
1001 DEVICE_NAME
, stat_word
>> 8, stat_word
& 0xff);
1005 stat_word
= inw(ESDI_STT_INT
);
1006 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME
,
1007 (stat_word
& 0x1000) ? "Ready, " : "Not Ready, ",
1008 (stat_word
& 0x0800) ? "Selected, " : "Not Selected, ",
1009 (stat_word
& 0x0400) ? "Write Fault, " : "",
1010 (stat_word
& 0x0200) ? "Track 0, " : "",
1011 (stat_word
& 0x0100) ? "Seek or command complete, " : "",
1016 stat_word
= inw(ESDI_STT_INT
);
1017 printk("%s: Blocks to do: %u", DEVICE_NAME
, stat_word
);
1019 if (word_count
-= 2) {
1021 rba
= inw(ESDI_STT_INT
);
1023 rba
|= inw(ESDI_STT_INT
) << 16;
1024 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1025 (u_short
) ((rba
& 0x1ff80000) >> 11),
1026 (u_short
) ((rba
& 0x7E0) >> 5), (u_short
) (rba
& 0x1f));
1032 stat_word
= inw(ESDI_STT_INT
);
1033 printk("%s: Blocks required ECC: %u", DEVICE_NAME
, stat_word
);
1037 #undef WAIT_FOR_STATUS
1042 static int ps2esdi_open(struct inode
*inode
, struct file
*file
)
1044 int dev
= DEVICE_NR(inode
->i_rdev
);
1046 if (dev
< ps2esdi_drives
) {
1047 while (!ps2esdi_valid
[dev
])
1048 sleep_on(&ps2esdi_wait_open
);
1050 access_count
[dev
]++;
1059 static int ps2esdi_release(struct inode
*inode
, struct file
*file
)
1061 int dev
= DEVICE_NR(inode
->i_rdev
);
1063 if (dev
< ps2esdi_drives
) {
1064 sync_dev(inode
->i_rdev
);
1065 access_count
[dev
]--;
1072 static int ps2esdi_ioctl(struct inode
*inode
,
1073 struct file
*file
, u_int cmd
, u_long arg
)
1076 struct ps2esdi_geometry
*geometry
= (struct ps2esdi_geometry
*) arg
;
1077 int dev
= DEVICE_NR(inode
->i_rdev
), err
;
1079 if (inode
&& (dev
< ps2esdi_drives
))
1083 if ((err
= verify_area(VERIFY_WRITE
, geometry
, sizeof(*geometry
))))
1085 put_user(ps2esdi_info
[dev
].head
, (char *) &geometry
->heads
);
1086 put_user(ps2esdi_info
[dev
].sect
, (char *) &geometry
->sectors
);
1087 put_user(ps2esdi_info
[dev
].cyl
, (short *) &geometry
->cylinders
);
1088 put_user(ps2esdi
[MINOR(inode
->i_rdev
)].start_sect
,
1089 (long *) &geometry
->start
);
1095 if (!capable(CAP_SYS_ADMIN
))
1101 read_ahead
[MAJOR(inode
->i_rdev
)] = arg
;
1105 if ((err
= verify_area(VERIFY_WRITE
, (long *) arg
, sizeof(long))))
1107 put_user(ps2esdi
[MINOR(inode
->i_rdev
)].nr_sects
, (long *) arg
);
1113 if (!capable(CAP_SYS_ADMIN
))
1117 fsync_dev(inode
->i_rdev
);
1118 invalidate_buffers(inode
->i_rdev
);
1122 if (!capable(CAP_SYS_ADMIN
))
1124 return (ps2esdi_reread_partitions(inode
->i_rdev
));
1125 RO_IOCTLS(inode
->i_rdev
, arg
);
1132 static int ps2esdi_reread_partitions(kdev_t dev
)
1134 int target
= DEVICE_NR(dev
);
1135 int start
= target
<< ps2esdi_gendisk
.minor_shift
;
1139 ps2esdi_valid
[target
] = (access_count
[target
] != 1);
1141 if (ps2esdi_valid
[target
])
1144 for (partition
= ps2esdi_gendisk
.max_p
- 1;
1145 partition
>= 0; partition
--) {
1146 int minor
= (start
| partition
);
1147 kdev_t devp
= MKDEV(MAJOR_NR
, minor
);
1148 struct super_block
* sb
= get_super(devp
);
1152 invalidate_inodes(sb
);
1153 invalidate_buffers(devp
);
1154 ps2esdi_gendisk
.part
[start
+ partition
].start_sect
= 0;
1155 ps2esdi_gendisk
.part
[start
+ partition
].nr_sects
= 0;
1158 ps2esdi_gendisk
.part
[start
].nr_sects
= ps2esdi_info
[target
].head
*
1159 ps2esdi_info
[target
].cyl
* ps2esdi_info
[target
].sect
;
1160 resetup_one_dev(&ps2esdi_gendisk
, target
);
1162 ps2esdi_valid
[target
] = 1;
1163 wake_up(&ps2esdi_wait_open
);
1168 void ps2esdi_reset_timer(unsigned long unused
)
1173 status
= inb(ESDI_INTRPT
);
1174 if ((status
& 0xf) == INT_RESET
) {
1175 outb((status
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
1176 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
1179 wake_up(&ps2esdi_int
);