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(void);
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? */
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
;
203 int cyl
[2] = {-1,-1};
204 int head
[2] = {-1, -1};
205 int sect
[2] = {-1, -1};
207 MODULE_PARM(tp720esdi
, "i");
208 MODULE_PARM(cyl
, "i");
209 MODULE_PARM(head
, "i");
210 MODULE_PARM(track
, "i");
212 int init_module(void) {
215 for(drive
= 0; drive
<= 1; drive
++) {
216 struct ps2_esdi_i_struct
*info
= &ps2esdi_info
[drive
];
218 if (cyl
[drive
] != -1) {
219 info
->cyl
= info
->lzone
= cyl
[drive
];
222 if (head
[drive
] != -1) {
223 info
->head
= head
[drive
];
224 info
->ctl
= (head
[drive
] > 8 ? 8 : 0);
226 if (sect
[drive
] != -1) info
->sect
= sect
[drive
];
228 return ps2esdi_init();
236 mca_mark_as_unused(ps2esdi_slot
);
237 mca_set_adapter_procfn(ps2esdi_slot
, NULL
, NULL
);
239 release_region(io_base
, 4);
240 free_dma(dma_arb_level
);
241 free_irq(PS2ESDI_IRQ
, NULL
)
242 unregister_blkdev(MAJOR_NR
, "ed");
246 /* handles boot time command line parameters */
247 __initfunc(void tp720_setup(char *str
, int *ints
))
249 /* no params, just sets the tp720esdi flag if it exists */
251 printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME
);
255 __initfunc(void ed_setup(char *str
, int *ints
))
259 /* handles 3 parameters only - corresponding to
260 1. Number of cylinders
268 /* print out the information - seen at boot time */
269 printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
270 DEVICE_NAME
, ints
[0], ints
[1], ints
[2], ints
[3]);
272 /* set the index into device specific information table */
273 if (ps2esdi_info
[0].head
!= 0)
276 /* set up all the device information */
277 ps2esdi_info
[hdind
].head
= ints
[2];
278 ps2esdi_info
[hdind
].sect
= ints
[3];
279 ps2esdi_info
[hdind
].cyl
= ints
[1];
280 ps2esdi_info
[hdind
].wpcom
= 0;
281 ps2esdi_info
[hdind
].lzone
= ints
[1];
282 ps2esdi_info
[hdind
].ctl
= (ints
[2] > 8 ? 8 : 0);
283 #if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
284 ps2esdi_drives
= hdind
+ 1; /* increment index for the next time */
288 static int ps2esdi_getinfo(char *buf
, int slot
, void *d
)
292 len
+= sprintf(buf
+ len
, "DMA Arbitration Level: %d\n",
294 len
+= sprintf(buf
+ len
, "IO Port: %x\n", io_base
);
295 len
+= sprintf(buf
+ len
, "IRQ: 14\n");
296 len
+= sprintf(buf
+ len
, "Drives: %d\n", ps2esdi_drives
);
301 /* ps2 esdi specific initialization - called thru the gendisk chain */
302 __initfunc(static void ps2esdi_geninit(struct gendisk
*ignored
))
305 The first part contains the initialization code
306 for the ESDI disk subsystem. All we really do
307 is search for the POS registers of the controller
308 to do some simple setup operations. First, we
309 must ensure that the controller is installed,
310 enabled, and configured as PRIMARY. Then we must
311 determine the DMA arbitration level being used by
312 the controller so we can handle data transfer
313 operations properly. If all of this works, then
314 we will set the INIT_FLAG to a non-zero value.
317 int slot
= 0, i
, reset_start
, reset_end
;
319 unsigned short adapterID
;
321 if ((slot
= mca_find_adapter(INTG_ESDI_ID
, 0)) != MCA_NOTFOUND
) {
322 adapterID
= INTG_ESDI_ID
;
323 printk("%s: integrated ESDI adapter found in slot %d\n",
324 DEVICE_NAME
, slot
+1);
326 mca_set_adapter_name(slot
, "PS/2 Integrated ESDI");
328 } else if ((slot
= mca_find_adapter(NRML_ESDI_ID
, 0)) != -1) {
329 adapterID
= NRML_ESDI_ID
;
330 printk("%s: normal ESDI adapter found in slot %d\n",
331 DEVICE_NAME
, slot
+1);
332 mca_set_adapter_name(slot
, "PS/2 ESDI");
338 mca_mark_as_used(slot
);
339 mca_set_adapter_procfn(slot
, (MCA_ProcFn
) ps2esdi_getinfo
, NULL
);
341 /* Found the slot - read the POS register 2 to get the necessary
342 configuration and status information. POS register 2 has the
343 following information :
348 1 - fairness disabled, linear priority assignment
349 5-2 arbitration level
352 0 - use addresses 0x3510 - 0x3517
356 status
= mca_read_stored_pos(slot
, 2);
357 /* is it enabled ? */
358 if (!(status
& STATUS_ENABLED
)) {
359 printk("%s: ESDI adapter disabled\n", DEVICE_NAME
);
362 /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
363 share with the SCSI driver */
364 if (request_irq(PS2ESDI_IRQ
, ps2esdi_interrupt_handler
,
365 SA_INTERRUPT
| SA_SHIRQ
, "PS/2 ESDI", &ps2esdi_gendisk
)
366 && request_irq(PS2ESDI_IRQ
, ps2esdi_interrupt_handler
,
367 SA_SHIRQ
, "PS/2 ESDI", &ps2esdi_gendisk
)
369 printk("%s: Unable to get IRQ %d\n", DEVICE_NAME
, PS2ESDI_IRQ
);
372 if (status
& STATUS_ALTERNATE
)
373 io_base
= ALT_IO_BASE
;
375 io_base
= PRIMARY_IO_BASE
;
377 /* get the dma arbitration level */
378 dma_arb_level
= (status
>> 2) & 0xf;
381 printk("%s: DMA arbitration level : %d\n",
382 DEVICE_NAME
, dma_arb_level
);
385 current_int_handler
= ps2esdi_initial_reset_int_handler
;
388 reset_start
= jiffies
;
389 while (!reset_status
) {
390 esdi_timer
.expires
= 100;
392 esdi_timer
.next
= esdi_timer
.prev
= NULL
;
393 add_timer(&esdi_timer
);
394 sleep_on(&ps2esdi_int
);
398 printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n",
399 DEVICE_NAME
, reset_end
- reset_start
, (reset_end
- reset_start
) / HZ
,
400 (reset_end
- reset_start
) % HZ
);
403 /* Integrated ESDI Disk and Controller has only one drive! */
404 if (adapterID
== INTG_ESDI_ID
) /* if not "normal" PS2 ESDI adapter */
405 ps2esdi_drives
= 1; /* then we have only one physical disk! */
409 /* finally this part sets up some global data structures etc. */
411 ps2esdi_get_device_cfg();
413 /* some annoyance in the above routine returns TWO drives?
414 Is something else happining in the background?
415 Regaurdless we fix the # of drives again. AJK */
416 /* Integrated ESDI Disk and Controller has only one drive! */
417 if (adapterID
== INTG_ESDI_ID
) /* if not "normal" PS2 ESDI adapter */
418 ps2esdi_drives
= 1; /* Not three or two, ONE DAMNIT! */
420 current_int_handler
= ps2esdi_normal_interrupt_handler
;
422 ps2esdi_gendisk
.nr_real
= ps2esdi_drives
;
424 for (i
= 0; i
< ps2esdi_drives
; i
++) {
425 ps2esdi
[i
<< 6].nr_sects
=
426 ps2esdi_info
[i
].head
*
427 ps2esdi_info
[i
].sect
*
429 ps2esdi_valid
[i
] = 1;
431 for (i
= 0; i
< (MAX_HD
<< 6); i
++)
432 ps2esdi_blocksizes
[i
] = 1024;
434 request_dma(dma_arb_level
, "ed");
435 request_region(io_base
, 4, "ed");
436 blksize_size
[MAJOR_NR
] = ps2esdi_blocksizes
;
437 } /* ps2esdi_geninit */
440 __initfunc(static void ps2esdi_get_device_cfg(void))
442 u_short cmd_blk
[TYPE_0_CMD_BLK_LENGTH
];
444 /*BA */ printk("%s: Drive 0\n", DEVICE_NAME
);
445 current_int_handler
= ps2esdi_geometry_int_handler
;
446 cmd_blk
[0] = CMD_GET_DEV_CONFIG
| 0x600;
449 ps2esdi_out_cmd_blk(cmd_blk
);
451 sleep_on(&ps2esdi_int
);
453 if (ps2esdi_drives
> 1) {
454 printk("%s: Drive 1\n", DEVICE_NAME
); /*BA */
455 cmd_blk
[0] = CMD_GET_DEV_CONFIG
| (1 << 5) | 0x600;
458 ps2esdi_out_cmd_blk(cmd_blk
);
460 sleep_on(&ps2esdi_int
);
461 } /* if second physical drive is present */
465 /* strategy routine that handles most of the IO requests */
466 static void do_ps2esdi_request(void)
469 /* since, this routine is called with interrupts cleared - they
470 must be before it finishes */
474 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
476 CURRENT_DEV
, MINOR(CURRENT
->rq_dev
),
477 CURRENT
->cmd
, CURRENT
->sector
,
478 CURRENT
->nr_sectors
, CURRENT
->buffer
);
481 /* standard macro that ensures that requests are really on the
482 list + sanity checks. */
485 if (virt_to_bus(CURRENT
->buffer
+ CURRENT
->nr_sectors
* 512) > 16 * MB
) {
486 printk("%s: DMA above 16MB not supported\n", DEVICE_NAME
);
489 do_ps2esdi_request();
491 } /* check for above 16Mb dmas */
492 if ((CURRENT_DEV
< ps2esdi_drives
) &&
493 (CURRENT
->sector
+ CURRENT
->nr_sectors
<=
494 ps2esdi
[MINOR(CURRENT
->rq_dev
)].nr_sects
)) {
496 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
498 CURRENT_DEV
, MINOR(CURRENT
->dev
),
499 CURRENT
->cmd
, CURRENT
->sector
,
500 CURRENT
->nr_sectors
);
504 block
= CURRENT
->sector
+ ps2esdi
[MINOR(CURRENT
->rq_dev
)].start_sect
;
507 printk("%s: blocknumber : %d\n", DEVICE_NAME
, block
);
509 count
= CURRENT
->nr_sectors
;
510 switch (CURRENT
->cmd
) {
512 ps2esdi_readwrite(READ
, CURRENT_DEV
, block
, count
);
516 ps2esdi_readwrite(WRITE
, CURRENT_DEV
, block
, count
);
520 printk("%s: Unknown command\n", DEVICE_NAME
);
523 do_ps2esdi_request();
525 } /* handle different commands */
527 /* is request is valid */
529 printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives
,
530 CURRENT
->sector
, ps2esdi
[MINOR(CURRENT
->rq_dev
)].nr_sects
);
533 do_ps2esdi_request();
536 } /* main strategy routine */
538 /* resets the ESDI adapter */
539 static void reset_ctrl(void)
545 /* enable interrupts on the controller */
546 status
= inb(ESDI_INTRPT
);
547 outb((status
& 0xe0) | ATT_EOI
, ESDI_ATTN
); /* to be sure we don't have
548 any interrupt pending... */
549 outb_p(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
551 /* read the ESDI status port - if the controller is not busy,
552 simply do a soft reset (fast) - otherwise we'll have to do a
553 hard (slow) reset. */
554 if (!(inb_p(ESDI_STATUS
) & STATUS_BUSY
)) {
555 /*BA */ printk("%s: soft reset...\n", DEVICE_NAME
);
556 outb_p(CTRL_SOFT_RESET
, ESDI_ATTN
);
561 printk("%s: hard reset...\n", DEVICE_NAME
);
562 outb_p(CTRL_HARD_RESET
, ESDI_CONTROL
);
563 expire
= jiffies
+ 200;
564 while (time_before(jiffies
, expire
));
565 outb_p(1, ESDI_CONTROL
);
569 } /* reset the controller */
571 /* called by the strategy routine to handle read and write requests */
572 static void ps2esdi_readwrite(int cmd
, u_char drive
, u_int block
, u_int count
)
575 u_short track
, head
, cylinder
, sector
;
576 u_short cmd_blk
[TYPE_1_CMD_BLK_LENGTH
];
578 /* do some relevant arithmatic */
579 CURRENT
->current_nr_sectors
=
580 (count
< (2 * MAX_16BIT
/ SECT_SIZE
)) ? count
: (2 * MAX_16BIT
/ SECT_SIZE
);
581 track
= block
/ ps2esdi_info
[drive
].sect
;
582 head
= track
% ps2esdi_info
[drive
].head
;
583 cylinder
= track
/ ps2esdi_info
[drive
].head
;
584 sector
= block
% ps2esdi_info
[drive
].sect
;
587 printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME
, cylinder
, head
, sector
);
589 /* call the routine that actually fills out a command block */
590 ps2esdi_fill_cmd_block
592 (cmd
== READ
) ? CMD_READ
: CMD_WRITE
,
593 cylinder
, head
, sector
,
594 CURRENT
->current_nr_sectors
, drive
);
596 /* send the command block to the controller */
597 if (ps2esdi_out_cmd_blk(cmd_blk
)) {
598 printk("%s: Controller failed\n", DEVICE_NAME
);
599 if ((++CURRENT
->errors
) < MAX_RETRIES
)
600 return do_ps2esdi_request();
604 do_ps2esdi_request();
607 /* check for failure to put out the command block */
610 printk("%s: waiting for xfer\n", DEVICE_NAME
);
612 /* turn disk lights on */
616 } /* ps2esdi_readwrite */
618 /* fill out the command block */
619 static void ps2esdi_fill_cmd_block(u_short
* cmd_blk
, u_short cmd
,
620 u_short cyl
, u_short head
, u_short sector
, u_short length
, u_char drive
)
623 cmd_blk
[0] = (drive
<< 5) | cmd
;
625 cmd_blk
[2] = ((cyl
& 0x1f) << 11) | (head
<< 5) | sector
;
626 cmd_blk
[3] = (cyl
& 0x3E0) >> 5;
628 } /* fill out the command block */
630 /* write a command block to the controller */
631 static int ps2esdi_out_cmd_blk(u_short
* cmd_blk
)
637 /* enable interrupts */
638 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
640 /* do not write to the controller, if it is busy */
641 for (i
= jiffies
+ ESDI_STAT_TIMEOUT
; time_after(i
, jiffies
) && (inb(ESDI_STATUS
) &
645 printk("%s: i(1)=%d\n", DEVICE_NAME
, i
);
648 /* if device is still busy - then just time out */
649 if (inb(ESDI_STATUS
) & STATUS_BUSY
) {
650 printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME
);
653 /* Set up the attention register in the controller */
654 outb(((*cmd_blk
) & 0xE0) | 1, ESDI_ATTN
);
657 printk("%s: sending %d words to controller\n", DEVICE_NAME
, (((*cmd_blk
) >> 14) + 1) << 1);
660 /* one by one send each word out */
661 for (i
= (((*cmd_blk
) >> 14) + 1) << 1; i
; i
--) {
662 status
= inb(ESDI_STATUS
);
663 for (j
= jiffies
+ ESDI_STAT_TIMEOUT
;
664 time_after(j
, jiffies
) && (status
& STATUS_BUSY
) &&
665 (status
& STATUS_CMD_INF
); status
= inb(ESDI_STATUS
));
666 if ((status
& (STATUS_BUSY
| STATUS_CMD_INF
)) == STATUS_BUSY
) {
668 printk("%s: sending %04X\n", DEVICE_NAME
, *cmd_blk
);
670 outw(*cmd_blk
++, ESDI_CMD_INT
);
672 printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
673 DEVICE_NAME
, status
);
676 } /* send all words out */
678 } /* send out the commands */
681 /* prepare for dma - do all the necessary setup */
682 static void ps2esdi_prep_dma(char *buffer
, u_short length
, u_char dma_xmode
)
686 buffer
=(char *)virt_to_bus(buffer
);
689 printk("ps2esdi: b_wait: %p\n", CURRENT
->bh
->b_wait
);
693 outb(dma_arb_level
| DMA_MASK_CHAN
, PORT_DMA_FN
);
695 outb(dma_arb_level
| DMA_WRITE_ADDR
, PORT_DMA_FN
);
696 outb((u_int
) buffer
& (u_int
) 0xff, PORT_DMA_EX
);
697 outb(((u_int
) buffer
>> 8) & (u_int
) 0xff, PORT_DMA_EX
);
698 outb(((u_int
) buffer
>> 16) & (u_int
) 0xff, PORT_DMA_EX
);
700 outb(dma_arb_level
| DMA_WRITE_TC
, PORT_DMA_FN
);
701 tc
= (length
* SECT_SIZE
/ 2) - 1;
702 outb(tc
& 0xff, PORT_DMA_EX
);
703 outb((tc
>> 8) & 0xff, PORT_DMA_EX
);
705 outb(dma_arb_level
| DMA_WRITE_MODE
, PORT_DMA_FN
);
706 outb(dma_xmode
, PORT_DMA_EX
);
708 outb(dma_arb_level
| DMA_UNMASK_CHAN
, PORT_DMA_FN
);
712 } /* prepare for dma */
716 static void ps2esdi_interrupt_handler(int irq
, void *dev_id
,
717 struct pt_regs
*regs
)
721 if (inb(ESDI_STATUS
) & STATUS_INTR
) {
722 int_ret_code
= inb(ESDI_INTRPT
);
723 if (current_int_handler
) {
724 /* Disable adapter interrupts till processing is finished */
725 outb(CTRL_DISABLE_INTR
, ESDI_CONTROL
);
726 current_int_handler(int_ret_code
);
728 printk("%s: help ! No interrupt handler.\n", DEVICE_NAME
);
734 static void ps2esdi_initial_reset_int_handler(u_int int_ret_code
)
737 switch (int_ret_code
& 0xf) {
740 printk("%s: initial reset completed.\n", DEVICE_NAME
);
741 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
742 wake_up(&ps2esdi_int
);
745 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
747 printk("%s: status: %02x\n", DEVICE_NAME
, inb(ESDI_STATUS
));
750 printk("%s: initial reset handler received interrupt: %02X\n",
751 DEVICE_NAME
, int_ret_code
);
752 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
755 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
759 static void ps2esdi_geometry_int_handler(u_int int_ret_code
)
761 u_int status
, drive_num
;
765 drive_num
= int_ret_code
>> 5;
766 switch (int_ret_code
& 0xf) {
767 case INT_CMD_COMPLETE
:
768 for (i
= ESDI_TIMEOUT
; i
& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
769 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
770 printk("%s: timeout reading status word\n", DEVICE_NAME
);
771 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
774 status
= inw(ESDI_STT_INT
);
775 if ((status
& 0x1F) == CMD_GET_DEV_CONFIG
) {
776 #define REPLY_WORDS 5 /* we already read word 0 */
777 u_short reply
[REPLY_WORDS
];
779 if (ps2esdi_read_status_words((status
>> 8) - 1, REPLY_WORDS
, reply
)) {
781 printk("%s: Device Configuration Status for drive %u\n",
782 DEVICE_NAME
, drive_num
);
784 printk("%s: Spares/cyls: %u", DEVICE_NAME
, reply
[0] >> 8);
787 ("Config bits: %s%s%s%s%s\n",
788 (reply
[0] & CONFIG_IS
) ? "Invalid Secondary, " : "",
789 ((reply
[0] & CONFIG_ZD
) && !(reply
[0] & CONFIG_IS
))
790 ? "Zero Defect, " : "Defects Present, ",
791 (reply
[0] & CONFIG_SF
) ? "Skewed Format, " : "",
792 (reply
[0] & CONFIG_FR
) ? "Removable, " : "Non-Removable, ",
793 (reply
[0] & CONFIG_RT
) ? "No Retries" : "Retries");
795 rba
= reply
[1] | ((unsigned long) reply
[2] << 16);
796 printk("%s: Number of RBA's: %lu\n", DEVICE_NAME
, rba
);
798 printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
799 DEVICE_NAME
, reply
[3], reply
[4] >> 8, reply
[4] & 0xff);
801 if (!ps2esdi_info
[drive_num
].head
) {
802 ps2esdi_info
[drive_num
].head
= 64;
803 ps2esdi_info
[drive_num
].sect
= 32;
804 ps2esdi_info
[drive_num
].cyl
= rba
/ (64 * 32);
805 ps2esdi_info
[drive_num
].wpcom
= 0;
806 ps2esdi_info
[drive_num
].lzone
= ps2esdi_info
[drive_num
].cyl
;
807 ps2esdi_info
[drive_num
].ctl
= 8;
808 if (tp720esdi
) { /* store the retrieved parameters */
809 ps2esdi_info
[0].head
= reply
[4] & 0Xff;
810 ps2esdi_info
[0].sect
= reply
[4] >> 8;
811 ps2esdi_info
[0].cyl
= reply
[3];
812 ps2esdi_info
[0].wpcom
= 0;
813 ps2esdi_info
[0].lzone
= reply
[3];
819 if (!ps2esdi_info
[drive_num
].head
) {
820 ps2esdi_info
[drive_num
].head
= reply
[4] & 0Xff;
821 ps2esdi_info
[drive_num
].sect
= reply
[4] >> 8;
822 ps2esdi_info
[drive_num
].cyl
= reply
[3];
823 ps2esdi_info
[drive_num
].wpcom
= 0;
824 ps2esdi_info
[drive_num
].lzone
= reply
[3];
825 if (tp720esdi
) { /* store the retrieved parameters */
826 ps2esdi_info
[0].head
= reply
[4] & 0Xff;
827 ps2esdi_info
[0].sect
= reply
[4] >> 8;
828 ps2esdi_info
[0].cyl
= reply
[3];
829 ps2esdi_info
[0].wpcom
= 0;
830 ps2esdi_info
[0].lzone
= reply
[3];
838 printk("%s: failed while getting device config\n", DEVICE_NAME
);
841 printk("%s: command %02X unknown by geometry handler\n",
842 DEVICE_NAME
, status
& 0x1f);
844 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
848 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
850 printk("%s: Device not available\n", DEVICE_NAME
);
854 case INT_CMD_ECC_RETRY
:
855 case INT_CMD_WARNING
:
859 case INT_CMD_BLK_ERR
:
860 /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME
);
861 dump_cmd_complete_status(int_ret_code
);
862 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
865 printk("%s: Unknown interrupt reason: %02X\n",
866 DEVICE_NAME
, int_ret_code
& 0xf);
867 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
871 wake_up(&ps2esdi_int
);
873 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
877 static void ps2esdi_normal_interrupt_handler(u_int int_ret_code
)
882 switch (int_ret_code
& 0x0f) {
883 case INT_TRANSFER_REQ
:
884 ps2esdi_prep_dma(CURRENT
->buffer
, CURRENT
->current_nr_sectors
,
885 (CURRENT
->cmd
== READ
) ? DMA_READ_16
: DMA_WRITE_16
);
886 outb(CTRL_ENABLE_DMA
| CTRL_ENABLE_INTR
, ESDI_CONTROL
);
890 printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME
,
892 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
895 case INT_CMD_COMPLETE
:
896 for (i
= ESDI_TIMEOUT
; i
& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
897 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
898 printk("%s: timeout reading status word\n", DEVICE_NAME
);
899 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
900 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
901 if ((++CURRENT
->errors
) < MAX_RETRIES
)
902 do_ps2esdi_request();
906 do_ps2esdi_request();
910 status
= inw(ESDI_STT_INT
);
911 switch (status
& 0x1F) {
912 case (CMD_READ
& 0xff):
913 case (CMD_WRITE
& 0xff):
915 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
916 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
918 printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT
->bh
->b_wait
);
920 ps2esdi_continue_request();
923 printk("%s: interrupt for unknown command %02X\n",
924 DEVICE_NAME
, status
& 0x1f);
925 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
926 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
932 case INT_CMD_ECC_RETRY
:
934 dump_cmd_complete_status(int_ret_code
);
935 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
936 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
937 ps2esdi_continue_request();
939 case INT_CMD_WARNING
:
944 dump_cmd_complete_status(int_ret_code
);
945 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
946 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
947 if ((++CURRENT
->errors
) < MAX_RETRIES
)
948 do_ps2esdi_request();
952 do_ps2esdi_request();
956 case INT_CMD_BLK_ERR
:
957 dump_cmd_complete_status(int_ret_code
);
958 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
959 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
962 do_ps2esdi_request();
966 printk("%s: huh ? Who issued this format command ?\n"
968 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
969 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
973 /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
974 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
975 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
979 printk("%s: Unknown interrupt reason: %02X\n",
980 DEVICE_NAME
, int_ret_code
& 0xf);
981 outb((int_ret_code
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
982 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
986 } /* handle interrupts */
989 static void ps2esdi_continue_request(void)
991 if (CURRENT
->nr_sectors
-= CURRENT
->current_nr_sectors
) {
992 CURRENT
->buffer
+= CURRENT
->current_nr_sectors
* SECT_SIZE
;
993 CURRENT
->sector
+= CURRENT
->current_nr_sectors
;
994 do_ps2esdi_request();
998 do_ps2esdi_request();
1004 static int ps2esdi_read_status_words(int num_words
,
1010 for (; max_words
&& num_words
; max_words
--, num_words
--, buffer
++) {
1011 for (i
= ESDI_TIMEOUT
; i
&& !(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
); i
--);
1012 if (!(inb(ESDI_STATUS
) & STATUS_STAT_AVAIL
)) {
1013 printk("%s: timeout reading status word\n", DEVICE_NAME
);
1016 *buffer
= inw(ESDI_STT_INT
);
1024 static void dump_cmd_complete_status(u_int int_ret_code
)
1026 #define WAIT_FOR_STATUS \
1027 for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
1028 if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
1029 printk("%s: timeout reading status word\n",DEVICE_NAME); \
1037 printk("%s: Device: %u, interrupt ID: %02X\n",
1038 DEVICE_NAME
, int_ret_code
>> 5,
1039 int_ret_code
& 0xf);
1042 stat_word
= inw(ESDI_STT_INT
);
1043 word_count
= (stat_word
>> 8) - 1;
1044 printk("%s: %u status words, command: %02X\n", DEVICE_NAME
, word_count
,
1049 stat_word
= inw(ESDI_STT_INT
);
1050 printk("%s: command status code: %02X, command error code: %02X\n",
1051 DEVICE_NAME
, stat_word
>> 8, stat_word
& 0xff);
1055 stat_word
= inw(ESDI_STT_INT
);
1056 printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME
,
1057 (stat_word
& 0x1000) ? "Ready, " : "Not Ready, ",
1058 (stat_word
& 0x0800) ? "Selected, " : "Not Selected, ",
1059 (stat_word
& 0x0400) ? "Write Fault, " : "",
1060 (stat_word
& 0x0200) ? "Track 0, " : "",
1061 (stat_word
& 0x0100) ? "Seek or command complete, " : "",
1066 stat_word
= inw(ESDI_STT_INT
);
1067 printk("%s: Blocks to do: %u", DEVICE_NAME
, stat_word
);
1069 if (word_count
-= 2) {
1071 rba
= inw(ESDI_STT_INT
);
1073 rba
|= inw(ESDI_STT_INT
) << 16;
1074 printk(", Last Cyl: %u Head: %u Sector: %u\n",
1075 (u_short
) ((rba
& 0x1ff80000) >> 11),
1076 (u_short
) ((rba
& 0x7E0) >> 5), (u_short
) (rba
& 0x1f));
1082 stat_word
= inw(ESDI_STT_INT
);
1083 printk("%s: Blocks required ECC: %u", DEVICE_NAME
, stat_word
);
1087 #undef WAIT_FOR_STATUS
1092 static int ps2esdi_open(struct inode
*inode
, struct file
*file
)
1094 int dev
= DEVICE_NR(inode
->i_rdev
);
1096 if (dev
< ps2esdi_drives
) {
1097 while (!ps2esdi_valid
[dev
])
1098 sleep_on(&ps2esdi_wait_open
);
1100 access_count
[dev
]++;
1109 static int ps2esdi_release(struct inode
*inode
, struct file
*file
)
1111 int dev
= DEVICE_NR(inode
->i_rdev
);
1113 if (dev
< ps2esdi_drives
) {
1114 sync_dev(inode
->i_rdev
);
1115 access_count
[dev
]--;
1122 static int ps2esdi_ioctl(struct inode
*inode
,
1123 struct file
*file
, u_int cmd
, u_long arg
)
1126 struct ps2esdi_geometry
*geometry
= (struct ps2esdi_geometry
*) arg
;
1127 int dev
= DEVICE_NR(inode
->i_rdev
), err
;
1129 if (inode
&& (dev
< ps2esdi_drives
))
1133 if ((err
= verify_area(VERIFY_WRITE
, geometry
, sizeof(*geometry
))))
1135 put_user(ps2esdi_info
[dev
].head
, (char *) &geometry
->heads
);
1136 put_user(ps2esdi_info
[dev
].sect
, (char *) &geometry
->sectors
);
1137 put_user(ps2esdi_info
[dev
].cyl
, (short *) &geometry
->cylinders
);
1138 put_user(ps2esdi
[MINOR(inode
->i_rdev
)].start_sect
,
1139 (long *) &geometry
->start
);
1147 if ((err
= verify_area(VERIFY_WRITE
, (long *) arg
, sizeof(long))))
1149 put_user(ps2esdi
[MINOR(inode
->i_rdev
)].nr_sects
, (long *) arg
);
1156 if (!capable(CAP_SYS_ADMIN
))
1158 return (ps2esdi_reread_partitions(inode
->i_rdev
));
1166 return blk_ioctl(inode
->i_rdev
, cmd
, arg
);
1173 static int ps2esdi_reread_partitions(kdev_t dev
)
1175 int target
= DEVICE_NR(dev
);
1176 int start
= target
<< ps2esdi_gendisk
.minor_shift
;
1180 ps2esdi_valid
[target
] = (access_count
[target
] != 1);
1182 if (ps2esdi_valid
[target
])
1185 for (partition
= ps2esdi_gendisk
.max_p
- 1;
1186 partition
>= 0; partition
--) {
1187 int minor
= (start
| partition
);
1188 kdev_t devp
= MKDEV(MAJOR_NR
, minor
);
1189 struct super_block
* sb
= get_super(devp
);
1193 invalidate_inodes(sb
);
1194 invalidate_buffers(devp
);
1195 ps2esdi_gendisk
.part
[start
+ partition
].start_sect
= 0;
1196 ps2esdi_gendisk
.part
[start
+ partition
].nr_sects
= 0;
1199 ps2esdi_gendisk
.part
[start
].nr_sects
= ps2esdi_info
[target
].head
*
1200 ps2esdi_info
[target
].cyl
* ps2esdi_info
[target
].sect
;
1201 resetup_one_dev(&ps2esdi_gendisk
, target
);
1203 ps2esdi_valid
[target
] = 1;
1204 wake_up(&ps2esdi_wait_open
);
1209 void ps2esdi_reset_timer(unsigned long unused
)
1214 status
= inb(ESDI_INTRPT
);
1215 if ((status
& 0xf) == INT_RESET
) {
1216 outb((status
& 0xe0) | ATT_EOI
, ESDI_ATTN
);
1217 outb(CTRL_ENABLE_INTR
, ESDI_CONTROL
);
1220 wake_up(&ps2esdi_int
);