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