~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/block/ps2esdi.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.