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
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html