highlevel.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:11k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.   **********************************************************************
  3.   *
  4.   *     Copyright 1999, 2000 Creative Labs, Inc.
  5.   *
  6.   **********************************************************************
  7.   *
  8.   *     Date                 Author               Summary of changes
  9.   *     ----                 ------               ------------------
  10.   *     October 20, 1999     Andrew de Quincey    Rewrote and extended
  11.   *                          Lucien Murray-Pitts  original incomplete 
  12.   *                                               driver.
  13.   *
  14.   *     April 18, 1999       Andrew Veliath       Original Driver
  15.   *                                               implementation
  16.   *
  17.   **********************************************************************
  18.   *
  19.   *     This program is free software; you can redistribute it and/or
  20.   *     modify it under the terms of the GNU General Public License as
  21.   *     published by the Free Software Foundation; either version 2 of
  22.   *     the License, or (at your option) any later version.
  23.   *
  24.   *     This program is distributed in the hope that it will be useful,
  25.   *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.   *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.   *     GNU General Public License for more details.
  28.   *
  29.   *     You should have received a copy of the GNU General Public
  30.   *     License along with this program; if not, write to the Free
  31.   *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  32.   *     USA.
  33.   *
  34.   **********************************************************************
  35.   */
  36. /**
  37.  *
  38.  * Overall driver for the Creative DXR2 card
  39.  * High level misc functions
  40.  *
  41.  */
  42. #include <linux/errno.h>
  43. #include <linux/sched.h>
  44. #include <linux/interrupt.h>
  45. #include <linux/delay.h>
  46. #include <asm/uaccess.h>
  47. #include <asm/io.h>
  48. #include <dxr2.h>
  49. #include <vxp524.h>
  50. #include <zivaDS.h>
  51. #include <pcm1723.h>
  52. #include <bt865.h>
  53. #include <tc6807af.h>
  54. #include "highlevel.h"
  55. #include "asic.h"
  56. /**
  57.  *
  58.  * Table of bitstream-specific transfer parameters. These are determined by hand
  59.  * The size of each allocated bm buffer MUST be geater then or equal to
  60.  * each of these
  61.  *
  62.  */
  63. static int thresholdsTable[] = {
  64.   
  65.   0x8000,  // DVD transfer size
  66.   40000,   // DVD min video buffer size
  67.   10000,   // DVD min audio buffer size
  68.   0x2000,  // VCD (CDROM) transfer size
  69.   40000,   // VCD min video buffer size
  70.   10000,   // VCD min audio buffer size
  71.   0x2000,  // VCD (DECODED) transfer size
  72.   40000,   // VCD min video buffer size
  73.   10000,   // VCD min audio buffer size
  74.   0x1000,  // CDDA transfer size
  75.   40000,   // CDDA min video buffer size
  76.   10000,   // CDDA min audio buffer size
  77.   0x1000,   // ??
  78.   40000,   // ??
  79.   10000    // ??
  80. };
  81. /**
  82.  *
  83.  * Sub IRQ handler....  the buit which actually does stuff. Exported so it can also be called
  84.  * from non-irq code when starting a TX. Starts a bm transfer from the writeBuffer.
  85.  *
  86.  * @param instance DXR2 instance
  87.  */
  88. extern void dxr2_sub_irq_handler(void* instance);
  89. /**
  90.  *
  91.  * Actually starts a BM transfer going (if it can)
  92.  *
  93.  * @param instance DXR2 instance to use
  94.  *
  95.  * @return 1 if a BM was started, 0 if not
  96.  *
  97.  */
  98. extern int dxr2_do_bm_transfer(dxr2_t* instance);
  99. /**
  100.  *
  101.  * Extracts hardware type
  102.  *
  103.  * @param instance DXR2 instance to use
  104.  *
  105.  * @return -ENODEV on validation failure, or device type (>=0) on success
  106.  *
  107.  */
  108. extern int dxr2_zivaDS_get_hardware_type(dxr2_t* instance)
  109. {
  110.   int rom0;
  111.   int rom1;
  112.   // read in the two WORDS from the eeprom
  113.   rom0 = dxr2_eeprom_read_byte(instance->vxp524Instance, 0) << 8;
  114.   rom0 |= dxr2_eeprom_read_byte(instance->vxp524Instance, 1);
  115.   rom1 = dxr2_eeprom_read_byte(instance->vxp524Instance, 0xA) << 8;
  116.   rom1 |= dxr2_eeprom_read_byte(instance->vxp524Instance, 0xB);
  117.   // this seems to be some form of validity check
  118.   if (rom0 != 0xA55A) {
  119.     
  120.     return(-ENODEV);
  121.   }
  122.   // OK, this works out what kind of hardware we have (I think)
  123.   if (rom1 == 0x100D) {
  124.     
  125.     return(ZIVADS_TYPE_3);
  126.   }
  127.   else if (rom1 == 0x100C) {
  128.     
  129.     return(ZIVADS_TYPE_4);
  130.   }
  131.   
  132.   // erk! hardware not valid!
  133.   return(-ENODEV);
  134. }
  135. /**
  136.  *
  137.  * IRQ handler function
  138.  *
  139.  * You may wonder why we don't do the BM transfer in here, or in a bottom half
  140.  * The reason is that even though this IRQ indicates the last BM operation has
  141.  * finished, this DOESN'T necessarily mean that the ZiVA is ready for more
  142.  * data yet. The ziva doesn't cause an IRQ when it is ready for data....
  143.  * we have to POLL for this. So, we have to do a big loop at the start of 
  144.  * dxr2_do_bm_transfer(), to wait until the ziva can cope with more data. 
  145.  * This is a problem. Theoretically, the ziva could take up to 1/2 second to 
  146.  * be ready for more data, so the delay loop would have to wait this long.
  147.  *
  148.  * There are four options
  149.  * 1) Busy loop in the IRQ handler. This is obviosuly NOT feasible.
  150.  * 2) Loop in a bottom half (i.e. schedule something on tq_immediate)
  151.  *    We tried this, BUT we still can't call the schedule() function in a bottom half, 
  152.  *    so we'd have to have a busy loop.... for 1/2 sec, which is NOT nice.
  153.  * 3) Stick it on tq_scheduler. This only gets executed when the scheduler is run... which isn't
  154.  *    deterministic enough for us. (believe me, we tried it)
  155.  * 4) The user's call to dxr2_io_write() call goes to sleep for a bit after starting a BM transfer.
  156.  *    The IRQ handler to wakes this up again when the BM finishes, so dxr2_io_write() can start
  157.  *    another transfer. Since we're not in any IRQ code, dxr2_io_write() call can use schedule() 
  158.  *    in it's polling loop to wait for the ziva to become ready... thus avoiding a nasty busy loop.
  159.  * 
  160.  * Solution 4, although not quite as clean as we'd like it to be, turned out to be the only 
  161.  * viable solution.
  162.  *
  163.  * @param irq IRQ number
  164.  * @param vInstance DXR2 instance pointer
  165.  * @param regs Processor regs
  166.  *
  167.  */
  168. extern void dxr2_irq_handler(int irq, void* vInstance, struct pt_regs* regs) 
  169. {
  170.   dxr2_t* instance = (dxr2_t*) vInstance;
  171.   // is the IRQ for us?
  172.   if (!vxp524_bm_completed(instance->vxp524Instance, 1)) {
  173.     
  174.     return;
  175.   }
  176.   // OK, if we've got this, then the BM operation must have finished,
  177.   // so mark it as such
  178.   vxp524_bm_not_in_use(instance->vxp524Instance);
  179.   // wake up waiting task
  180.   wake_up_interruptible(&(instance->waitQueue));
  181. }
  182. /**
  183.  *
  184.  * Actually starts a BM transfer going (if it can)
  185.  *
  186.  * @param instance DXR2 instance to use
  187.  *
  188.  * @return 1 if a BM was started, 0 if not
  189.  *
  190.  */
  191. extern int dxr2_do_bm_transfer(dxr2_t* instance) 
  192. {
  193.   int tmp;
  194.   int status = 0;
  195.   int size;
  196.   // offset into the thresholds table
  197.   tmp = (instance->currentBitstreamType * 3);
  198.   // check buffers on ziva.... if there's no space => wait until there is some
  199.   while ((zivaDS_get_mem(instance->zivaDSInstance, ZIVADS_VIDEO_EMPTINESS) < thresholdsTable[tmp+1]) ||
  200.  (zivaDS_get_mem(instance->zivaDSInstance, ZIVADS_AUDIO_EMPTINESS) < thresholdsTable[tmp+2]) ||
  201.  (zivaDS_get_reg(instance->zivaDSInstance, ZIVADS_REGCONTROL) & 0x80)) {
  202.     schedule();
  203.   }
  204.   // swap buffers over... so the BM buffer is the one that was just written in to
  205.   tmp = instance->bmBuffer;
  206.   instance->bmBuffer = instance->writeBuffer;
  207.   instance->writeBuffer = tmp;
  208.   instance->bufferCount[instance->writeBuffer] = 0;
  209.   // if there is some data in the buffer, send it
  210.   if (instance->bufferCount[instance->bmBuffer] > 0) {
  211.     vxp524_bm_send_data(instance->vxp524Instance,
  212. virt_to_bus((void*) instance->buffer[instance->bmBuffer]),
  213. instance->bufferCount[instance->bmBuffer],
  214. 1);
  215.     status = 1;
  216.   }
  217.   // OK, copy next load of data into the write buffer
  218.   size = instance->userBufferSize - instance->userBytesTransferred;
  219.   if (size > 0) {
  220.     
  221.     tmp = (instance->currentBitstreamType * 3);
  222.     if (size > thresholdsTable[tmp]) {
  223.       
  224.       size = thresholdsTable[tmp];
  225.     }
  226.     copy_from_user((void*) instance->buffer[instance->writeBuffer], 
  227.    (void*) instance->userBuffer + instance->userBytesTransferred,
  228.    size);
  229.     instance->bufferCount[instance->writeBuffer] = size;
  230.     // update the number of bytes we've transferred
  231.     instance->userBytesTransferred += size;
  232.   }
  233.     
  234.   // return the status
  235.   return(status);
  236. }
  237.   
  238. /**
  239.  *
  240.  * Handles user's writes to the device
  241.  *
  242.  * 
  243.  */
  244. extern ssize_t dxr2_io_write(struct file* filp, const char* buf, size_t count, 
  245.      loff_t* offset) 
  246. {
  247.   dxr2_t* instance = (dxr2_t*) filp->private_data;
  248.   int size;
  249.   int tmp;
  250.     
  251.   // if there's no supplied data, exit now
  252.   if (count == 0) {
  253.     
  254.     return(count);
  255.   }
  256.   
  257.   // OK, prime inital buffer
  258.   size = count;
  259.   tmp = (instance->currentBitstreamType * 3);
  260.   if (size > thresholdsTable[tmp]) {
  261.    
  262.     size = thresholdsTable[tmp];
  263.   }
  264.   copy_from_user((void*) instance->buffer[instance->writeBuffer], 
  265.  (void*) buf, size);
  266.   instance->bufferCount[instance->writeBuffer] = size;
  267.   // remember the data the user supplied for later... they may have supplied more than the 
  268.   // threshold, and we'll have to send that in a bit as well
  269.   instance->userBuffer = (char*) buf;
  270.   instance->userBytesTransferred = size;
  271.   instance->userBufferSize = count;
  272.   
  273.   // OK, loop until we run out of data
  274.   while(1) {
  275.     
  276.     // if the BM is still in use, don't do anything 
  277.     // (we must have timed out before the operation had finished)
  278.     if (!instance->vxp524Instance->bmInUse) {
  279.       
  280.       // OK, enter critical section
  281.       DXR2_ENTER_CRITICAL(instance);
  282.       
  283.       // issue any queued commands
  284.       dxr2_process_deferred_queue(instance);
  285.       // if a new BM transfer wasn't started, we'ev run out of data,
  286.       // so we can return to the user
  287.       if (!dxr2_do_bm_transfer(instance)) {
  288. DXR2_EXIT_CRITICAL(instance);
  289. break;
  290.       }
  291.       // critical section done.
  292.       DXR2_EXIT_CRITICAL(instance);
  293.     }
  294.     
  295.     // sleep for a bit. Notice that we have a timeout. This is because
  296.     // when we first wrote this, we were on a PII-400, and it worked 
  297.     // perectly. However, when we later tried it on a K6-233, we 
  298.     // had nasty hanging problems, because the IRQ would sometimes 
  299.     // occur while we were still in the dxr2_do_bm_transfer() above. 
  300.     // This meant the IRQ called wake_up_interruptible on us, BEFORE 
  301.     // we had actually gone to sleep. We then happily slept.... forever, 
  302.     // because we had missed the wake_up call. After about 8 hours of 
  303.     // trying different architectures, we came to the conclusion that 
  304.     // using a timeout was the only 100% certain way of avoiding such problems.
  305.     // this comment is so detailed because every so often we kept on
  306.     // thinking "ah ha!" I can remove that timeout.. followed about 15
  307.     // minutes later by realising why not... gah!
  308.     interruptible_sleep_on_timeout(&(instance->waitQueue), 1);
  309.   }
  310.   // OK, return the bytes transmitted.
  311.   return(count);
  312. }