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