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

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