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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [sun3x_esp.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* sun3x_esp.c:  EnhancedScsiProcessor Sun3x SCSI driver code.
2
 *
3
 * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
4
 *
5
 * Based on David S. Miller's esp driver
6
 */
7
 
8
#include <linux/kernel.h>
9
#include <linux/types.h>
10
#include <linux/string.h>
11
#include <linux/slab.h>
12
#include <linux/blk.h>
13
#include <linux/proc_fs.h>
14
#include <linux/stat.h>
15
#include <linux/delay.h>
16
 
17
#include "scsi.h"
18
#include "hosts.h"
19
#include "NCR53C9x.h"
20
 
21
#include "sun3x_esp.h"
22
#include <asm/sun3x.h>
23
#include <asm/dvma.h>
24
#include <asm/irq.h>
25
 
26
extern struct NCR_ESP *espchain;
27
 
28
static void dma_barrier(struct NCR_ESP *esp);
29
static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
30
static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
31
static void dma_drain(struct NCR_ESP *esp);
32
static void dma_invalidate(struct NCR_ESP *esp);
33
static void dma_dump_state(struct NCR_ESP *esp);
34
static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
35
static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
36
static void dma_ints_off(struct NCR_ESP *esp);
37
static void dma_ints_on(struct NCR_ESP *esp);
38
static int  dma_irq_p(struct NCR_ESP *esp);
39
static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr);
40
static int  dma_ports_p(struct NCR_ESP *esp);
41
static void dma_reset(struct NCR_ESP *esp);
42
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
43
static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
44
static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
45
static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
46
static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
47
static void dma_advance_sg (Scsi_Cmnd *sp);
48
 
49
#if 0
50
/* This is where all commands are put before they are trasfered to the ESP chip
51
 * via PIO.
52
 */
53
static volatile unsigned char cmd_buffer[16];
54
#endif
55
 
56
/* Detecting ESP chips on the machine.  This is the simple and easy
57
 * version.
58
 */
59
int sun3x_esp_detect(Scsi_Host_Template *tpnt)
60
{
61
        struct NCR_ESP *esp;
62
        struct ConfigDev *esp_dev;
63
 
64
        esp_dev = 0;
65
        esp = esp_allocate(tpnt, (void *) esp_dev);
66
 
67
        /* Do command transfer with DMA */
68
        esp->do_pio_cmds = 0;
69
 
70
        /* Required functions */
71
        esp->dma_bytes_sent = &dma_bytes_sent;
72
        esp->dma_can_transfer = &dma_can_transfer;
73
        esp->dma_dump_state = &dma_dump_state;
74
        esp->dma_init_read = &dma_init_read;
75
        esp->dma_init_write = &dma_init_write;
76
        esp->dma_ints_off = &dma_ints_off;
77
        esp->dma_ints_on = &dma_ints_on;
78
        esp->dma_irq_p = &dma_irq_p;
79
        esp->dma_ports_p = &dma_ports_p;
80
        esp->dma_setup = &dma_setup;
81
 
82
        /* Optional functions */
83
        esp->dma_barrier = &dma_barrier;
84
        esp->dma_invalidate = &dma_invalidate;
85
        esp->dma_drain = &dma_drain;
86
        esp->dma_irq_entry = 0;
87
        esp->dma_irq_exit = 0;
88
        esp->dma_led_on = 0;
89
        esp->dma_led_off = 0;
90
        esp->dma_poll = &dma_poll;
91
        esp->dma_reset = &dma_reset;
92
 
93
        /* virtual DMA functions */
94
        esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
95
        esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
96
        esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
97
        esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
98
        esp->dma_advance_sg = &dma_advance_sg;
99
 
100
        /* SCSI chip speed */
101
        esp->cfreq = 20000000;
102
        esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE);
103
        esp->dregs = (void *)SUN3X_ESP_DMA;
104
 
105
#if 0
106
        esp->esp_command = (volatile unsigned char *)cmd_buffer;
107
        esp->esp_command_dvma = dvma_map((unsigned long)cmd_buffer,
108
                                         sizeof (cmd_buffer));
109
#else
110
        esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE);
111
        esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command);
112
#endif
113
 
114
        esp->irq = 2;
115
        if (request_irq(esp->irq, esp_intr, SA_INTERRUPT,
116
                        "SUN3X SCSI", NULL)) {
117
                esp_deallocate(esp);
118
                return 0;
119
        }
120
 
121
        esp->scsi_id = 7;
122
        esp->diff = 0;
123
 
124
        esp_initialize(esp);
125
 
126
        /* for reasons beyond my knowledge (and which should likely be fixed)
127
           sync mode doesn't work on a 3/80 at 5mhz.  but it does at 4. */
128
        esp->sync_defp = 0x3f;
129
 
130
        printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
131
               esps_in_use);
132
        esps_running = esps_in_use;
133
        return esps_in_use;
134
}
135
 
136
static void dma_do_drain(struct NCR_ESP *esp)
137
{
138
        struct sparc_dma_registers *dregs =
139
                (struct sparc_dma_registers *) esp->dregs;
140
 
141
        int count = 500000;
142
 
143
        while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0))
144
                udelay(1);
145
 
146
        if(!count) {
147
                printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
148
        }
149
 
150
        dregs->cond_reg |= DMA_FIFO_STDRAIN;
151
 
152
        count = 500000;
153
 
154
        while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0))
155
                udelay(1);
156
 
157
        if(!count) {
158
                printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
159
        }
160
 
161
}
162
 
163
static void dma_barrier(struct NCR_ESP *esp)
164
{
165
        struct sparc_dma_registers *dregs =
166
                (struct sparc_dma_registers *) esp->dregs;
167
        int count = 500000;
168
 
169
        while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0))
170
                udelay(1);
171
 
172
        if(!count) {
173
                printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
174
        }
175
 
176
        dregs->cond_reg &= ~(DMA_ENABLE);
177
}
178
 
179
/* This uses various DMA csr fields and the fifo flags count value to
180
 * determine how many bytes were successfully sent/received by the ESP.
181
 */
182
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
183
{
184
        struct sparc_dma_registers *dregs =
185
                (struct sparc_dma_registers *) esp->dregs;
186
 
187
        int rval = dregs->st_addr - esp->esp_command_dvma;
188
 
189
        return rval - fifo_count;
190
}
191
 
192
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
193
{
194
        return sp->SCp.this_residual;
195
}
196
 
197
static void dma_drain(struct NCR_ESP *esp)
198
{
199
        struct sparc_dma_registers *dregs =
200
                (struct sparc_dma_registers *) esp->dregs;
201
        int count = 500000;
202
 
203
        if(dregs->cond_reg & DMA_FIFO_ISDRAIN) {
204
                dregs->cond_reg |= DMA_FIFO_STDRAIN;
205
                while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0))
206
                        udelay(1);
207
                if(!count) {
208
                        printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
209
                }
210
 
211
        }
212
}
213
 
214
static void dma_invalidate(struct NCR_ESP *esp)
215
{
216
        struct sparc_dma_registers *dregs =
217
                (struct sparc_dma_registers *) esp->dregs;
218
 
219
        __u32 tmp;
220
        int count = 500000;
221
 
222
        while(((tmp = dregs->cond_reg) & DMA_PEND_READ) && (--count > 0))
223
                udelay(1);
224
 
225
        if(!count) {
226
                printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
227
        }
228
 
229
        dregs->cond_reg = tmp | DMA_FIFO_INV;
230
        dregs->cond_reg &= ~DMA_FIFO_INV;
231
 
232
}
233
 
234
static void dma_dump_state(struct NCR_ESP *esp)
235
{
236
        struct sparc_dma_registers *dregs =
237
                (struct sparc_dma_registers *) esp->dregs;
238
 
239
        ESPLOG(("esp%d: dma -- cond_reg<%08lx> addr<%08lx>\n",
240
                esp->esp_id, dregs->cond_reg, dregs->st_addr));
241
}
242
 
243
static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
244
{
245
        struct sparc_dma_registers *dregs =
246
                (struct sparc_dma_registers *) esp->dregs;
247
 
248
        dregs->st_addr = vaddress;
249
        dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
250
}
251
 
252
static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
253
{
254
        struct sparc_dma_registers *dregs =
255
                (struct sparc_dma_registers *) esp->dregs;
256
 
257
        /* Set up the DMA counters */
258
 
259
        dregs->st_addr = vaddress;
260
        dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE);
261
}
262
 
263
static void dma_ints_off(struct NCR_ESP *esp)
264
{
265
        DMA_INTSOFF((struct sparc_dma_registers *) esp->dregs);
266
}
267
 
268
static void dma_ints_on(struct NCR_ESP *esp)
269
{
270
        DMA_INTSON((struct sparc_dma_registers *) esp->dregs);
271
}
272
 
273
static int dma_irq_p(struct NCR_ESP *esp)
274
{
275
        return DMA_IRQ_P((struct sparc_dma_registers *) esp->dregs);
276
}
277
 
278
static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr)
279
{
280
        int count = 50;
281
        dma_do_drain(esp);
282
 
283
        /* Wait till the first bits settle. */
284
        while((*(volatile unsigned char *)vaddr == 0xff) && (--count > 0))
285
                udelay(1);
286
 
287
        if(!count) {
288
//              printk("%s:%d timeout expire (data %02x)\n", __FILE__, __LINE__,
289
//                     esp_read(esp->eregs->esp_fdata));
290
                //mach_halt();
291
                vaddr[0] = esp_read(esp->eregs->esp_fdata);
292
                vaddr[1] = esp_read(esp->eregs->esp_fdata);
293
        }
294
 
295
}
296
 
297
static int dma_ports_p(struct NCR_ESP *esp)
298
{
299
        return (((struct sparc_dma_registers *) esp->dregs)->cond_reg
300
                        & DMA_INT_ENAB);
301
}
302
 
303
/* Resetting various pieces of the ESP scsi driver chipset/buses. */
304
static void dma_reset(struct NCR_ESP *esp)
305
{
306
        struct sparc_dma_registers *dregs =
307
                (struct sparc_dma_registers *)esp->dregs;
308
 
309
        /* Punt the DVMA into a known state. */
310
        dregs->cond_reg |= DMA_RST_SCSI;
311
        dregs->cond_reg &= ~(DMA_RST_SCSI);
312
        DMA_INTSON(dregs);
313
}
314
 
315
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
316
{
317
        struct sparc_dma_registers *dregs =
318
                (struct sparc_dma_registers *) esp->dregs;
319
        unsigned long nreg = dregs->cond_reg;
320
 
321
//      printk("dma_setup %c addr %08x cnt %08x\n",
322
//             write ? 'W' : 'R', addr, count);
323
 
324
        dma_do_drain(esp);
325
 
326
        if(write)
327
                nreg |= DMA_ST_WRITE;
328
        else {
329
                nreg &= ~(DMA_ST_WRITE);
330
        }
331
 
332
        nreg |= DMA_ENABLE;
333
        dregs->cond_reg = nreg;
334
        dregs->st_addr = addr;
335
}
336
 
337
static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
338
{
339
    sp->SCp.have_data_in = dvma_map((unsigned long)sp->SCp.buffer,
340
                                       sp->SCp.this_residual);
341
    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
342
}
343
 
344
static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
345
{
346
    int sz = sp->SCp.buffers_residual;
347
    struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
348
 
349
    while (sz >= 0) {
350
        sg[sz].dvma_addr = dvma_map((unsigned long)sg[sz].addr, sg[sz].len);
351
        sz--;
352
    }
353
    sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address);
354
}
355
 
356
static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
357
{
358
    dvma_unmap((char *)sp->SCp.have_data_in);
359
}
360
 
361
static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
362
{
363
    int sz = sp->use_sg - 1;
364
    struct mmu_sglist *sg = (struct mmu_sglist *)sp->buffer;
365
 
366
    while(sz >= 0) {
367
        dvma_unmap((char *)sg[sz].dvma_addr);
368
        sz--;
369
    }
370
}
371
 
372
static void dma_advance_sg (Scsi_Cmnd *sp)
373
{
374
    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
375
}
376
 
377
static Scsi_Host_Template driver_template = SCSI_SUN3X_ESP;
378
 
379
#include "scsi_module.c"
380
 
381
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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