logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[PoewrPC 405GP][C/Asembler][Linux 2.6.22.1] driver eth

Komar_Rafal 16 Lip 2008 14:11 3700 28
REKLAMA
  • #1 5347804
    Komar_Rafal
    Poziom 10  
    Witam, ma problem z obsluga przerwan w tym procesorze. Bez systemu to zrobic to jest prosto ale jestem poczatkujacym developerem linuxowym i nie wiem jak w driverze zrobic obsluge przerwania (powiedzmy z pinu IRQ3).
    Czy ktos moze mi w tym pomoc ?
  • REKLAMA
  • REKLAMA
  • #3 5347829
    Komar_Rafal
    Poziom 10  
    Juz to dzisiaj przeczytalem i nie rozumiem jednej rzeczy.
    result = request_irq(short_irq, short_interrupt, SA_INTERRUPT, "short", NULL);
    short_irq to numer przerwania. Nie wiem jak ozenic wlasnie ten numer z przerwaniem sprzetowym (np. IRQ3)

    Dodano po 32 [minuty]:

    Juz wiem chyba skad ten numer wziasc, podejrzewam, ze te numery przzerwan przekazywane do funkcji request_irq to te same numery co w datasheet'cie :)
    W ogole to pisze pewien driver do obslugi sterownika ethernotowego. I przerwania sa mi potrzebne do odbioru ramek (jest taki sygnal w tym sterowniku, ktory powinien generowac przerwanie m.in. jak odbierze ramke). I chcialbym to zrobic tak:
    moj driver idzie spac: interruptible_sleep_on
    pojawia sie przerwanie i trzeba odebrac z bufora ta ramke i przeslac ja do wartsw wyzszych.
    I tutaj interesuje mnie odbior. Czy moge to zrobic w funkcji obslugi przerwania (wtedy pewnie wszystkie inne przerwania sa nieaktywne) czy lepiej zrobic to jakos na schedulerze (ale wtedy nie mam gwarancji, ze zdaze odebrac cala ramke)?
  • #5 5353987
    Komar_Rafal
    Poziom 10  
    To jest sterownik zrobiony w VHDlu na Alterze w mojej firmie. Potrafie juz go obsluzyc pod linuxem w driverze znakowym. Teraz chodzi o to, zeby upakowac go w driverze ethernetowym. Rozdzial 17 przeczytalem gdzies do 3/4 juz ;)
  • REKLAMA
  • #6 5354208
    szelus
    Poziom 34  
    To najlepiej wzorować sie na jakimś driverze dla kontrolera majacego podobny interfejs sprzętowy (w VHDL-u można zrobić wszystko ;)).
    Gdzie są bufory? Sterownik ma swoja pamięć? To np. coś ze starszych typu NE2000. Czy master DMA bezpośrednio do pamięci? Ale wtedy chyba nie byłoby problemu...
  • #8 5369700
    Komar_Rafal
    Poziom 10  
    No wiec pisze :)
    Driver juz jako tako chodzi, wysylam zapisujac odpowiednie rejestry w tym dolaczonym urzadzonku, odbieram w przerwaniu (jak cos tam do bufora przyjdzie to to urzadzonko generuje mi przerwanie, wtedy sciagam z buforka odpowiednio dane). Teraz musialbym DMA uruchomic bo jak na razie zapisuje to po slowach a wolalbym zeby to DMA za mnie zrobilo :) Ale poki co mam tez kilka problemow, wrecz magicznych :/
    np.
    mam PC i moja plytke z PowerPC. Ustawiam wsyztskie IP i ARP (na razie nie ma broadcastu, pozniej bedzie :) ). I pinguje sobie z PC na PowerPC i nie zgadniecie co sie dzieje.

    Pare danych:
    PC: 10.10.1.2 00:0C:6E:CA:2B:A2
    PowerPC: eth1 10.10.1.3 00:11:22:33:44:55
    PC:\> ping 10.10.1.3

    zrzut rozkodowanych naglowkow ramek:
    [PoewrPC 405GP][C/Asembler][Linux 2.6.22.1] driver eth
    niech mi teraz ktos madry powie dlaczego pierwsza odpowiedz na pinga jest z adresem zmienionym na ostatniej polowce bajtu o 1 (jest A3 a ma byc A2) a kazda nastepna odpowiedz jest dobra ?

    arp z PowerPC:
    ? (192.168.1.180) at 00:02:3F:0C:FB:A3 [ether] on eth0
    ? (10.10.1.2) at 00:0C:6E:CA:2B:A2 [ether] PERM on eth1
    (moj driver jest na eth1)

    arp z PC:
    dres internetowy Adres fizyczny Typ
    0.10.1.3 00-11-22-33-44-55 statyczne
    92.168.1.1 00-30-4f-28-10-28 dynamiczne
    92.168.1.2 00-17-31-51-b8-b0 dynamiczne
  • #9 5369838
    szelus
    Poziom 34  
    Masz tą swoją płytę podłączoną tylko do PC? Bo na dugim interfejsie masz (prawdopodobnie) tą samą podsieć, co na drugim interfejsie PC. Prawdopodobnie, bo nie podajesz masek. Jak masz podłączone dwoma równoległymi podsieciami, to nie wiadomo którędy pójdzie komunikacja.

    Gdzie i czym łapiesz ten ruch?

    Adresy ostatecznie wpisuje driver, więc i tak obstawiam, że masz babola.
  • #10 5369977
    Komar_Rafal
    Poziom 10  
    Jak adresy wpisuje driver ? Moj driver tylko posyla to co dostanie z wyzszych warstw do tego urzadzonka i sprawdza czy sie zapisalo.

    (...)
    struct net_device *mac_dev;
    mac_dev->hard_start_xmit        = mac_tx;
    (...)
    
    
    int mac_tx(struct sk_buff *skb, struct net_device *dev)
    {
            int len;
            char *data;
            data = skb->data;
            len = skb->len;
            dev->trans_start = jiffies; // save the timestamp
            if (mac_hw_tx(data, len, dev) != 0)
                    return -1;
            return 0;
    }
    
    static int mac_hw_tx(char *data, int len, struct net_device *dev)
    {
            int i, k, tx_buff_fill, tx_buff_free, tx_count, time_out = 0;
            volatile short *tmpPtr;
            Tword word = {0};
            struct mac_priv *priv = netdev_priv(dev);
    
            if (k = len % 4)                                        // how many bytes remind
                    for (i = 1; i <= k; i++)
                            word.byte[k - i] = data[len - i];
            tx_count = len / 4;
            bryce_write_reg_16(BRYCE_TX_THRESHOLD, 8);
            bryce_write_reg_16(BRYCE_TX_FRAME_SIZE, 4 + len);              // frame length + control bytes
            tx_buff_fill = bryce_read_reg_32(BRYCE_TX_BUFF_FILL);
            tx_buff_free = TX_BUFF_SIZE - tx_buff_fill;
            bryce_conf_EBC32();
            if (tx_buff_free >= (4 + len))                                   // whole frame can put to tx buffer
            {
                    //bryce_write_reg_32(BRYCE_TX_BUFF, 0);                 // 4 control bytes
                    tmpPtr = (EBCptr + BRYCE_TX_BUFF / sizeof(short));
                    out32(tmpPtr, 0);
                    for (i = 0; i < tx_count; i++)
                    {
                            //bryce_write_reg_32(BRYCE_TX_BUFF, TXbuff[i].word);
                            out32(tmpPtr, *((int*)&data[i * 4]));
                    }
                    out32(tmpPtr, word.word);                               // remind bytes
            }
            while (!(bryce_read_reg_16(BRYCE_EER) & (1 << TXEOF)))
            {
                    mdelay(1);
                    if (time_out++ == TX_TIMEOUT_MS)
                            return -1;
            }
            priv->stats.tx_packets++;
            priv->stats.tx_bytes += len;
            return 0;
    }


    Z powyzszego kodu w skrocie:
    jak cos sie wysyla na eth1 to wywoluje sie funkcja mac_tx ktorej zadaniem jest po prostu przepisac to co dostala jako parametr (data, len) na moje urzadzenie, ja juz gotowa ramke dostaje.

    Plytka jest do calej sieci podlaczona ale cala siec to 192.168.1.0/24 a dla wlasnych potrzeb stworzylem tylko na tym urzadzeniu i PC podsiec 10.10.1.0/24. wszytskie te ramki podgladam co do bajta i widze ktoredy leca :)
  • #11 5370146
    szelus
    Poziom 34  
    Komar_Rafal napisał:
    Jak adresy wpisuje driver ?

    Tak, że je kopiuje. W te i wewte. Tzn. na odbiorze też. A może za pierwszym razem źle odbiera?
    Dodaj sobie wydruki kontrolne nagłówków, to będziesz wiedział.

    Cytat:

    Plytka jest do calej sieci podlaczona ale cala siec to 192.168.1.0/24 a dla wlasnych potrzeb stworzylem tylko na tym urzadzeniu i PC podsiec 10.10.1.0/24. wszytskie te ramki podgladam co do bajta i widze ktoredy leca :)


    Znaczy, eth1 to interfejs wirtualny? Eh, grunt, to zaczynać od prostej konfiguracji...

    P.S. Znaczniki code, nie kolor
  • #12 5370431
    Komar_Rafal
    Poziom 10  
    szelus napisał:
    Komar_Rafal napisał:
    Jak adresy wpisuje driver ?

    Tak, że je kopiuje. W te i wewte. Tzn. na odbiorze też. A może za pierwszym razem źle odbiera?
    Dodaj sobie wydruki kontrolne nagłówków, to będziesz wiedział.

    Dodalem juz dawno i wszystko wysyla i odbiera sie tak jak to generuja warstwy wyzsze.

    szelus napisał:
    Znaczy, eth1 to interfejs wirtualny? Eh, grunt, to zaczynać od prostej konfiguracji...

    eth1 to interfejs powiazany z driverem sieciowym. No wlasnie niby wsyztsko chodiz procz tej pierwszej ramki na odpowiedz pinga. Jak wysylam pinga z plytki do PC to dzieje sie podobnie, pierwszy ping jest pod ten zmieniony mac adres a nastepne juz pod dobry.

    szelus napisał:
    P.S. Znaczniki code, nie kolor


    Zmienione :)
  • #13 5370932
    szelus
    Poziom 34  
    Komar_Rafal napisał:

    Dodalem juz dawno i wszystko wysyla i odbiera sie tak jak to generuja warstwy wyzsze.

    Tzn. pierwsza ramka przychodzi do drivera z warstwy wyższej z tym adresem A3? Jeżeli tak, to wygląda na jakiś problem z ARPem. Bo aby wysłać tego PING-a, warstwa wyższa znajduje adres docelowy w tablicy ARP. Jeżeli nie masz statycznie, to tego ARPa musi odebrać. Widzisz go (wydruki/analizator)?

    Cytat:

    eth1 to interfejs powiazany z driverem sieciowym. No wlasnie niby wsyztsko chodiz procz tej pierwszej ramki na odpowiedz pinga. Jak wysylam pinga z plytki do PC to dzieje sie podobnie, pierwszy ping jest pod ten zmieniony mac adres a nastepne juz pod dobry.

    A co jest na eth0? I gdzie podłączone? Poza tym, w jakim kontekście pierwszy? Pierwszy w serii, pierwszy po załadowaniu systemu/drivera?
  • #14 5372536
    Komar_Rafal
    Poziom 10  
    szelus napisał:

    Tzn. pierwsza ramka przychodzi do drivera z warstwy wyższej z tym adresem A3? Jeżeli tak, to wygląda na jakiś problem z ARPem. Bo aby wysłać tego PING-a, warstwa wyższa znajduje adres docelowy w tablicy ARP. Jeżeli nie masz statycznie, to tego ARPa musi odebrać. Widzisz go (wydruki/analizator)?

    Tak wlasnie jest, pierwsza ramka przychodzi taka z warstw wyzszych. ARP poki co sam ustawiam:
    arp -s 10.10.1.2 00:0C:6E:CA:2B:A2

    Moja tablica ARP wyglada tak:
    bash-2.05a# arp -a
    ? (10.10.1.2) at 00:0C:6E:CA:2B:A2 [ether] PERM on eth1
    ? (192.168.1.180) at 00:02:3F:0C:FB:A3 [ether] on eth0
    ? (192.168.1.180) at 00:02:3F:0C:FB:A3 [ether] on eth0


    Jak bawilem sie tak z innym PC to dzialo sie dokladnie tak samo, wyglada na to, ze ostatni bicik maca jest zanegowany (bo jak np bylo A3 w adresie to pierwsza rama szla A2).

    szelus napisał:

    A co jest na eth0? I gdzie podłączone?

    eth0 jest w podsieci 192.168.1.0/24, musi byc podlaczone bo tam jest nfs (root file system nie znajduje sie na plytce tylko na PC:192.168.1.180).

    szelus napisał:

    Poza tym, w jakim kontekście pierwszy? Pierwszy w serii, pierwszy po załadowaniu systemu/drivera?

    Powiedzmy, ze pierwszy po pewnym czasie wynoszacym kilka sekund. Co to oznacza? Jak zrobie pinga po restarcie (i odpowiednich ustawieniach) to w serii pinga tylko w pierwszej ramce jest przeklamanie. Jak przerwe pinga i poczekam chwile (kilka sekund) to jest juz wsio ok ale jak poczekam dluzsza chwile to dzieje sie znowu to samo.
  • #15 5372894
    szelus
    Poziom 34  
    Sprawdź, co zawiera tablica ARP (arp -v) kiedy chodzi ping vs. po dłuższej przerwie. Może to coś powie.
    Wpisy w tablicy ARP przedawniają sie po pewnym czasie, ale statyczne raczej nie powinny :?
  • #16 5372931
    Komar_Rafal
    Poziom 10  
    bash-2.05a# arp -v
    Address                  HWtype  HWaddress           Flags Mask            Iface
    xxxxxx.yyyyyyy.pl     ether   00:17:31:51:B8:B0   C                     eth0
    192.168.1.180            ether   00:02:3F:0C:FB:A3   C                     eth0
    10.10.1.2                ether   00:0C:6E:CA:2B:A2   CM                    eth1
    Entries: 3      Skipped: 0      Found: 3
  • REKLAMA
  • #17 5372972
    szelus
    Poziom 34  
    Ale to w czasie, gdy ping chodzi, czy po przerwie? I co jest w drugim przypadku? To samo?
  • #18 5373218
    Komar_Rafal
    Poziom 10  
    To wyzej jest zaraz po pingu, jednoczesnie nie moge sprawdzic bo mam jedna konsole po RS tylko.

    Ponizej ta sama tablica po dluzszej przerwie:

    bash-2.05a# arp -v
    Address                  HWtype  HWaddress           Flags Mask            Iface
    192.168.1.180            ether   00:02:3F:0C:FB:A3   C                     eth0
    10.10.1.2                ether   00:0C:6E:CA:2B:A2   CM                    eth1
    10.10.1.2                ether   00:0C:6E:CA:2B:A2   CM                    eth1
    Entries: 3      Skipped: 0      Found: 3


    Dodano po 7 [minuty]:

    Zauwazylem, ze jezeli tablica arp zmienia sie z tej pierwszej na ta druga to wtedy sie takie cyrki dzieja, a po pierwszym pingu zmienia sie na ta pierwsza znowu.
  • #19 5373362
    szelus
    Poziom 34  
    Hmm... Tochę to podejrzane. Wygląda, jakby był jakiś błąd w obsłudze ARP w Linuxie. Co nie jest niemożliwe, bo przypuszczam, że mało kto wpisuje cokolwiek statycznie do tablicy ARP.

    Dziwne jest zwłaszcza, że w tej drugiej tablicy adres dodany manualnie występuje dwa razy - tak, jakby powielał sie wpis przy usuwaniu (innego) adresu.
    Moja hipoteza byłaby właśnie taka - przy usuwaniu jest błąd, inicjalny lookup (przy ping-u) wybiera niewłaściwy wpis i jednocześnie startuje lookup na drugm interejsie, przychodzący brodcast (ARP) dodaje wpis przesuwając (jakoś) pozostałe + jest gdzieś hazard i przekazany do drivera adres zostaje nadpisany, ale efektywnie tylko ostatni bajt, bo resztę już driver zdążył skopiować.
    Odpowiedź na ping-a nie przychodzi (z oczywistych względów) i po timeoucie ponowny lookup znajduje już właściwy (jedyny) wpis.
  • #20 5373482
    Komar_Rafal
    Poziom 10  
    szelus napisał:
    ...przychodzący brodcast (ARP) dodaje wpis przesuwając (jakoś) pozostałe

    Nie ma przychodzacego broadcastu, broadcast i multicast sa sprzetowo zablokowane, w PC jest po prostu takze w tablicy arp dodany odpowiedni wpis.
  • #21 5373509
    szelus
    Poziom 34  
    W tym miejscu chodziło mi o eth0. Ten pierwszy wpis (z pierwszej tablicy) skądś się przecież bierze. Przez osmozę tego nie złapał ;)
  • #22 5373581
    Komar_Rafal
    Poziom 10  
    Wlasnie mialem przypadek, ze przed i po pingu tablica arp byla taka sama :/
    
    bash-2.05a# arp -v -n
    Address                  HWtype  HWaddress           Flags Mask            Iface
    192.168.1.2              ether   00:17:31:51:B8:B0   C                     eth0
    192.168.1.180            ether   00:02:3F:0C:FB:A3   C                     eth0
    10.10.1.2                ether   00:0C:6E:CA:2B:A2   CM                    eth1
    Entries: 3      Skipped: 0      Found: 3
    bash-2.05a# ping 10.10.1.2
    PING 10.10.1.2 (10.10.1.2): 56 data bytes
    (timeout)
    64 bytes from 10.10.1.2: icmp_seq=1 ttl=128 time=1.5 ms
    64 bytes from 10.10.1.2: icmp_seq=2 ttl=128 time=1.4 ms
    
    --- 10.10.1.2 ping statistics ---
    3 packets transmitted, 2 packets received, 33% packet loss
    round-trip min/avg/max = 1.4/1.4/1.5 ms
    bash-2.05a# arp -v -n
    Address                  HWtype  HWaddress           Flags Mask            Iface
    192.168.1.2              ether   00:17:31:51:B8:B0   C                     eth0
    192.168.1.180            ether   00:02:3F:0C:FB:A3   C                     eth0
    10.10.1.2                ether   00:0C:6E:CA:2B:A2   CM                    eth1
    Entries: 3      Skipped: 0      Found: 3
    bash-2.05a#
    
  • #23 5373746
    szelus
    Poziom 34  
    To sugeruje, że moja hipoteza była błędna, przynajmniej częściowo. Choć niekoniecznie, bo teoretycznie wpis mógł się przedawnić akurat pomiędzy wydanie pierwszej komendy arp a ping.
    W każdym razie, jeżeli chcesz to analizować, to musiałbyś przynajmniej częściowo wniknąć w działanie protokołów sieciowych na Linuxie, a przynajmniej pododawać więcej wydruków kontrolnych (np w obsłudze arp-a itp).
  • #24 5373810
    Komar_Rafal
    Poziom 10  
    a skad bys chcial wydruki kontrolne ? :)
    pamietaj tylko, ze mam jedna konsole.
  • #25 5373923
    szelus
    Poziom 34  
    Obawiam się, że ja Ci na razie za dużo nie pomogę, bo czas już mi się kończy i muszę "zniknąć" na c.a. dwa tygodnie.

    Nie pamiętam też już - musiałbym przejrzeć dokładnie kod, a nie bardzo mam teraz czas.

    W każdym razie, należałoby wrzucić printk na lookup ARP, może dodawanie i usuwanie z tablicy (to chyba w arp.c, ale nie dam głowy) + drukowanie nagłówków ramek na wejściu/wyjściu z drivera. Potem - w zależności od rezultatów i podejrzeń.
    Przy jednej konsoli jest tego trochę, ale da się żyć ;) Zresztą, można to wyrzucać na poziomie ERROR to powinno automatycznie pójść do log-u (a jak nie, to odpowiednio skonfigurować syslog-a).

    A może to nie Twój problem i jak włączysz dynamiczne arp-y to problem "magicznie" zniknie ?

    W każdym razie - powodzenia.
  • #26 5410237
    Komar_Rafal
    Poziom 10  
    Dziwne rzeczy tu sie dzieja. Jak wysyla sie normalne zapytanie arp z plytki to moj driver dostaje do wyslania cos takiego:
    0x0000: FF FF FF FF FF FE 00 11 22 33 44 55 08 06 00 01 
    0x0010: 08 00 06 04 00 01 00 11 22 33 44 55 0A 0A 01 03 
    0x0020: 00 00 00 00 00 00 0A 0A 01 05 
    


    broadcast: FF:FF:FF:FF:FF:FE
    src MAC: 00:11:22:33:44:55
    type: 0x0806 - ARP

    Hrdw type: 0x0001
    Protocol type: 0x0800
    Hrwd length: 0x06
    Protocol length: 0x04
    Operation: 0x0001 - ARP request
    Src MAC: 00:11:22:33:44:55
    Src IP: 10.10.1.3 (0x 0A 0A 01 03)
    Dest MAC: 00:00:00:00:00:00
    Dest IP: 10.10.1.5 (0x 0A 0A 01 05)

    i wszystko by sie zgaqdzalo gdyby nie ten zmieniony znowu jeden bicik (zamiast FF jest FE, tak jak poprzednio zaiast 02 bylo 03). I zapytanie ARP, poniewaz nie dostaje odpowiedzi, jest powtarzane caly czas z tym bledem.

    Podobnie dzieje sie jak w PC wywale z tablicy ARP adres plytki. Wtedy ping z PC najpierw pyta sie kto ma taki mac i patrzcie co sie dzieje:

    Zapytanie z PC:
    0x0000 ff ff ff ff ff ff 00 0c  6e ca 2b a2 08 06 00 01  
    0x0010 08 00 06 04 00 01 00 0c  6e ca 2b a2 0a 0a 01 02  
    0x0020 00 00 00 00 00 00 0a 0a  01 03 
    


    Odpowiedz z plytki:
    0x0000: 00 0C 6E CA 2B A3 00 11 22 33 44 55 08 06 00 01
    0x0010: 08 00 06 04 00 02 00 11 22 33 44 55 0A 0A 01 03
    0x0020: 00 0C 6E CA 2B A2 0A 0A 01 02
    


    Widzicie, ze zapytanie jest z adresu:
    00:0C:6E:CA:2B:A2
    a odpowiedz idzie na adres:
    00:0C:6E:CA:2B:A3

    dlaczego ? ;( ;( :(
    Pomocy bo juz mam tego dosyc :/
  • #28 5432275
    Komar_Rafal
    Poziom 10  
    Juz rozwiazalem problem :D Kierowalem sie ksiazka Linux Device Drivers i zrobilem sobie na tej podstawie szkielet drivera. A potem jak go dostosowywalem do swoich potrzeb to nie usunalem funkcji rebuild_header a tam bylo zeby zmienial ten ostatni bajcik :D Teraz wszystko dziala :)
REKLAMA