/home/hillier_g/checkout/most4linux/most-kernel/most-sync-rt-m.c

Go to the documentation of this file.
00001 /*
00002  *  Copyright(c) Siemens AG, Muenchen, Germany, 2005, 2006, 2007
00003  *                           Bernhard Walle <bernhard.walle@gmx.de>
00004  *                           Gernot Hillier <gernot.hillier@siemens.com>
00005  *
00006  * ----------------------------------------------------------------------------
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as 
00009  * published by the Free Software Foundation;
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  * ----------------------------------------------------------------------------
00020  */
00021 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config/config.h"
00031 #endif
00032 #include <linux/module.h>
00033 #include <linux/fs.h>
00034 #include <linux/dma-mapping.h>
00035 #include <linux/timer.h>
00036 #include <linux/rwsem.h>
00037 #include <asm/msr.h>
00038 #include <asm/system.h>
00039 #include <asm/semaphore.h>
00040 #include <asm/uaccess.h>
00041 
00042 #include "most-constants.h"
00043 #include "most-base.h"
00044 #include "most-sync-rt.h"
00045 #include "most-common-rt.h"
00046 #include "most-rxbuf.h"
00047 #include "most-txbuf.h"
00048 #include "serial-rt-debug.h"
00049 #include "most-measurements.h"
00050 
00054 #define DRIVER_NAME                     "most-sync-rt"
00055 
00059 #define DRIVER_MAJOR_VERSION            0
00060 
00064 #define DRIVER_MINOR_VERSION            1
00065 
00069 #define DRIVER_PATHLEVEL                0
00070 
00074 #define PR                              DRIVER_NAME       ": "
00075 
00076 /* should see the PR */
00077 #include "most-sync-common.h"
00078 
00082 static char *version = "$Rev: 170 $";
00083 
00087 struct most_sync_rt_dev *most_sync_rt_devices[MOST_DEVICE_NUMBER];
00088 
00089 /* forward declarations ---------------------------------------------------- */
00090 static int     most_sync_nrt_open  (struct rtdm_dev_context *, rtdm_user_info_t *, int);
00091 static int     most_sync_nrt_close (struct rtdm_dev_context *, rtdm_user_info_t *);
00092 static int     most_sync_nrt_ioctl (struct rtdm_dev_context *, rtdm_user_info_t *,
00093                                     int, void *);
00094 static ssize_t most_sync_rt_read   (struct rtdm_dev_context *, rtdm_user_info_t *, 
00095                                     void *, size_t);
00096 static ssize_t most_sync_rt_write  (struct rtdm_dev_context *, rtdm_user_info_t *, 
00097                                     const void *, size_t);
00098 
00099 /* module parameters ------------------------------------------------------- */
00100 
00101 /*
00102  * see header
00103  */
00104 long sw_rx_buffer_size = STD_MOST_FRAMES_PER_SEC; /* 1 s */
00105 
00106 /*
00107  * see header
00108  */
00109 long sw_tx_buffer_size = STD_MOST_FRAMES_PER_SEC; /* 1 s */
00110 
00111 /*
00112  * see header
00113  */
00114 long hw_rx_buffer_size = 44; /* 1 ms */
00115 
00116 /*
00117  * see header
00118  */
00119 long hw_tx_buffer_size = 44; /* 1 ms */
00120 
00124 #ifdef SYNC_DEBUG
00125 static serial_rt_t s_serial_fd;
00126 #endif
00127 
00128 #ifndef DOXYGEN
00129 module_param(sw_rx_buffer_size, long, S_IRUGO);
00130 MODULE_PARM_DESC(sw_rx_buffer_size, 
00131         "Size of the software receive buffer in frame parts "
00132         "(default: " __MODULE_STRING(STD_MOST_FRAMES_PER_SEC) ")");
00133 
00134 module_param(sw_tx_buffer_size, long, S_IRUGO);
00135 MODULE_PARM_DESC(sw_tx_buffer_size, 
00136         "Size of the software transmit buffer in frame parts "
00137         "(default: " __MODULE_STRING(STD_MOST_FRAMES_PER_SEC) ")");
00138 
00139 module_param(hw_rx_buffer_size, long, S_IRUGO);
00140 MODULE_PARM_DESC(hw_rx_buffer_size, 
00141         "Size of the hardware receive buffer in frame parts "
00142         "(default: " __MODULE_STRING(44) ")");
00143 
00144 module_param(hw_tx_buffer_size, long, S_IRUGO);
00145 MODULE_PARM_DESC(hw_tx_buffer_size, 
00146         "Size of the hardware transmit buffer in frame parts "
00147         "(default: " __MODULE_STRING(44) ")");
00148 #endif
00149 
00150 /* general static data elements -------------------------------------------- */
00151 
00156 static const struct rtdm_device device_templ = {
00157     .struct_version    = RTDM_DEVICE_STRUCT_VER,
00158 
00159     .device_flags      = RTDM_NAMED_DEVICE,
00160     .context_size      = sizeof(struct most_sync_rt_file),
00161     .device_name       = "",
00162 
00163     .open_rt           = NULL,
00164     .open_nrt          = most_sync_nrt_open,
00165 
00166     .ops               = {
00167         .close_rt      = NULL,
00168         .close_nrt     = most_sync_nrt_close,
00169 
00170         .ioctl_rt      = NULL,
00171         .ioctl_nrt     = most_sync_nrt_ioctl,
00172 
00173         .read_rt       = most_sync_rt_read,
00174         .read_nrt      = NULL,
00175 
00176         .write_rt      = most_sync_rt_write,
00177         .write_nrt     = NULL,
00178     },
00179 
00180     .device_class      = RTDM_CLASS_MOSTSYNC,
00181     .device_sub_class  = RTDM_SUBCLASS_MOSTSYNC_OASIS,
00182     .driver_name       = DRIVER_NAME,
00183     .driver_version    = RTDM_DRIVER_VER(DRIVER_MAJOR_VERSION,
00184                                         DRIVER_MINOR_VERSION,
00185                                         DRIVER_PATHLEVEL),
00186     .peripheral_name   = "MOST Synchronous Access for PCI Interface",
00187     .provider_name     = "Bernhard Walle",
00188 };
00189 
00196 static inline void most_sync_nrt_stop_rx(struct most_sync_rt_file *file)
00197 {
00198     most_sync_stop_rx_common(file->sync_dev, file);
00199 }
00200 
00207 static inline void most_sync_nrt_stop_tx(struct most_sync_rt_file *file)
00208 {
00209     most_sync_stop_tx_common(file->sync_dev, file);
00210 }
00211 
00223 static inline int most_sync_nrt_reconfigure_begin(struct most_conf_sync *sync)
00224 {
00225     int         err;
00226     bool        ok_to_continue = false;
00227 
00228     while (true) {
00229         RTDM_EXECUTE_ATOMICALLY(
00230             ok_to_continue = !sync->reconfigure_flag && sync->counter == 0;
00231             if (ok_to_continue)
00232                 sync->reconfigure_flag = true;
00233         );
00234 
00235         if (ok_to_continue) {
00236             break;
00237         }
00238 
00239         /* if not ok, wait here */
00240         err = wait_event_interruptible(sync->wait_reconfigure,
00241                 !sync->reconfigure_flag && sync->counter == 0);
00242         if (err < 0) {
00243             return err;
00244         }
00245     }
00246 
00247     return 0;
00248 }
00249 
00258 static inline void most_sync_nrt_reconfigure_end(struct most_conf_sync *sync)
00259 {
00260     RTDM_EXECUTE_ATOMICALLY(
00261         sync->reconfigure_flag = false;
00262 
00263         /* wake up RT tasks waiting until reconfigure_flags becomes false */
00264         rtdm_event_pulse(&sync->wait_read_write);
00265 
00266         /* wake up other NRT tasks waiting until reconfigure_flags becomes false */
00267         wake_up_interruptible(&sync->wait_reconfigure);
00268     );
00269 }
00270 
00285 static inline int most_sync_rt_read_write_begin(struct most_conf_sync *sync)
00286 {
00287     int err = 0;
00288 
00289     return_value_if_fails_dbg(sync != NULL, -EINVAL);
00290     assert(sync->counter >= 0);
00291 
00292     /* wait until reconfigure_flag is zero */
00293     RTDM_EXECUTE_ATOMICALLY(
00294         if (sync->reconfigure_flag)
00295             err = rtdm_event_wait(&sync->wait_read_write);
00296 
00297         /* 
00298          * increase the read/write counter => no reconfigure ioctl may take
00299          * place 
00300          */
00301         if (err >= 0)
00302             sync->counter++;
00303     );
00304 
00305     return err;
00306 }
00307 
00316 static inline void most_sync_rt_read_write_end(struct most_conf_sync *sync)
00317 {
00318     /* 
00319      * use RTDM_EXECUTE_ATOMICALLY because this syncs between NRT and RT as
00320      * well
00321      */
00322     RTDM_EXECUTE_ATOMICALLY(
00323         /* wake up Linux processes if necessary */
00324         if (--sync->counter == 0)
00325             wake_up_interruptible(&sync->wait_reconfigure);
00326     );
00327 
00328     assert(sync->counter >= 0);
00329 }
00330 
00345 static int most_sync_nrt_open(struct rtdm_dev_context      *context, 
00346                               rtdm_user_info_t             *user_info,
00347                               int                          oflag)
00348 {
00349     struct most_sync_rt_dev     *sync_dev;
00350     struct most_sync_rt_file    *file = (void *)context->dev_private;
00351 
00352     sync_dev = container_of((struct rtdm_device *)context->device, 
00353                             struct most_sync_rt_dev, rtdm_dev);
00354     most_manage_usage(sync_dev->most_dev, 1);
00355 
00356     pr_sync_debug(PR "most_sync_open called for PCI card %d\n",
00357                   MOST_DEV_CARDNUMBER(sync_dev->most_dev));
00358 
00359     /* initialize members of the private data structure */
00360     memset(file, 0, sizeof(struct most_sync_rt_file));
00361     INIT_LIST_HEAD(&file->list);
00362     file->sync_dev = sync_dev;
00363 
00364     /* check and increase the counter */
00365     if (atomic_inc_and_test(&sync_dev->open_count)) {
00366         rtnrt_err(PR "Too much open (%d) for a MOST device,"
00367                 " only %d allowed\n", atomic_read(&sync_dev->open_count),
00368                 MOST_SYNC_OPENS);
00369         goto out_dec;
00370     }
00371 
00372     /* add the file to the list */
00373     rtdm_lock_get(&sync_dev->lock);
00374     list_add_tail(&file->list, &sync_dev->file_list);
00375     rtdm_lock_put(&sync_dev->lock);
00376 
00377     return 0;
00378 
00379 out_dec:
00380     atomic_dec(&sync_dev->open_count);
00381     most_manage_usage(sync_dev->most_dev, -1);
00382     return -EBUSY;
00383 }
00384 
00393 static int most_sync_nrt_close(struct rtdm_dev_context     *context,
00394                                rtdm_user_info_t            *user_info)
00395 {
00396     struct most_sync_rt_file    *file = (void *)context->dev_private;
00397     struct most_sync_rt_dev     *sync_dev = file->sync_dev;
00398     int                         err = 0, count = 0;
00399 
00400     pr_sync_debug(PR "most_sync_rt_close called for PCI card %d\n",
00401             MOST_DEV_CARDNUMBER(sync_dev->most_dev));;
00402 
00403     /* remove the device from the list and check if it's the last close */
00404     rtdm_lock_get(&sync_dev->lock);
00405     list_del(&file->list);
00406     rtdm_lock_put(&sync_dev->lock);
00407 
00408     /* check if it's the last reader */
00409     do {
00410         if (file->rx_running && atomic_dec_and_test(&sync_dev->receiver_count)) {
00411             pr_sync_debug(PR "Last Reader\n");
00412             err = most_sync_nrt_reconfigure_begin(&sync_dev->rx_sync);
00413             if (err >= 0) {
00414                 most_sync_last_closed_rx(sync_dev, file, most_sync_nrt_stop_rx);
00415                 most_sync_nrt_reconfigure_end(&sync_dev->rx_sync);
00416             }
00417         }
00418 
00419         /* check if it's the last writer */
00420         if (file->tx_running && atomic_dec_and_test(&sync_dev->transmitter_count)) {
00421             pr_sync_debug(PR "Last Transmitter\n");
00422             err = most_sync_nrt_reconfigure_begin(&sync_dev->tx_sync);
00423             if (err >= 0) {
00424                 most_sync_last_closed_tx(sync_dev, file, most_sync_nrt_stop_tx);
00425                 most_sync_nrt_reconfigure_end(&sync_dev->tx_sync);
00426             }
00427         }
00428     } while (err != 0 && count++ < MAX_RETRIES);
00429 
00430     if (count != 0) {
00431         rtnrt_warn(PR "Aquiring the lock failed %d times, err = %d\n", count, err);
00432     }
00433 
00434     most_manage_usage(sync_dev->most_dev, -1);
00435     atomic_dec(&sync_dev->open_count);
00436 
00437     return 0;
00438 }
00439 
00448 static inline int most_sync_nrt_setup_rx(struct most_sync_rt_file *file,
00449                                          rtdm_user_info_t         *user_info,
00450                                          void                     *ioctl_arg)
00451 {
00452     struct frame_part           *arg = (struct frame_part *)ioctl_arg;
00453     struct most_sync_rt_dev     *sync_dev = file->sync_dev;
00454     int                         err = 0;
00455     struct frame_part           param;
00456     
00457     /* get the argument */
00458     copy_from_user_or_kernel(err, user_info, &param, arg, sizeof(struct frame_part));
00459     if (unlikely(err != 0)) {
00460         return -EFAULT;
00461     }
00462 
00463     pr_sync_debug(PR "size = %d, offset = %d\n", param.count,
00464             param.offset);
00465 
00466     /* on error, the task was interrupted */
00467     err = most_sync_nrt_reconfigure_begin(&sync_dev->rx_sync);
00468     if (err < 0) {
00469         return err;
00470     }
00471 
00472     /* if it's running, stop it*/
00473     if (file->rx_running) {
00474         most_sync_nrt_stop_rx(file);
00475     }
00476 
00477     most_sync_setup_rx_common(param, file, sync_dev, hw_rx_buffer_size,
00478             sw_rx_buffer_size, err, most_sync_rt_file);
00479 
00480     most_sync_nrt_reconfigure_end(&sync_dev->rx_sync);
00481 
00482     return err;
00483 }
00484             
00493 static inline int most_sync_nrt_setup_tx(struct most_sync_rt_file *file, 
00494                                          rtdm_user_info_t         *user_info, 
00495                                          void                     *ioctl_arg)
00496 {
00497     struct frame_part           *arg = (struct frame_part *)ioctl_arg;
00498     struct most_sync_rt_dev     *sync_dev = file->sync_dev;
00499     int                         err = 0;
00500     struct frame_part           param;
00501     
00502     /* get the argument */
00503     copy_from_user_or_kernel(err, user_info, &param, arg, sizeof(struct frame_part));
00504     if (unlikely(err != 0)) {
00505         return -EFAULT;
00506     }
00507 
00508     /* on error, the task was interrupted */
00509     err = most_sync_nrt_reconfigure_begin(&sync_dev->tx_sync);
00510     if (err < 0) {
00511         return err;
00512     }
00513 
00514     /* if it's running, stop it*/
00515     if (file->tx_running) {
00516         most_sync_nrt_stop_rx(file);
00517     }
00518 
00519     most_sync_setup_tx_common(param, file, sync_dev, hw_tx_buffer_size,
00520             sw_tx_buffer_size, err, most_sync_rt_file);
00521     most_sync_nrt_reconfigure_end(&sync_dev->tx_sync);
00522 
00523     return err;
00524 }
00525 
00536 static int most_sync_nrt_ioctl(struct rtdm_dev_context *context,
00537                                rtdm_user_info_t        *user_info, 
00538                                int                     request, 
00539                                void                    *arg)
00540 {
00541     struct most_sync_rt_file    *file = (void *)context->dev_private;
00542     int                         err = 0;
00543 
00544     /*
00545      * extract the type and number bitfields, and don't decode
00546      * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
00547      */
00548     if (unlikely((_IOC_TYPE(request) != MOST_SYNC_RT_IOCTL_MAGIC))) {
00549         return -ENOTTY;
00550     }
00551 
00552     /* if ioctl() is called from userspace, check the arguments */
00553     if (user_info) {
00554         if (_IOC_DIR(request) & _IOC_READ) {
00555             err = !rtdm_read_user_ok(user_info, arg, _IOC_SIZE(request));
00556         } else if (_IOC_DIR(request) & _IOC_WRITE) {
00557             err = !rtdm_rw_user_ok(user_info, arg, _IOC_SIZE(request));
00558         }
00559 
00560         if (err) {
00561             return -EFAULT;
00562         }
00563     }
00564 
00565     /* now do the command */
00566     switch (request) {
00567         case MOST_SYNC_RT_SETUP_RX:
00568             return most_sync_nrt_setup_rx(file, user_info, arg);
00569 
00570         case MOST_SYNC_RT_SETUP_TX:
00571             return most_sync_nrt_setup_tx(file, user_info, arg);
00572 
00573         default:
00574             return -ENOTTY;
00575     }
00576 
00577     return 0;
00578 }
00579 
00590 static ssize_t most_sync_rt_read(struct rtdm_dev_context *context,
00591                                  rtdm_user_info_t        *user_info,
00592                                  void                    *buff,
00593                                  size_t                  count)
00594 {
00595     struct most_sync_rt_file        *file = (void *)context->dev_private;
00596     struct most_sync_rt_dev         *sync_dev = file->sync_dev;
00597     struct rtnrt_memcopy_desc       copy = { rtnrt_copy_to_user_rt, (void *)user_info };
00598     ssize_t                         copied = 0;
00599     int                             err = 0;
00600 
00601     pr_sync_debug(PR "Entering most_sync_rt_read %d, c=%d\n",
00602             file->reader_index, count);
00603 
00604     /* optimisation */
00605     return_value_if_fails(count != 0, 0);
00606 
00607     /* check if we can read */
00608     if (!file->rx_running) {
00609         rtnrt_err(PR "Cannot read at this time\n");
00610         return -EBUSY;
00611     }
00612 
00613     /* aquire the lock */
00614     err = most_sync_rt_read_write_begin(&sync_dev->rx_sync);
00615     if (err < 0) {
00616         pr_sync_debug(PR "most_sync_rt_read_write_begin "
00617                 "returned %d\n", err);
00618         return err;
00619     }
00620 
00621     while (copied == 0) {
00622         copied = rxbuf_get(sync_dev->sw_receive_buf, file->reader_index, 
00623                     file->part_rx, buff, count, &copy);
00624 
00625         if (unlikely(copied < 0)) {
00626             rtnrt_err(PR "Error in rxbuf_get: %d\n", copied);
00627             goto out_read;
00628         }
00629 
00630         if (copied == 0) {
00631             RTDM_EXECUTE_ATOMICALLY(
00632                 if (rxbuf_is_empty(sync_dev->sw_receive_buf, file->reader_index))
00633                     err = rtdm_event_wait(&sync_dev->rx_wait);
00634             );
00635 
00636             if (unlikely(err != 0)) {
00637                 pr_sync_debug(PR "rtdm_event_wait returned with %d\n", err);
00638                 copied = err;
00639                 goto out_read;
00640             }
00641         }
00642     }
00643 
00644 out_read:
00645     most_sync_rt_read_write_end(&sync_dev->rx_sync);
00646 
00647     pr_sync_debug(PR "Finishing most_sync_rt_read %d with %d\n",
00648                                 file->reader_index, copied);
00649     return copied;
00650 }
00651 
00662 static ssize_t most_sync_rt_write(struct rtdm_dev_context *context, 
00663                                   rtdm_user_info_t        *user_info, 
00664                                   const void              *buff, 
00665                                   size_t                  count)
00666 {
00667     struct most_sync_rt_file    *file = (void *)context->dev_private;
00668     struct most_sync_rt_dev     *sync_dev = file->sync_dev;
00669     struct rtnrt_memcopy_desc   copy = { rtnrt_copy_from_user_rt, (void *)user_info };
00670     ssize_t                     copied = 0;
00671     int                         err = 0;
00672 
00673     pr_sync_debug(PR "Write called, count = %d\n", count);
00674 
00675     /* optimisation */
00676     return_value_if_fails(count != 0, 0);
00677 
00678     /* check if we can write */
00679     if (!file->tx_running) {
00680         rtnrt_err(PR "Cannot write at this time\n");
00681         return -EBUSY;
00682     }
00683 
00684     /* aquire the lock */
00685     err = most_sync_rt_read_write_begin(&sync_dev->tx_sync);
00686     if (err < 0) {
00687         pr_sync_debug(PR "most_sync_rt_read_write_begin returned %d", err);
00688         return err;
00689     }
00690 
00691     while (copied != count) {
00692         err = txbuf_put(sync_dev->sw_transmit_buf, file->writer_index,
00693                     file->part_tx, buff + copied, count - copied, &copy);
00694         if (unlikely(err < 0)) {
00695             rtnrt_err(PR "Error in txbuf_put: %d\n", err);
00696             goto out_write;
00697         }
00698 
00699         copied += err;
00700         if (err == 0) {
00701             RTDM_EXECUTE_ATOMICALLY(
00702                 if (txbuf_is_full(sync_dev->sw_transmit_buf, file->writer_index)) 
00703                     err = rtdm_event_wait(&sync_dev->tx_wait);
00704             );
00705 
00706             if (unlikely(err != 0)) {
00707                 pr_sync_debug(PR "rtdm_event_wait returned with %d\n", err);
00708                 copied = err;
00709                 goto out_write;
00710             }
00711         }
00712     }
00713 
00714 out_write:
00715     most_sync_rt_read_write_end(&sync_dev->tx_sync);
00716     pr_sync_debug(PR "Finishing most_sync_write %d with %d\n",
00717                                 file->writer_index, copied);
00718     return copied;
00719 }
00720 
00727 static int most_sync_rt_probe(struct most_dev *most_dev)
00728 {
00729     int                         number = MOST_DEV_CARDNUMBER(most_dev);
00730     int                         err;
00731     struct most_sync_rt_dev     *sync_dev;
00732 
00733     return_value_if_fails_dbg(number < MOST_DEVICE_NUMBER, -EINVAL);
00734     pr_sync_debug(PR "most_sync_rt_probe called, registering %d\n", number);
00735 
00736     /* create a new device structure */
00737     sync_dev = kmalloc(sizeof(struct most_sync_rt_dev), GFP_KERNEL);
00738     if (unlikely(sync_dev == NULL)) {
00739         rtnrt_warn(PR "Allocation of private data structure failed\n");
00740         err = -ENOMEM;
00741         goto out;
00742     }
00743     memset(sync_dev, 0, sizeof(struct most_sync_rt_dev));
00744 
00745     /* initialize some members */
00746     sync_dev->most_dev = most_dev;
00747     INIT_LIST_HEAD(&sync_dev->file_list);
00748     rtdm_lock_init(&sync_dev->lock);
00749     rtdm_event_init(&sync_dev->rx_wait, 0);
00750     rtdm_event_init(&sync_dev->tx_wait, 0);
00751     most_conf_sync_init(&sync_dev->tx_sync);
00752     most_conf_sync_init(&sync_dev->rx_sync);
00753     atomic_set(&sync_dev->receiver_count, 0);
00754     atomic_set(&sync_dev->transmitter_count, 0);
00755 
00756     /* create the new RTDM device */
00757     memcpy(&sync_dev->rtdm_dev, &device_templ, sizeof(struct rtdm_device));
00758     snprintf(sync_dev->rtdm_dev.device_name, RTDM_MAX_DEVNAME_LEN,
00759             "mostsync%d", number);
00760     sync_dev->rtdm_dev.device_id = number;
00761     sync_dev->rtdm_dev.proc_name = sync_dev->rtdm_dev.device_name;
00762 
00763     /* register the new RTDM device */
00764     err = rtdm_dev_register(&sync_dev->rtdm_dev);
00765     if (unlikely(err < 0)) {
00766         goto out_sync_dev;
00767     }
00768 
00769     /* put the device in the global list of devices */
00770     most_sync_rt_devices[number] = sync_dev;
00771 
00772     return 0;
00773 
00774 out_sync_dev:
00775     kfree(sync_dev);
00776 out:
00777 
00778     return err;
00779 }
00780 
00787 static int most_sync_rt_remove(struct most_dev *dev)
00788 {
00789     int                         number = MOST_DEV_CARDNUMBER(dev);
00790     struct most_sync_rt_dev     *sync_dev = most_sync_rt_devices[number];
00791 
00792     pr_sync_debug(PR "most_sync_rt_remove called, unregistering %d\n", number);
00793 
00794     /* delete device */
00795     rtdm_dev_unregister(&sync_dev->rtdm_dev, 1000);
00796 
00797     /* free memory and remove from the global device list */
00798     most_sync_rt_devices[number] = NULL;
00799     rtdm_event_destroy(&sync_dev->rx_wait);
00800     rtdm_event_destroy(&sync_dev->tx_wait);
00801     most_conf_sync_destroy(&sync_dev->rx_sync);
00802     most_conf_sync_destroy(&sync_dev->tx_sync);
00803 
00804     kfree(sync_dev);
00805 
00806     return 0;
00807 }
00808 
00815 static void most_sync_rt_interrupt_handler(struct most_dev      *dev, 
00816                                            unsigned int         intstatus)
00817 {
00818     int                         card = MOST_DEV_CARDNUMBER(dev);
00819     struct most_sync_rt_dev     *sync_dev = most_sync_rt_devices[card];
00820     u32                         val;
00821     int                         current_page;
00822 
00823     return_if_fails_dbg(sync_dev != NULL);
00824 
00825     if (intstatus & ISSRX) {
00826         void          *dma_start;
00827         size_t        siz;
00828         
00829         pr_rt_irq_debug(PR "RT RX INT\n");
00830 
00831         val = most_readreg_rt(sync_dev->most_dev, MOST_PCI_SRXCTRL_REG);
00832         dma_start = sync_dev->hw_receive_buf.addr_virt;
00833         siz = sync_dev->hw_receive_buf.size / 2;
00834 
00835         /* 
00836          * current page == 0 
00837          * -> increase address (because then we must read out page 1!!!!)
00838          */
00839         if (!(val & SRXPP)) {
00840             dma_start += siz;
00841         }
00842 
00843         measuring_receive_isr_start(sync_dev->sw_receive_buf);
00844         rxbuf_put(sync_dev->sw_receive_buf, dma_start, siz);
00845         measuring_receive_isr_wakeup();
00846         rtdm_event_pulse(&sync_dev->rx_wait);
00847 
00848         current_page = (val & SRXPP) ? 1 : 2;
00849         if ((sync_dev->rx_current_page != 0) && 
00850                 (sync_dev->rx_current_page == current_page)) {
00851             rtnrt_warn(PR "RT-RX: sync_dev->rx_current_page == current_page\n");
00852         }
00853         sync_dev->rx_current_page = current_page;
00854     }
00855     
00856     if (intstatus & ISSTX) {
00857         void          *dma_start;
00858         ssize_t       read;
00859         size_t        siz;
00860         unsigned int  *ptr;
00861 
00862         pr_rt_irq_debug(PR "TX RT INT\n");
00863 
00864         val = most_readreg_rt(sync_dev->most_dev, MOST_PCI_STXCTRL_REG);
00865         dma_start = sync_dev->hw_transmit_buf.addr_virt;
00866         siz = sync_dev->hw_transmit_buf.size / 2;
00867 
00868         /* 
00869          * current page == 0 
00870          * -> increase address (because then we must read out page 1!!!!)
00871          */
00872         if (!(val & STXPP)) {
00873             dma_start += siz;
00874         }
00875 
00876         ptr = dma_start;
00877 
00878         read = txbuf_get(sync_dev->sw_transmit_buf, dma_start, siz);
00879         rtdm_event_pulse(&sync_dev->tx_wait);
00880 
00881         current_page = (val & STXPP) ? 1 : 2;
00882         if ((sync_dev->tx_current_page != 0) && 
00883                 (sync_dev->tx_current_page == current_page))
00884         {
00885             rtnrt_warn(PR "RT-TX: sync_dev->tx_current_page == current_page\n");
00886         }
00887         sync_dev->tx_current_page = current_page;
00888     }
00889 }
00890 
00895 static struct most_high_driver most_sync_rt_high_driver = {
00896     .name                   = "most-sync-rt",
00897     .sema_list              = LIST_HEAD_INIT(most_sync_rt_high_driver.sema_list),
00898     .spin_list              = LIST_HEAD_INIT(most_sync_rt_high_driver.spin_list),
00899     .probe                  = most_sync_rt_probe,
00900     .remove                 = most_sync_rt_remove,
00901     .interrupt_mask         = (IESTX | IESRX),
00902     .int_handler            = most_sync_rt_interrupt_handler
00903 };
00904 
00910 static int __init most_sync_rt_init(void)
00911 {
00912     int err;
00913 
00914     rtnrt_info("Loading module %s, version %s\n", DRIVER_NAME, version);
00915     print_measuring_warning();
00916 
00917     serial_rt_debug_init();
00918 
00919     /* register driver */
00920     err = most_register_high_driver(&most_sync_rt_high_driver);
00921     if (unlikely(err != 0)) {
00922         return err;
00923     }
00924 
00925     return 0;
00926 }
00927 
00931 static void __exit most_sync_rt_exit(void)
00932 {
00933     most_deregister_high_driver(&most_sync_rt_high_driver);
00934     serial_rt_debug_finish();
00935 
00936     rtnrt_info("Unloading module %s, version %s\n", DRIVER_NAME, version);
00937 }
00938 
00939 #ifndef DOXYGEN
00940 EXPORT_SYMBOL(hw_tx_buffer_size);
00941 EXPORT_SYMBOL(hw_rx_buffer_size);
00942 EXPORT_SYMBOL(sw_tx_buffer_size);
00943 EXPORT_SYMBOL(sw_rx_buffer_size);
00944 
00945 MODULE_LICENSE("GPL");
00946 MODULE_AUTHOR("Bernhard Walle");
00947 MODULE_VERSION("$Rev: 170 $");
00948 MODULE_DESCRIPTION("Real-time (RTDM) Driver for MOST Synchronous data.");
00949 module_init(most_sync_rt_init);
00950 module_exit(most_sync_rt_exit);
00951 #endif
00952 
00953 /* vim: set ts=4 et sw=4: */

Generated on Fri Mar 9 14:48:58 2007 for MOST Linux Drivers (Linux and RTAI) by  doxygen 1.5.0