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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [dsp56k.c] - Blame information for rev 65

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

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * The DSP56001 Device Driver, saviour of the Free World(tm)
3
 *
4
 * Authors: Fredrik Noring   <noring@nocrew.org>
5
 *          lars brinkhoff   <lars@nocrew.org>
6
 *          Tomas Berndtsson <tomas@nocrew.org>
7
 *
8
 * First version May 1996
9
 *
10
 * History:
11
 *  97-01-29   Tomas Berndtsson,
12
 *               Integrated with Linux 2.1.21 kernel sources.
13
 *  97-02-15   Tomas Berndtsson,
14
 *               Fixed for kernel 2.1.26
15
 *
16
 * BUGS:
17
 *  Hmm... there must be something here :)
18
 *
19
 * Copyright (C) 1996,1997 Fredrik Noring, lars brinkhoff & Tomas Berndtsson
20
 *
21
 * This file is subject to the terms and conditions of the GNU General Public
22
 * License.  See the file COPYING in the main directory of this archive
23
 * for more details.
24
 */
25
 
26
#include <linux/module.h>
27
#include <linux/slab.h> /* for kmalloc() and kfree() */
28
#include <linux/major.h>
29
#include <linux/types.h>
30
#include <linux/errno.h>
31
#include <linux/delay.h>        /* guess what */
32
#include <linux/fs.h>
33
#include <linux/mm.h>
34
#include <linux/init.h>
35
#include <linux/device.h>
36
 
37
#include <asm/atarihw.h>
38
#include <asm/traps.h>
39
#include <asm/uaccess.h>        /* For put_user and get_user */
40
 
41
#include <asm/dsp56k.h>
42
 
43
/* minor devices */
44
#define DSP56K_DEV_56001        0    /* The only device so far */
45
 
46
#define TIMEOUT    10   /* Host port timeout in number of tries */
47
#define MAXIO    2048   /* Maximum number of words before sleep */
48
#define DSP56K_MAX_BINARY_LENGTH (3*64*1024)
49
 
50
#define DSP56K_TX_INT_ON        dsp56k_host_interface.icr |=  DSP56K_ICR_TREQ
51
#define DSP56K_RX_INT_ON        dsp56k_host_interface.icr |=  DSP56K_ICR_RREQ
52
#define DSP56K_TX_INT_OFF       dsp56k_host_interface.icr &= ~DSP56K_ICR_TREQ
53
#define DSP56K_RX_INT_OFF       dsp56k_host_interface.icr &= ~DSP56K_ICR_RREQ
54
 
55
#define DSP56K_TRANSMIT         (dsp56k_host_interface.isr & DSP56K_ISR_TXDE)
56
#define DSP56K_RECEIVE          (dsp56k_host_interface.isr & DSP56K_ISR_RXDF)
57
 
58
#define handshake(count, maxio, timeout, ENABLE, f) \
59
{ \
60
        long i, t, m; \
61
        while (count > 0) { \
62
                m = min_t(unsigned long, count, maxio); \
63
                for (i = 0; i < m; i++) { \
64
                        for (t = 0; t < timeout && !ENABLE; t++) \
65
                                msleep(20); \
66
                        if(!ENABLE) \
67
                                return -EIO; \
68
                        f; \
69
                } \
70
                count -= m; \
71
                if (m == maxio) msleep(20); \
72
        } \
73
}
74
 
75
#define tx_wait(n) \
76
{ \
77
        int t; \
78
        for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \
79
                msleep(10); \
80
        if(!DSP56K_TRANSMIT) { \
81
                return -EIO; \
82
        } \
83
}
84
 
85
#define rx_wait(n) \
86
{ \
87
        int t; \
88
        for(t = 0; t < n && !DSP56K_RECEIVE; t++) \
89
                msleep(10); \
90
        if(!DSP56K_RECEIVE) { \
91
                return -EIO; \
92
        } \
93
}
94
 
95
/* DSP56001 bootstrap code */
96
static char bootstrap[] = {
97
        0x0c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116
        0x00, 0x00, 0x60, 0xf4, 0x00, 0x00, 0x00, 0x4f, 0x61, 0xf4,
117
        0x00, 0x00, 0x7e, 0xa9, 0x06, 0x2e, 0x80, 0x00, 0x00, 0x47,
118
        0x07, 0xd8, 0x84, 0x07, 0x59, 0x84, 0x08, 0xf4, 0xa8, 0x00,
119
        0x00, 0x04, 0x08, 0xf4, 0xbf, 0x00, 0x0c, 0x00, 0x00, 0xfe,
120
        0xb8, 0x0a, 0xf0, 0x80, 0x00, 0x7e, 0xa9, 0x08, 0xf4, 0xa0,
121
        0x00, 0x00, 0x01, 0x08, 0xf4, 0xbe, 0x00, 0x00, 0x00, 0x0a,
122
        0xa9, 0x80, 0x00, 0x7e, 0xad, 0x08, 0x4e, 0x2b, 0x44, 0xf4,
123
        0x00, 0x00, 0x00, 0x03, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x01,
124
        0x0e, 0xa0, 0x00, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb5, 0x08,
125
        0x50, 0x2b, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb8, 0x08, 0x46,
126
        0x2b, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x02, 0x0a, 0xf0, 0xaa,
127
        0x00, 0x7e, 0xc9, 0x20, 0x00, 0x45, 0x0a, 0xf0, 0xaa, 0x00,
128
        0x7e, 0xd0, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xc6, 0x0a, 0xa9,
129
        0x80, 0x00, 0x7e, 0xc4, 0x08, 0x58, 0x6b, 0x0a, 0xf0, 0x80,
130
        0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xcd, 0x0a,
131
        0xa9, 0x80, 0x00, 0x7e, 0xcb, 0x08, 0x58, 0xab, 0x0a, 0xf0,
132
        0x80, 0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xd4,
133
        0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xd2, 0x08, 0x58, 0xeb, 0x0a,
134
        0xf0, 0x80, 0x00, 0x7e, 0xad};
135
static int sizeof_bootstrap = 375;
136
 
137
 
138
static struct dsp56k_device {
139
        unsigned long in_use;
140
        long maxio, timeout;
141
        int tx_wsize, rx_wsize;
142
} dsp56k;
143
 
144
static struct class *dsp56k_class;
145
 
146
static int dsp56k_reset(void)
147
{
148
        u_char status;
149
 
150
        /* Power down the DSP */
151
        sound_ym.rd_data_reg_sel = 14;
152
        status = sound_ym.rd_data_reg_sel & 0xef;
153
        sound_ym.wd_data = status;
154
        sound_ym.wd_data = status | 0x10;
155
 
156
        udelay(10);
157
 
158
        /* Power up the DSP */
159
        sound_ym.rd_data_reg_sel = 14;
160
        sound_ym.wd_data = sound_ym.rd_data_reg_sel & 0xef;
161
 
162
        return 0;
163
}
164
 
165
static int dsp56k_upload(u_char __user *bin, int len)
166
{
167
        int i;
168
        u_char *p;
169
 
170
        dsp56k_reset();
171
 
172
        p = bootstrap;
173
        for (i = 0; i < sizeof_bootstrap/3; i++) {
174
                /* tx_wait(10); */
175
                dsp56k_host_interface.data.b[1] = *p++;
176
                dsp56k_host_interface.data.b[2] = *p++;
177
                dsp56k_host_interface.data.b[3] = *p++;
178
        }
179
        for (; i < 512; i++) {
180
                /* tx_wait(10); */
181
                dsp56k_host_interface.data.b[1] = 0;
182
                dsp56k_host_interface.data.b[2] = 0;
183
                dsp56k_host_interface.data.b[3] = 0;
184
        }
185
 
186
        for (i = 0; i < len; i++) {
187
                tx_wait(10);
188
                get_user(dsp56k_host_interface.data.b[1], bin++);
189
                get_user(dsp56k_host_interface.data.b[2], bin++);
190
                get_user(dsp56k_host_interface.data.b[3], bin++);
191
        }
192
 
193
        tx_wait(10);
194
        dsp56k_host_interface.data.l = 3;    /* Magic execute */
195
 
196
        return 0;
197
}
198
 
199
static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
200
                           loff_t *ppos)
201
{
202
        struct inode *inode = file->f_path.dentry->d_inode;
203
        int dev = iminor(inode) & 0x0f;
204
 
205
        switch(dev)
206
        {
207
        case DSP56K_DEV_56001:
208
        {
209
 
210
                long n;
211
 
212
                /* Don't do anything if nothing is to be done */
213
                if (!count) return 0;
214
 
215
                n = 0;
216
                switch (dsp56k.rx_wsize) {
217
                case 1:  /* 8 bit */
218
                {
219
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
220
                                  put_user(dsp56k_host_interface.data.b[3], buf+n++));
221
                        return n;
222
                }
223
                case 2:  /* 16 bit */
224
                {
225
                        short __user *data;
226
 
227
                        count /= 2;
228
                        data = (short __user *) buf;
229
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
230
                                  put_user(dsp56k_host_interface.data.w[1], data+n++));
231
                        return 2*n;
232
                }
233
                case 3:  /* 24 bit */
234
                {
235
                        count /= 3;
236
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
237
                                  put_user(dsp56k_host_interface.data.b[1], buf+n++);
238
                                  put_user(dsp56k_host_interface.data.b[2], buf+n++);
239
                                  put_user(dsp56k_host_interface.data.b[3], buf+n++));
240
                        return 3*n;
241
                }
242
                case 4:  /* 32 bit */
243
                {
244
                        long __user *data;
245
 
246
                        count /= 4;
247
                        data = (long __user *) buf;
248
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
249
                                  put_user(dsp56k_host_interface.data.l, data+n++));
250
                        return 4*n;
251
                }
252
                }
253
                return -EFAULT;
254
        }
255
 
256
        default:
257
                printk(KERN_ERR "DSP56k driver: Unknown minor device: %d\n", dev);
258
                return -ENXIO;
259
        }
260
}
261
 
262
static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count,
263
                            loff_t *ppos)
264
{
265
        struct inode *inode = file->f_path.dentry->d_inode;
266
        int dev = iminor(inode) & 0x0f;
267
 
268
        switch(dev)
269
        {
270
        case DSP56K_DEV_56001:
271
        {
272
                long n;
273
 
274
                /* Don't do anything if nothing is to be done */
275
                if (!count) return 0;
276
 
277
                n = 0;
278
                switch (dsp56k.tx_wsize) {
279
                case 1:  /* 8 bit */
280
                {
281
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
282
                                  get_user(dsp56k_host_interface.data.b[3], buf+n++));
283
                        return n;
284
                }
285
                case 2:  /* 16 bit */
286
                {
287
                        const short __user *data;
288
 
289
                        count /= 2;
290
                        data = (const short __user *)buf;
291
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
292
                                  get_user(dsp56k_host_interface.data.w[1], data+n++));
293
                        return 2*n;
294
                }
295
                case 3:  /* 24 bit */
296
                {
297
                        count /= 3;
298
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
299
                                  get_user(dsp56k_host_interface.data.b[1], buf+n++);
300
                                  get_user(dsp56k_host_interface.data.b[2], buf+n++);
301
                                  get_user(dsp56k_host_interface.data.b[3], buf+n++));
302
                        return 3*n;
303
                }
304
                case 4:  /* 32 bit */
305
                {
306
                        const long __user *data;
307
 
308
                        count /= 4;
309
                        data = (const long __user *)buf;
310
                        handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
311
                                  get_user(dsp56k_host_interface.data.l, data+n++));
312
                        return 4*n;
313
                }
314
                }
315
 
316
                return -EFAULT;
317
        }
318
        default:
319
                printk(KERN_ERR "DSP56k driver: Unknown minor device: %d\n", dev);
320
                return -ENXIO;
321
        }
322
}
323
 
324
static int dsp56k_ioctl(struct inode *inode, struct file *file,
325
                        unsigned int cmd, unsigned long arg)
326
{
327
        int dev = iminor(inode) & 0x0f;
328
        void __user *argp = (void __user *)arg;
329
 
330
        switch(dev)
331
        {
332
        case DSP56K_DEV_56001:
333
 
334
                switch(cmd) {
335
                case DSP56K_UPLOAD:
336
                {
337
                        char __user *bin;
338
                        int r, len;
339
                        struct dsp56k_upload __user *binary = argp;
340
 
341
                        if(get_user(len, &binary->len) < 0)
342
                                return -EFAULT;
343
                        if(get_user(bin, &binary->bin) < 0)
344
                                return -EFAULT;
345
 
346
                        if (len == 0) {
347
                                return -EINVAL;      /* nothing to upload?!? */
348
                        }
349
                        if (len > DSP56K_MAX_BINARY_LENGTH) {
350
                                return -EINVAL;
351
                        }
352
 
353
                        r = dsp56k_upload(bin, len);
354
                        if (r < 0) {
355
                                return r;
356
                        }
357
 
358
                        break;
359
                }
360
                case DSP56K_SET_TX_WSIZE:
361
                        if (arg > 4 || arg < 1)
362
                                return -EINVAL;
363
                        dsp56k.tx_wsize = (int) arg;
364
                        break;
365
                case DSP56K_SET_RX_WSIZE:
366
                        if (arg > 4 || arg < 1)
367
                                return -EINVAL;
368
                        dsp56k.rx_wsize = (int) arg;
369
                        break;
370
                case DSP56K_HOST_FLAGS:
371
                {
372
                        int dir, out, status;
373
                        struct dsp56k_host_flags __user *hf = argp;
374
 
375
                        if(get_user(dir, &hf->dir) < 0)
376
                                return -EFAULT;
377
                        if(get_user(out, &hf->out) < 0)
378
                                return -EFAULT;
379
 
380
                        if ((dir & 0x1) && (out & 0x1))
381
                                dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
382
                        else if (dir & 0x1)
383
                                dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0;
384
                        if ((dir & 0x2) && (out & 0x2))
385
                                dsp56k_host_interface.icr |= DSP56K_ICR_HF1;
386
                        else if (dir & 0x2)
387
                                dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1;
388
 
389
                        status = 0;
390
                        if (dsp56k_host_interface.icr & DSP56K_ICR_HF0) status |= 0x1;
391
                        if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
392
                        if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
393
                        if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
394
 
395
                        return put_user(status, &hf->status);
396
                }
397
                case DSP56K_HOST_CMD:
398
                        if (arg > 31 || arg < 0)
399
                                return -EINVAL;
400
                        dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
401
                                                             DSP56K_CVR_HC);
402
                        break;
403
                default:
404
                        return -EINVAL;
405
                }
406
                return 0;
407
 
408
        default:
409
                printk(KERN_ERR "DSP56k driver: Unknown minor device: %d\n", dev);
410
                return -ENXIO;
411
        }
412
}
413
 
414
/* As of 2.1.26 this should be dsp56k_poll,
415
 * but how do I then check device minor number?
416
 * Do I need this function at all???
417
 */
418
#if 0
419
static unsigned int dsp56k_poll(struct file *file, poll_table *wait)
420
{
421
        int dev = iminor(file->f_path.dentry->d_inode) & 0x0f;
422
 
423
        switch(dev)
424
        {
425
        case DSP56K_DEV_56001:
426
                /* poll_wait(file, ???, wait); */
427
                return POLLIN | POLLRDNORM | POLLOUT;
428
 
429
        default:
430
                printk("DSP56k driver: Unknown minor device: %d\n", dev);
431
                return 0;
432
        }
433
}
434
#endif
435
 
436
static int dsp56k_open(struct inode *inode, struct file *file)
437
{
438
        int dev = iminor(inode) & 0x0f;
439
 
440
        switch(dev)
441
        {
442
        case DSP56K_DEV_56001:
443
 
444
                if (test_and_set_bit(0, &dsp56k.in_use))
445
                        return -EBUSY;
446
 
447
                dsp56k.timeout = TIMEOUT;
448
                dsp56k.maxio = MAXIO;
449
                dsp56k.rx_wsize = dsp56k.tx_wsize = 4;
450
 
451
                DSP56K_TX_INT_OFF;
452
                DSP56K_RX_INT_OFF;
453
 
454
                /* Zero host flags */
455
                dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0;
456
                dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1;
457
 
458
                break;
459
 
460
        default:
461
                return -ENODEV;
462
        }
463
 
464
        return 0;
465
}
466
 
467
static int dsp56k_release(struct inode *inode, struct file *file)
468
{
469
        int dev = iminor(inode) & 0x0f;
470
 
471
        switch(dev)
472
        {
473
        case DSP56K_DEV_56001:
474
                clear_bit(0, &dsp56k.in_use);
475
                break;
476
        default:
477
                printk(KERN_ERR "DSP56k driver: Unknown minor device: %d\n", dev);
478
                return -ENXIO;
479
        }
480
 
481
        return 0;
482
}
483
 
484
static const struct file_operations dsp56k_fops = {
485
        .owner          = THIS_MODULE,
486
        .read           = dsp56k_read,
487
        .write          = dsp56k_write,
488
        .ioctl          = dsp56k_ioctl,
489
        .open           = dsp56k_open,
490
        .release        = dsp56k_release,
491
};
492
 
493
 
494
/****** Init and module functions ******/
495
 
496
static char banner[] __initdata = KERN_INFO "DSP56k driver installed\n";
497
 
498
static int __init dsp56k_init_driver(void)
499
{
500
        int err = 0;
501
 
502
        if(!MACH_IS_ATARI || !ATARIHW_PRESENT(DSP56K)) {
503
                printk("DSP56k driver: Hardware not present\n");
504
                return -ENODEV;
505
        }
506
 
507
        if(register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) {
508
                printk("DSP56k driver: Unable to register driver\n");
509
                return -ENODEV;
510
        }
511
        dsp56k_class = class_create(THIS_MODULE, "dsp56k");
512
        if (IS_ERR(dsp56k_class)) {
513
                err = PTR_ERR(dsp56k_class);
514
                goto out_chrdev;
515
        }
516
        device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k");
517
 
518
        printk(banner);
519
        goto out;
520
 
521
out_chrdev:
522
        unregister_chrdev(DSP56K_MAJOR, "dsp56k");
523
out:
524
        return err;
525
}
526
module_init(dsp56k_init_driver);
527
 
528
static void __exit dsp56k_cleanup_driver(void)
529
{
530
        device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
531
        class_destroy(dsp56k_class);
532
        unregister_chrdev(DSP56K_MAJOR, "dsp56k");
533
}
534
module_exit(dsp56k_cleanup_driver);
535
 
536
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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