Подскажите с f->f_op->read

<< < (2/4) > >>

RXL:
Приведи ф-ий полностью - кусками плохо смотреть.

opushkin:
Сетевой драйвер - демонструха со связью через СОМ порт; ttyS0 конфигурируется скриптом; f открывается при инициализации модуля; передача при вызове _xmit через ->write работает; чтение хочется сделать по опросу через таймер, но оно не работает. Привожу весь код. Прошу сильно не бить - эксперимент в процессе, много несуразностей, но не критичных (я та-ак думаю).
Код: (C)
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>    /* For current */
#include <linux/tty.h>      /* For the tty declarations */
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/inet.h>
#include <linux/skbuff.h>
#include <linux/mm.h>
#include <asm/segment.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/mman.h>
#include <linux/a.out.h>
#include <linux/stat.h>
#include <linux/timer.h>
#include <linux/timex.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
spinlock_t timer_lock = SPIN_LOCK_UNLOCKED;
spinlock_t tx_lock = SPIN_LOCK_UNLOCKED;
/*Структура пакета*/
struct iphdr
  {
    unsigned int ihl:4;
    unsigned int version:4;
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    unsigned char saddr[4]; /* IP address of originator */
    unsigned char daddr[4]; /* IP address of destination */
    /*The options start here. */
  };
struct my_buf {
int rlen;
unsigned char *rdata;
char rc;
        union rbuffer{
        unsigned char rbuff[1024];
        struct iphdr rhdr;
        }rb;
};
struct file *f;
struct net_device_stats *stats;
struct timer_list timer;
struct my_buf rbf;

static int ndt_xmit(struct sk_buff *skb, struct net_device *dev);
static struct net_device_stats *ndt_get_stats(struct net_device *dev);
/*static void load_pack(struct my_buf *xbf);*/
static void ttys_write(const char *buf, size_t lenbuf);

int fd, retval, shift;
mm_segment_t fs;

void ndt_irq (unsigned long data)
{
spin_lock_bh(&timer_lock);
struct my_buf *tbf;
tbf = &rbf;

fs=get_fs();
set_fs(KERNEL_DS);
if (f && f->f_dentry &&
       f->f_op && f->f_op->read) {
 
     /*do retval = f->f_op->read(f, &tbf->rc, 1, &f->f_pos);
     while (retval == -11);*/
     retval = f->f_op->read(f, &tbf->rc, 1, &f->f_pos);
     f->f_op->write(f, "!==END READ==!", 14, &f->f_pos);
printk(KERN_WARNING "^tstnd: ===PIC=== retval= %d char= %s.\n", retval, &tbf->rc);
        if (retval > 0){
        shift = tbf->rlen++;
        tbf->rb.rbuff[shift] = tbf->rc;
        ttys_write("!==PUT CHAR==!", 14);
                if (tbf->rlen > 9) {
                ttys_write(tbf->rb.rbuff, tbf->rlen);
                tbf->rlen = 0;
                ttys_write("!==SENT BUFF==!", 15);
                }
        }
    }
   else  printk("<0> ^tstnd: stuct FILE is empty\n");
set_fs(fs);

mod_timer(&timer, jiffies + 1 * HZ);
spin_unlock_bh(&timer_lock);
}
/*Вызывается IFCONFIG */
int ndt_open (struct net_device *dev)
{
        printk(KERN_WARNING "^tstnd: ndt_open called.\n");
        netif_start_queue (dev);
/*указатель на начало данных*/
rbf.rdata = &rbf.rb.rbuff[0];
/*инициализация таймера*/
init_timer(&timer);
timer.expires = jiffies + 2 * HZ;
timer.function = ndt_irq;
add_timer(&timer);
return 0;
}
/*Вызывается IFCONFIG */
int ndt_stop (struct net_device *dev)
{
/*остановка таймера*/
del_timer_sync(&timer);
        printk (KERN_WARNING "^tstnd: ndt_stop called.\n");
        netif_stop_queue(dev);
        return 0;
}
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
static int ndt_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct net_device_stats *stats = dev->priv;
/*unsigned char *sad;
unsigned char *dad;
unsigned char sadd[4];
unsigned char dadd[4];*/

spin_lock_bh(&tx_lock);
fs=get_fs();
set_fs(KERNEL_DS);
     f->f_op->write(f, skb->data, skb->len, &f->f_pos);
     f->f_op->write(f, "===PACK_END===", 14, &f->f_pos);
set_fs(fs);
spin_unlock_bh(&tx_lock);

/*Передача пакета через буфер приёмника назад*/
/*              rbf.rlen = skb->len;
        shift = 0;
                while (shift + 1 <= skb->len) {
                rbf.rb.rbuff[shift] = skb->data[shift];
                shift++;
                }
sad = &rbf.rb.rhdr.saddr[0];
dad = &rbf.rb.rhdr.daddr[0];
        shift = 0;
                while (shift + 1 <= 4) {
                sadd[shift] = sad[shift];
                shift++;
                }
        shift = 0;
                while (shift + 1 <= 4) {
                dadd[shift] = dad[shift];
                shift++;
                }
sad = &sadd[0];
dad = &dadd[0];
        shift = 0;
                while (shift + 1 <= 4) {
                rbf.rb.rhdr.daddr[shift] = sad[shift];
                shift++;
                }
        shift = 0;
                while (shift + 1 <= 4) {
                rbf.rb.rhdr.saddr[shift] = dad[shift];
                shift++;
                }
load_pack(&rbf);*/

        dev_kfree_skb(skb);
        stats->tx_bytes += skb->len;
        stats->tx_packets++;
return 0;
}

static struct net_device_stats *ndt_get_stats(struct net_device *dev)
{
        return dev->priv;
}
struct net_device tstnd_dev = {
        .open                   = ndt_open,
        .stop                   = ndt_stop,
        .hard_start_xmit        = ndt_xmit,
};

int ndt_init_module (void)
{
strcpy (tstnd_dev.name, "tstnd");
        stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
        if (stats) {
                memset(stats, 0, sizeof(struct net_device_stats));
                tstnd_dev.priv = stats;
                tstnd_dev.get_stats = &ndt_get_stats;
        }

if ((retval = register_netdev (&tstnd_dev))) {
        printk (KERN_WARNING "^tstnd: Error %d  of initializing module.\n",retval);
        return retval;
        }
printk(KERN_WARNING "^tstnd: initializing the Module.\n");

spin_lock_bh(&tx_lock);
fs=get_fs();
set_fs(KERNEL_DS);
  f=filp_open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY, 0666);
   if(IS_ERR(f)) printk (KERN_WARNING "^tstnd: Error opening ttyS.\n");
set_fs(fs);
spin_unlock_bh(&tx_lock);
return 0;
}

void ndt_cleanup (void)
{
spin_lock_bh(&tx_lock);
fs=get_fs();
set_fs(KERNEL_DS);
  filp_close(f,0);
set_fs(fs);
spin_unlock_bh(&tx_lock);
        unregister_netdev (&tstnd_dev);
        printk (KERN_WARNING "^tstnd: Cleaning Up the Module.\n");
        return;
}

module_init (ndt_init_module);
module_exit (ndt_cleanup);
/*=================================================================================*/
/* Вывод строки на ttyS0 */
static void ttys_write(const char *buf, size_t lenbuf)
{
spin_lock_bh(&tx_lock);
fs=get_fs();
set_fs(KERNEL_DS);
   if(f != NULL) {
     f->f_op->write(f, buf, lenbuf, &f->f_pos);
    }
   else  printk(KERN_WARNING "^tstnd: stuct FILE is empty\n");
 set_fs(fs);
spin_unlock_bh(&tx_lock);
}

/* Изменение формата адреса из двоичного в текстовый.*/
void printAddr(unsigned char *addr)
{
int j;
        for ( j = 0; j < 4; j++ )
        {
        printk("%d", addr[j]);
        if ( j < 3 )
                printk(".");
        }
}
/* Вывод содержимого пакета в лог*/
/*void pdumpk(void* b, int len)
{
int i;
struct iphdr *ip = b;

        printk("----------------\n");
        for ( i = 0; i < len; i++ )
        {
                if ( !(i & 15) ) printk("\n%04X:  ", i);
                printk("%02X ", ((unsigned char*)b)[i]);
        }
        printk("\n");
        printk("IPv%d: hdr-size=%d pkt-size=%d protocol=%d TTL=%d ",
                ip->version, ip->ihl*4, ntohs(ip->tot_len), ip->protocol,
                ip->ttl);
printk("\n");
        printk("rst= ");
printAddr(ip->saddr);
        printk(" dst= ");
printAddr(ip->daddr);
printk("\n");
}*/
void spdumpk(struct my_buf *sxbf)
{
int i;
        printk("\n----------------");
        for ( i = 0; i < sxbf->rlen; i++ )
        {
                if ( !(i & 15) ) printk("\n%04X:  ", i);
                printk("%02X ", ((unsigned char*)sxbf->rb.rbuff)[i]);
        }
        printk("\n");
        printk("IPv%d: hdr-size=%d pkt-size=%d protocol=%d TTL=%d ",
                sxbf->rb.rhdr.version, sxbf->rb.rhdr.ihl*4, ntohs(sxbf->rb.rhdr.tot_len),
                sxbf->rb.rhdr.protocol, sxbf->rb.rhdr.ttl);
printk("\n");
        printk("rst= ");
printAddr(sxbf->rb.rhdr.saddr);
        printk(" dst= ");
printAddr(sxbf->rb.rhdr.daddr);
printk("\n");
}

/*static void load_pack(struct my_buf *xbf)
{
        struct net_device_stats *stats = tstnd_dev.priv;
        struct sk_buff *r_skb;
        int count;
        count = xbf->rlen;
        printk(KERN_WARNING "^tstnd: Принят пакет.\n");
        r_skb = dev_alloc_skb(count);
                if (r_skb == NULL)  {
                        printk(KERN_WARNING "^tstnd: memory squeeze, dropping packet.\n");
                        stats->rx_dropped++;
                        return;
                }
        r_skb->dev = &tstnd_dev;
        memcpy(skb_put(r_skb, count), xbf->rb.rbuff, count);
        r_skb->mac.raw=r_skb->data;
        r_skb->protocol=htons(ETH_P_IP);
       
        spdumpk(xbf);*/
        /*pdumpk(r_skb->data, count);*/
/*      netif_rx(r_skb);
        stats->rx_bytes += xbf->rlen;
        stats->rx_packets++;
}*/
MAKEFILE:
Код: (Text)
TARGET = forex
OBJS = forex.o
MDIR = drivers/misc
EXTRA_CFLAGS = -DEXPORT_SYMTAB
CURRENT = $(shell uname -r)
KDIR = /lib/modules/$(CURRENT)/build
PWD = $(shell pwd)
DEST = /lib/modules/$(CURRENT)/kernel/$(MDIR)
obj-m      := $(TARGET).o
default:
        make -C $(KDIR) SUBDIRS=$(PWD) modules
$(TARGET).o: $(OBJS)
        $(LD) $(LD_RFLAG) -r -o $@ $(OBJS)
ifneq (,$(findstring 2.4.,$(CURRENT)))
install:
        su -c "cp -v $(TARGET).o $(DEST) && /sbin/depmod -a"
else
install:
        su -c "cp -v $(TARGET).ko $(DEST) && /sbin/depmod -a"
endif
clean:
        -rm -f *.o *.ko .*.cmd .*.flags *.mod.c
-include $(KDIR)/Rules.make
Скрипт для запуска:
Код: (Bash)
#!/bin/sh
insmod ./forex.ko
ifconfig tstnd 192.168.2.1 up
ifconfig tstnd netmask 255.255.255.0
#route add 192.168.2.0 tstnd
Скрипт для удаления:
Код: (Bash)
#!/bin/sh
ifconfig tstnd down
rmmod forex
Библиотек многовато - поубирал кое что из текста, а их убирать - надо возиться.




Поправил твой пост. Оформлять внешний вид надо! Теперь знаешь как (нажми "редактировать" и посмотри теги [code]).

RXL:
Макрос set_fs() описан в include/asm/uaccess.h . Просто макрос. Изменяет current->addr_limit.
Там же черным по белому:Цитата

The fs value determines whether argument validity checking should be
performed or not.  If get_fs() == USER_DS, checking is performed, with
get_fs() == KERNEL_DS, checking is bypassed.

For historical reasons, these macros are grossly misnamed.

Остальной код пока не смотрел.

opushkin:
М..да... О сколько нам открытий чудных.... Я в Линухе недавно.
Ещё раз спасибо.

opushkin:
Чтение оживает если напрямую разрешать прерывания по приёму в регистре управления прерываниями UART. Но работает в режиме эха - скидывает принятое назад. Адекватно себя ведёт если опять же напрямую прописать в этот рег разрешение на передачу и по CTS/DSR. Передача через ->write, а приём по опросу таймером, прямо читая рег состояния линии и данных. При  выгрузке модуля - ругается как сапожник, но ничего не отваливается.
Код: (Bash)
Jan 15 17:23:35 localhost kernel: ^tstnd: ndt_stop called.
Jan 15 17:23:35 localhost kernel: bad: scheduling while atomic!
Jan 15 17:23:35 localhost kernel:  [dump_stack+30/32] dump_stack+0x1e/0x20
Jan 15 17:23:35 localhost kernel:  [<c0107bfe>] dump_stack+0x1e/0x20
Jan 15 17:23:35 localhost kernel:  [schedule+1101/1168] schedule+0x44d/0x490
Jan 15 17:23:35 localhost kernel:  [<c02cf7ad>] schedule+0x44d/0x490
Jan 15 17:23:35 localhost kernel:  [schedule_timeout+90/176] schedule_timeout+0x5a/0xb0
Jan 15 17:23:35 localhost kernel:  [<c02cfb2a>] schedule_timeout+0x5a/0xb0
Jan 15 17:23:35 localhost kernel:  [tty_wait_until_sent+171/240] tty_wait_until_sent+0xab/0xf0
Jan 15 17:23:35 localhost kernel:  [<c01fa1db>] tty_wait_until_sent+0xab/0xf0
Jan 15 17:23:35 localhost kernel:  [uart_close+152/480] uart_close+0x98/0x1e0
Jan 15 17:23:35 localhost kernel:  [<c0209958>] uart_close+0x98/0x1e0
Jan 15 17:23:35 localhost kernel:  [release_dev+1364/1712] release_dev+0x554/0x6b0
Jan 15 17:23:35 localhost kernel:  [<c01f5b04>] release_dev+0x554/0x6b0
Jan 15 17:23:35 localhost kernel:  [tty_release+17/32] tty_release+0x11/0x20
Jan 15 17:23:35 localhost kernel:  [<c01f60f1>] tty_release+0x11/0x20
Jan 15 17:23:35 localhost kernel:  [__fput+240/288] __fput+0xf0/0x120
Jan 15 17:23:35 localhost kernel:  [<c01576c0>] __fput+0xf0/0x120
Jan 15 17:23:35 localhost kernel:  [filp_close+80/144] filp_close+0x50/0x90
Jan 15 17:23:35 localhost kernel:  [<c0155d50>] filp_close+0x50/0x90
Jan 15 17:23:35 localhost kernel:  [pg0+544732060/1069613056] ndt_cleanup+0x4c/0x80 [tmrcdr]
Jan 15 17:23:35 localhost kernel:  [<e0b6d39c>] ndt_cleanup+0x4c/0x80 [tmrcdr]
Jan 15 17:23:35 localhost kernel:  [sys_delete_module+306/384] sys_delete_module+0x132/0x180
Jan 15 17:23:35 localhost kernel:  [<c0131902>] sys_delete_module+0x132/0x180
Jan 15 17:23:35 localhost kernel:  [sysenter_past_esp+82/113] sysenter_past_esp+0x52/0x71
Jan 15 17:23:35 localhost kernel:  [<c0106dcd>] sysenter_past_esp+0x52/0x71
Jan 15 17:23:35 localhost kernel: Attempt to kill tasklet from interrupt
Jan 15 17:23:35 localhost net.agent[6640]: remove event not handled
Jan 15 17:23:35 localhost kernel: ^tstnd: Cleaning Up the Module.
Варварство конечно. Чтение в таком виде:
При инициализации:
Код: (C)
#define BASE     0x3f8      // базовый адрес
#define ICR_N     1         // регистр управления прерываниями

outb_p(10, BASE + ICR_N);
В прерывании таймера:
Код: (C)
//ЧТЕНИЕ РЕГИСТРА СОСТОЯНИЯ ЛИНИИ
data = inb_p(BASE + LSR_N);
printk(KERN_WARNING "^tstnd: Control line registr is: %x\n", data);
reg_lsr.byte = data;
//ПРЯМОЕ ЧТЕНИЕ ИЗ ПОРТА ttyS0
   if (reg_lsr.bit_reg.in_ready != 0) {
   rbf.rc = inb_p(BASE);
   printk(KERN_WARNING "^tstnd: ===PIC=== Reseived char= %s.\n", &rbf.rc);
        shift = tbf->rlen++;
        tbf->rb.rbuff[shift] = tbf->rc;
                if (tbf->rlen > 9) {
                ttys_write(tbf->rb.rbuff, tbf->rlen);
                tbf->rlen = 0;
                }
   } else printk(KERN_WARNING "^tstnd: ===PIC=== Input is empty.%x\n", data);
В общем  :wow: переходящее в  :o

Навигация

[0] Главная страница сообщений

[#] Следующая страница

[*] Предыдущая страница