root/drivers/block/promise.c

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

DEFINITIONS

This source file includes following definitions.
  1. promise_selectproc
  2. promise_cmd
  3. setup_dc4030
  4. init_dc4030
  5. promise_read_intr
  6. promise_write_pollfunc
  7. promise_write
  8. do_promise_io

   1 /*
   2  *  linux/drivers/block/promise.c       Version 0.04  Mar 15, 1996
   3  *
   4  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
   5  */
   6 
   7 /*
   8  *  Principal Author/Maintainer:  peterd@pnd-pc.demon.co.uk
   9  *
  10  *  This file provides support for the second port and cache of Promise
  11  *  IDE interfaces, e.g. DC4030, DC5030.
  12  *
  13  *  Thanks are due to Mark Lord for advice and patiently answering stupid
  14  *  questions, and all those mugs^H^H^H^Hbrave souls who've tested this.
  15  *
  16  *  Version 0.01        Initial version, #include'd in ide.c rather than
  17  *                      compiled separately.
  18  *                      Reads use Promise commands, writes as before. Drives
  19  *                      on second channel are read-only.
  20  *  Version 0.02        Writes working on second channel, reads on both
  21  *                      channels. Writes fail under high load. Suspect
  22  *                      transfers of >127 sectors don't work.
  23  *  Version 0.03        Brought into line with ide.c version 5.27.
  24  *                      Other minor changes.
  25  *  Version 0.04        Updated for ide.c version 5.30
  26  *                      Changed initialization strategy
  27  *  Version 0.05        Kernel integration.  -ml
  28  *  Version 0.06        Ooops. Add hwgroup to direct call of ide_intr() -ml
  29  */
  30 
  31 
  32 /*
  33  * From:  'peterd@pnd-pc.demon.co.uk'
  34  *
  35  * Here's another version of the Promise driver for DC4030VL2 cards.
  36  * There have been few substantive changes to the code, but it is now in
  37  * line with the more recent ide.c changes, and is somewhat more configurable.
  38  *
  39  * Once you've compiled it in, you'll have to also enable the interface
  40  * setup routine from the kernel command line, as in 
  41  *
  42  *      'linux ide0=dc4030'
  43  *
  44  * As before, it seems that somewhere around 3Megs when writing, bad things
  45  * start to happen [timeouts/retries -ml]. If anyone can give me more feedback,
  46  * I'd really appreciate it.  [email: peterd@pnd-pc.demon.co.uk]
  47  *
  48  */
  49 
  50 
  51 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
  52 
  53 #include <linux/types.h>
  54 #include <linux/kernel.h>
  55 #include <linux/delay.h>
  56 #include <linux/timer.h>
  57 #include <linux/mm.h>
  58 #include <linux/ioport.h>
  59 #include <linux/blkdev.h>
  60 #include <linux/hdreg.h>
  61 #include <asm/io.h>
  62 #include <asm/irq.h>
  63 #include "ide.h"
  64 #include "promise.h"
  65 
  66 /* This is needed as the controller may not interrupt if the required data is
  67 available in the cache. We have to simulate an interrupt. Ugh! */
  68 
  69 extern void ide_intr(int, void *dev_id, struct pt_regs*);
  70 
  71 /*
  72  * promise_selectproc() is invoked by ide.c
  73  * in preparation for access to the specified drive.
  74  */
  75 static void promise_selectproc (ide_drive_t *drive)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77         unsigned int number;
  78 
  79         OUT_BYTE(drive->select.all,IDE_SELECT_REG);
  80         udelay(1);      /* paranoia */
  81         number = ((HWIF(drive)->is_promise2)<<1) + drive->select.b.unit;
  82         OUT_BYTE(number,IDE_FEATURE_REG);
  83 }
  84 
  85 /*
  86  * promise_cmd handles the set of vendor specific commands that are initiated
  87  * by command F0. They all have the same success/failure notification.
  88  */
  89 int promise_cmd(ide_drive_t *drive, byte cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         unsigned long timeout, timer;
  92         byte status_val;
  93 
  94         promise_selectproc(drive);      /* redundant? */
  95         OUT_BYTE(0xF3,IDE_SECTOR_REG);
  96         OUT_BYTE(cmd,IDE_SELECT_REG);
  97         OUT_BYTE(PROMISE_EXTENDED_COMMAND,IDE_COMMAND_REG);
  98         timeout = HZ * 10;
  99         timeout += jiffies;
 100         do {
 101                 if(jiffies > timeout) {
 102                         return 2; /* device timed out */
 103                 }
 104                 /* This is out of delay_10ms() */
 105                 /* Delays at least 10ms to give interface a chance */
 106                 timer = jiffies + (HZ + 99)/100 + 1;
 107                 while (timer > jiffies);
 108                 status_val = IN_BYTE(IDE_SECTOR_REG);
 109         } while (status_val != 0x50 && status_val != 0x70);
 110 
 111         if(status_val == 0x50)
 112                 return 0; /* device returned success */
 113         else
 114                 return 1; /* device returned failure */
 115 }
 116 
 117 ide_hwif_t *hwif_required = NULL;
 118 
 119 void setup_dc4030 (ide_hwif_t *hwif)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121     hwif_required = hwif;
 122 }
 123 
 124 /*
 125 init_dc4030: Test for presence of a Promise caching controller card.
 126 Returns: 0 if no Promise card present at this io_base
 127          1 if Promise card found
 128 */
 129 int init_dc4030 (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         ide_hwif_t *hwif = hwif_required;
 132         ide_drive_t *drive;
 133         ide_hwif_t *second_hwif;
 134         struct dc_ident ident;
 135         int i;
 136         
 137         if (!hwif) return 0;
 138 
 139         drive = &hwif->drives[0];
 140         second_hwif = &ide_hwifs[hwif->index+1];
 141         if(hwif->is_promise2) /* we've already been found ! */
 142             return 1;
 143 
 144         if(IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF)
 145         {
 146             return 0;
 147         }
 148         OUT_BYTE(0x08,IDE_CONTROL_REG);
 149         if(promise_cmd(drive,PROMISE_GET_CONFIG)) {
 150             return 0;
 151         }
 152         if(ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
 153             printk("%s: Failed Promise read config!\n",hwif->name);
 154             return 0;
 155         }
 156         ide_input_data(drive,&ident,SECTOR_WORDS);
 157         if(ident.id[1] != 'P' || ident.id[0] != 'T') {
 158             return 0;
 159         }
 160         printk("%s: Promise caching controller, ",hwif->name);
 161         switch(ident.type) {
 162             case 0x43:  printk("DC4030VL, "); break;
 163             default:    printk("unknown - type 0x%02x - please report!, "
 164                                ,ident.type);
 165                         return 0;
 166         }
 167         printk("%dKB cache, ",(int)ident.cache_mem);
 168         switch(ident.irq) {
 169             case 0x00: hwif->irq = 14; break;
 170             case 0x01: hwif->irq = 12; break;
 171             default:   hwif->irq = 15; break;
 172         }
 173         printk("on IRQ %d\n",hwif->irq);
 174         hwif->chipset    = second_hwif->chipset    = ide_promise;
 175         hwif->selectproc = second_hwif->selectproc = &promise_selectproc;
 176         second_hwif->is_promise2 = 1;
 177         second_hwif->io_base = hwif->io_base;
 178         second_hwif->ctl_port = hwif->ctl_port; 
 179         second_hwif->irq = hwif->irq;
 180         for (i=0; i<2 ; i++) {
 181             hwif->drives[i].io_32bit = 3;
 182             second_hwif->drives[i].io_32bit = 3;
 183             if(!ident.current_tm[i+2].cyl) second_hwif->drives[i].noprobe=1;
 184         }
 185         return 1;
 186 }
 187 
 188 /*
 189  * promise_read_intr() is the handler for disk read/multread interrupts
 190  */
 191 static void promise_read_intr (ide_drive_t *drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193         byte stat;
 194         int i;
 195         unsigned int sectors_left, sectors_avail, nsect;
 196         struct request *rq;
 197 
 198         if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
 199                 ide_error(drive, "promise_read_intr", stat);
 200                 return;
 201         }
 202 
 203 read_again:
 204         do {
 205             sectors_left = IN_BYTE(IDE_NSECTOR_REG);
 206             IN_BYTE(IDE_SECTOR_REG);
 207         } while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left);
 208         rq = HWGROUP(drive)->rq;
 209         sectors_avail = rq->nr_sectors - sectors_left;
 210 
 211 read_next:
 212         rq = HWGROUP(drive)->rq;
 213         if ((nsect = rq->current_nr_sectors) > sectors_avail)
 214                 nsect = sectors_avail;
 215         sectors_avail -= nsect;
 216         ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
 217 #ifdef DEBUG
 218         printk("%s:  promise_read: sectors(%ld-%ld), buffer=0x%08lx, "
 219                "remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, 
 220                (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
 221 #endif
 222         rq->sector += nsect;
 223         rq->buffer += nsect<<9;
 224         rq->errors = 0;
 225         i = (rq->nr_sectors -= nsect);
 226         if ((rq->current_nr_sectors -= nsect) <= 0)
 227                 ide_end_request(1, HWGROUP(drive));
 228         if (i > 0) {
 229                 if (sectors_avail)
 230                     goto read_next;
 231                 stat = GET_STAT();
 232                 if(stat & DRQ_STAT)
 233                     goto read_again;
 234                 if(stat & BUSY_STAT) {
 235                     ide_set_handler (drive, &promise_read_intr, WAIT_CMD);
 236                     return;
 237                 }
 238                 printk("Ah! promise read intr: sectors left !DRQ !BUSY\n");
 239                 ide_error(drive, "promise read intr", stat);
 240         }
 241 }
 242 
 243 /*
 244  * promise_write_pollfunc() is the handler for disk write completion polling.
 245  */
 246 static void promise_write_pollfunc (ide_drive_t *drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 247 {
 248         int i;
 249         ide_hwgroup_t *hwgroup = HWGROUP(drive);
 250         struct request *rq;
 251 
 252         if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
 253             if (jiffies < hwgroup->poll_timeout) {
 254                 ide_set_handler (drive, &promise_write_pollfunc, 1);
 255                 return; /* continue polling... */
 256             }
 257             printk("%s: write timed-out!\n",drive->name);
 258             ide_error (drive, "write timeout", GET_STAT());
 259             return;
 260         }
 261         
 262         ide_multwrite(drive, 4);
 263         rq = hwgroup->rq;
 264         for (i = rq->nr_sectors; i > 0;) {
 265             i -= rq->current_nr_sectors;
 266             ide_end_request(1, hwgroup);
 267         }
 268         return;
 269 }
 270 
 271 /*
 272  * promise_write() transfers a block of one or more sectors of data to a
 273  * drive as part of a disk write operation. All but 4 sectors are transfered
 274  * in the first attempt, then the interface is polled (nicely!) for completion
 275  * before the final 4 sectors are transfered. Don't ask me why, but this is
 276  * how it's done in the drivers for other O/Ses. There is no interrupt
 277  * generated on writes, which is why we have to do it like this.
 278  */
 279 static void promise_write (ide_drive_t *drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281     ide_hwgroup_t *hwgroup = HWGROUP(drive);
 282     struct request *rq = &hwgroup->wrq;
 283     int i;
 284 
 285     if (rq->nr_sectors > 4) {
 286         ide_multwrite(drive, rq->nr_sectors - 4);
 287         hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
 288         ide_set_handler (drive, &promise_write_pollfunc, 1);
 289         return;
 290     } else {
 291         ide_multwrite(drive, rq->nr_sectors);
 292         rq = hwgroup->rq;
 293         for (i = rq->nr_sectors; i > 0;) {
 294             i -= rq->current_nr_sectors;
 295             ide_end_request(1, hwgroup);
 296         }
 297     }
 298 }
 299 
 300 /*
 301  * do_promise_rw_disk() issues READ and WRITE commands to a
 302  * disk on a promise controller, using LBA to address sectors.  It also
 303  * takes care of issuing special DRIVE_CMDs.
 304  */
 305 void do_promise_io (ide_drive_t *drive, struct request *rq)
     /* [previous][next][first][last][top][bottom][index][help] */
 306 {
 307         unsigned long timeout;
 308         unsigned short io_base = HWIF(drive)->io_base;
 309         byte stat;
 310 
 311         if (rq->cmd == READ) {
 312             ide_set_handler(drive, &promise_read_intr, WAIT_CMD);
 313             OUT_BYTE(PROMISE_READ, io_base+IDE_COMMAND_OFFSET);
 314             /* The card's behaviour is odd at this point. If the data is
 315                available, DRQ will be true, and no interrupt will be
 316                generated by the card. If this is the case, we need to simulate
 317                an interrupt. Ugh! Otherwise, if an interrupt will occur, bit0
 318                of the SELECT register will be high, so we can just return and
 319                be interrupted.*/
 320             timeout = jiffies + HZ/20; /* 50ms wait */
 321             do {
 322                 stat=GET_STAT();
 323                 if(stat & DRQ_STAT) {
 324                     unsigned long flags;
 325                     save_flags(flags);
 326                     cli();
 327                     disable_irq(HWIF(drive)->irq);
 328                     ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
 329                     enable_irq(HWIF(drive)->irq);
 330                     restore_flags(flags);
 331                     return;
 332                 }
 333                 if(IN_BYTE(io_base+IDE_SELECT_OFFSET) & 0x01)
 334                     return;
 335             } while (jiffies < timeout);
 336             printk("%s: reading: No DRQ and not waiting - Odd!\n",
 337                    drive->name);
 338             return;
 339         }
 340         if (rq->cmd == WRITE) {
 341             OUT_BYTE(PROMISE_WRITE, io_base+IDE_COMMAND_OFFSET);
 342             if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
 343                 printk("%s: no DRQ after issuing PROMISE_WRITE\n", drive->name);
 344                 return;
 345             }
 346             if (!drive->unmask)
 347                 cli();
 348             HWGROUP(drive)->wrq = *rq; /* scratchpad */
 349             promise_write(drive);
 350             return;
 351         }
 352         printk("%s: bad command: %d\n", drive->name, rq->cmd);
 353         ide_end_request(0, HWGROUP(drive));
 354 }

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