root/drivers/block/ht6560b.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qd6560b_selectproc
  2. try_to_init_ht6560b
  3. tune_ht6560b
  4. init_ht6560b

   1 /*
   2  *  linux/drivers/block/ht6580.c       Version 0.01  Feb 06, 1996
   3  *
   4  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
   5  */
   6 
   7 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
   8 
   9 #include <linux/types.h>
  10 #include <linux/kernel.h>
  11 #include <linux/delay.h>
  12 #include <linux/timer.h>
  13 #include <linux/mm.h>
  14 #include <linux/ioport.h>
  15 #include <linux/blkdev.h>
  16 #include <linux/hdreg.h>
  17 #include <asm/io.h>
  18 #include "ide.h"
  19 
  20 /*
  21  * This routine handles interface switching for the peculiar hardware design
  22  * on the F.G.I./Holtek HT-6560B VLB IDE interface.
  23  * The HT-6560B can only enable one IDE port at a time, and requires a
  24  * silly sequence (below) whenever we switch between primary and secondary.
  25  *
  26  * This stuff is courtesy of malafoss@snakemail.hut.fi
  27  *
  28  * At least one user has reported that this code can confuse the floppy
  29  * controller and/or driver -- perhaps this should be changed to use
  30  * a read-modify-write sequence, so as not to disturb other bits in the reg?
  31  */
  32 
  33 /*
  34  * We don't know what all of the bits are for, but we *do* know about these:
  35  *      bit5 (0x20): "1" selects slower speed (?)
  36  *      bit0 (0x01): "1" selects second interface
  37  */
  38 static byte qd6560b_selects [2][MAX_DRIVES] = {{0x3c,0x3c}, {0x3d,0x3d}};
  39 
  40 static void qd6560b_selectproc (ide_drive_t *drive)     /* called from ide.c */
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         static byte current_select = 0;
  43         byte drive_select = qd6560b_selects[HWIF(drive)->index][drive->select.b.unit];
  44 
  45         if (drive_select != current_select) {
  46                 byte t;
  47                 unsigned long flags;
  48                 save_flags (flags);
  49                 cli();
  50                 current_select = drive_select;
  51                 (void) inb(0x3e6);
  52                 (void) inb(0x3e6);
  53                 (void) inb(0x3e6);
  54                 /*
  55                  * Note: input bits are reversed to output bits!!
  56                  */
  57                 t = inb(0x3e6) ^ 0x3f;
  58                 t &= (~0x21);
  59                 t |= (current_select & 0x21);
  60                 outb(t,0x3e6);
  61                 restore_flags (flags);
  62         }
  63 }
  64 
  65 /*
  66  * Autodetection and initialization of ht6560b
  67  */
  68 int try_to_init_ht6560b(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         byte orig_value;
  71         int i;
  72 
  73         /* Autodetect ht6560b */
  74         if ((orig_value=inb(0x3e6)) == 0xff)
  75                 return 0;
  76 
  77         for (i=3;i>0;i--) {
  78                 outb(0x00,0x3e6);
  79                 if (!( (~inb(0x3e6)) & 0x3f )) {
  80                           outb(orig_value,0x3e6);
  81                           return 0;
  82                 }
  83         }
  84         outb(0x00,0x3e6);
  85         if ((~inb(0x3e6))& 0x3f) {
  86                 outb(orig_value,0x3e6);
  87                 return 0;
  88         }
  89         /* 
  90          * Ht6560b autodetected:
  91          *     reverse input bits to output bits
  92          *     initialize bit1 to 0
  93          */
  94         outb((orig_value ^ 0x3f) & 0xfd,0x3e6);
  95         printk("ht6560b: detected and initialized\n");
  96         return 1;
  97 }
  98 
  99 static void tune_ht6560b (ide_drive_t *drive, byte pio)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101         unsigned int hwif, unit;
 102 
 103         if (pio == 255)  {      /* auto-tune */
 104                 if (drive->media != ide_disk) {
 105                         pio = 0; /* cdroms don't like our fast mode */
 106                 } else {
 107                         struct hd_driveid *id = drive->id;
 108                         pio = id->tPIO;
 109                         if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x01))
 110                                 pio = 3;
 111                 }
 112         }
 113         hwif = HWIF(drive)->index;
 114         unit = drive->select.b.unit;
 115         if (pio < 3)
 116                 qd6560b_selects[hwif][unit] |= 0x20;
 117         else
 118                 qd6560b_selects[hwif][unit] &= ~0x20;
 119 }
 120 
 121 void init_ht6560b (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         if (check_region(0x3e6,1)) {
 124                 printk("\nht6560b: PORT 0x3e6 ALREADY IN USE\n");
 125         } else {
 126                 if (try_to_init_ht6560b()) {
 127                         request_region(0x3e6, 1, "ht6560b");
 128                         ide_hwifs[0].chipset = ide_ht6560b;
 129                         ide_hwifs[1].chipset = ide_ht6560b;
 130                         ide_hwifs[0].selectproc = &qd6560b_selectproc;
 131                         ide_hwifs[1].selectproc = &qd6560b_selectproc;
 132                         ide_hwifs[0].tuneproc = &tune_ht6560b;
 133                         ide_hwifs[1].tuneproc = &tune_ht6560b;
 134                         ide_hwifs[0].serialized = 1;
 135                 }
 136         }
 137 }

/* [previous][next][first][last][top][bottom][index][help] */