linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mark Hounschell <markh@compro.net>
To: Peter Hurley <peter@hurleysoftware.com>
Cc: linux-serial@vger.kernel.org, Mark Hounschell <dmarkh@cfl.rr.com>
Subject: Re: Out of tree GPL serial tty driver help?
Date: Fri, 26 Apr 2013 16:26:29 -0400	[thread overview]
Message-ID: <517AE2F5.4060200@compro.net> (raw)
In-Reply-To: <1367005866.3971.15.camel@thor.lan>

On 04/26/2013 03:51 PM, Peter Hurley wrote:
> On Fri, 2013-04-26 at 14:17 -0400, Mark Hounschell wrote:
>> On 04/26/2013 12:37 PM, Peter Hurley wrote:
>>> These drivers weren't really current at 3.4 though, either. I'm not sure
>>> what else you're going to find that doesn't work.
>>>
>>
>> No, I have kept them current, or I should say functional, to the best of
>> my ability from 2.6 up to and including 3.4.x.
>
> By 'current', I mean 'similar in structure and functionality to in-tree
> drivers'.
>
> The structure of this driver is more akin to a 2.5 driver (back when
> there were separate serial and callout tty drivers).
>
>>   What I have here works
>> with kernels up to 3.4.x. I have not tried anything between 3.4 and 3.8.
>>    As far as building against 3.8, the only issues were the change from
>> *termios to termios and the "structn_tty_data" no longer in an include
>> file so not easily directly accessible.
>
> What is this driver accessing in N_TTY's private data?
>
         /* Decide how much data we can send into the tty layer */
         if(dgdm_rawreadok && tty->real_raw)
                 flip_len = MYFLIPLEN;
         else
                 flip_len = TTY_FLIPBUF_SIZE;
         len = MIN(data_len, flip_len);
         len = MIN(len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);
         dxb_return_fixed_cost(dxb, channel, 1);
         ld = tty_ldisc_ref(tty);
.
.
.
.
                 /*
                  * In high performance mode, we don't have to update
                  * flag_buf or any of the counts or pointers into flip buf.
                  */
                 if(!dgdm_rawreadok || !tty->real_raw) {
                         if (I_PARMRK(tty) || I_BRKINT(tty) || 
I_INPCK(tty)) {
                                 parity_scan(dc, myflipbuf[boardnum],
                                         myflipflagbuf[boardnum], &len);
                         } else {
                                 memset(myflipflagbuf[boardnum], 
TTY_NORMAL, len);
                         }
                 }
.
.
.
.
                 /*
                  * If we're doing raw reads, jam it right into the
                  * line disc bypassing the flip buffers.
                  * OPT OPP: do this only once per channel instead of
                  * once per dxb message.
                  */
                 if(dgdm_rawreadok && tty->real_raw) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
                         tty->ldisc->ops->receive_buf(tty, 
myflipbuf[boardnum], NULL, len);
#else
                         tty->ldisc.ops->receive_buf(tty, 
myflipbuf[boardnum], NULL, len);
#endif
#else
                         tty->ldisc.receive_buf(tty, 
myflipbuf[boardnum], NULL, len);
#endif
                 } else {
                         len = tty_buffer_request_room(tty, len);
                         tty_insert_flip_string_flags(tty, 
myflipbuf[boardnum],
                                 myflipflagbuf[boardnum], len);

                         /* Tell the tty layer its okay to "eat" the 
data now */
                         tty_flip_buffer_push(tty);
                 }
.
.
.
         /*
          * Just go ahead and try to read some data into the flip buffer.
          * If there isn't any data available, dxb_rxbuf_read will return
          * 0 back to us right away.
          *
          * The dgdm_rawreadok case takes advantage of carnal knowldge that
          * the char_buf and the flag_buf are next to each other and
          * are each of (2 * TTY_FLIPBUF_SIZE) size.
          */

         if(dgdm_rawreadok && tty->real_raw)
                 flip_len = MYFLIPLEN;
         else
                 flip_len = TTY_FLIPBUF_SIZE;

         flip_len = MIN(flip_len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);

         len = dxb_rxbuf_read(brd->dxb, dc->dxbchan, 
myflipbuf[boardnum], flip_len);


etc...

Looks like for hopes of performance????




>>> For both PCI and PCI-e, these drivers should _at a minimum_ be pci
>>> drivers that register the tty driver at module init and register _only_
>>> the tty devices for that particular PCI device at PCI probe time. Look
>>> at the end of synclink_gt.c for how this is supposed to look.
>>>
>>
>> I'll look at it some more but I have been there.
>
> Specifically, review:
> 	struct pci_driver
> 	device_init()
> 	init_one()
> 	remove_one()
> 	sglt_init()
> 	sglt_exit()
>

Ok, I'll will look more closely at these to try to understand what 
should be done.


Here is the init_module funtion FYI.

GLOBAL int init_module(void)
{
     int rc;

         /* make sure that the globals are init'd before we do anything 
else */
         dgdm_init_globals();

         dgdm_NumBoards = 0;
         dgdm_Major_Serial_Registered = FALSE;
         dgdm_Major_Callout_Registered = FALSE;
         dgdm_Major_TransparentPrint_Registered = FALSE;
         dgdm_Major_Control_Registered = FALSE;
         dgdm_Major_ISDN_Registered = FALSE;

         APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));

         /*
          * Find and configure all the cards
          */

         rc = dgdm_init_pci();

         if (!rc) {
                 /*
                  * At least one card was found, register the devices
                  * with the kernel.
                  */
                 dgdm_proc_register_basic();

                 if (dgdm_tty) {
                         rc = dgdm_tty_init();  // This is the function 
that creates all the device entries
                         if (rc < 0) {
                                 dgdm_tty_uninit();
                                 APR(("Can't init tty devices (%d)\n", rc));
                                 return (rc);
                         }
                         /*
                          * Register FEP related /proc files
                          */
                         dgdm_proc_register_fep();
                 }
                 if (!dgdm_Major_Control_Registered) {
                         /*
                          * Register memory/control/debug/mangement devices
                          */
                         rc = register_chrdev(major + DGDM_CONTROL_MAJOR,
                                              "dxb", &BoardFops);
                         if (rc < 0) {
                                 APR(("Can't register ram device 
(%d)\n", rc));
                                 return (rc);
                         }
                         dgdm_Major_Control_Registered = TRUE;
                 }
                 if (dgdm_isdn && !dgdm_Major_ISDN_Registered) {
                         /*
                          * Register ISDN testing device
                          */
                         rc = register_chrdev(major + DGDM_ISDN_MAJOR,
                                              "dxbisdn", 
&dgdm_BoardIsdnFops);
                         if (rc < 0) {
                                 APR(("Can't register ISDN device 
(%d)\n", rc));
                                 return (rc);
                         }
                         dgdm_Major_ISDN_Registered = TRUE;
                 }
                 if(dgdm_NumBoards > 4) {
                         if (!dgdm_Major_Control2_Registered) {
                                 rc = 
register_chrdev(major+DGDM_CONTROL2_MAJOR,
                                                      "dxb2", &BoardFops);
                                 if (rc < 0) {
                                         APR(("Can't register high ram "
                                              "device (%d)\n", rc));
                                         return (rc);
                                 }
                                 dgdm_Major_Control2_Registered = TRUE;
                         }
                         if (dgdm_isdn && !dgdm_Major_ISDN2_Registered) {
                                 rc = register_chrdev(major + 
DGDM_ISDN2_MAJOR,
                                                      "dxbisdn2", 
&dgdm_BoardIsdnFops);
                                 if (rc < 0) {
                                         APR(("Can't register high ISDN "
                                              "devices (%d)\n", rc));
                                         return (rc);
                                 }
                                 dgdm_Major_ISDN2_Registered = TRUE;
                         }
                 }

                 //       Compro Computer Svcs udev support
                 // Need udev notification of the dgdm_mgmt device creation
                 //
                 // See config/99-dgdm.rules 
"/etc/udev/rules.d/99-dgdm.rules"
                 // and /usr/local/sbin/dgdm
                 //
                 if (alloc_chrdev_region(&dgdm_mgmt_major, 0, 1, 
"dgdm_mgmt") != 0) {
                         printk("DGDM: Unable to get MAJOR/MINOR device 
numbers\n");
                         return -ENODEV;
                 }

                 dgdm_mgmt_device = cdev_alloc();
                 if (dgdm_mgmt_device <= 0) {
                         printk("DGDM: Unable to alloc cdev struct\n");
                         return -ENODEV;
                 }

                 cdev_init(dgdm_mgmt_device, &dgdm_BoardIsdnFops);
                 dgdm_mgmt_device->owner = THIS_MODULE;

                 if (cdev_add(dgdm_mgmt_device, dgdm_mgmt_major, 1) < 0) {
                         printk("DGDM: Error Registering chrdev device\n");
                         return -ENODEV;
                 }

                 dgdm_mgmt_class = class_create(THIS_MODULE, "dgdm_mgmt");
                 if (IS_ERR(dgdm_mgmt_class)) {
                         printk("DGDM: Error creating class\n");
                         return -ENODEV;
                 }

                 device_dgdm_mgmt = device_create(dgdm_mgmt_class, NULL, 
dgdm_mgmt_major, NULL, "dgdm_mgmt");
                 if (IS_ERR(device_dgdm_mgmt)) {
                         printk("DGDM: Error creating device entry\n");
                         return -ENODEV;
                 }
         } else {
                 cleanup_module();
         }

         return (rc);
}


Mark

  reply	other threads:[~2013-04-26 20:26 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-24 17:44 Out of tree GPL serial tty driver help? Mark Hounschell
2013-04-25 21:41 ` Peter Hurley
2013-04-26 12:58   ` Mark Hounschell
2013-04-26 13:45     ` Peter Hurley
2013-04-26 14:28       ` Mark Hounschell
2013-04-26 14:35         ` Greg KH
2013-04-26 15:10           ` Mark Hounschell
2013-04-26 15:19             ` Greg KH
2013-04-26 15:39               ` Peter Hurley
2013-04-26 16:03                 ` Greg KH
2013-04-26 17:58                   ` Mark Hounschell
2013-04-26 23:21                     ` Greg KH
2013-04-26 16:37         ` Peter Hurley
2013-04-26 18:17           ` Mark Hounschell
2013-04-26 19:51             ` Peter Hurley
2013-04-26 20:26               ` Mark Hounschell [this message]
2013-04-26 21:49                 ` Peter Hurley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=517AE2F5.4060200@compro.net \
    --to=markh@compro.net \
    --cc=dmarkh@cfl.rr.com \
    --cc=linux-serial@vger.kernel.org \
    --cc=peter@hurleysoftware.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).