OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [block/] [promise.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*  -*- 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)
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)
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)
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)
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)
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)
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)
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)
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.