Uživatel:FroxDev/Btcode
Z 8.B8 wiki
< Uživatel:FroxDev(Rozdíly mezi verzemi)
m (Stránka FroxDev/Btcode přemístěna na stránku Uživatel:FroxDev/Btcode: jsem blb) |
|||
Řádka 7: | Řádka 7: | ||
=== exception_matrix === | === exception_matrix === | ||
* přečte registr CP0_CAUSE a podle kódu výjimky zavolá příslušný handler v poli exception_handlers | * přečte registr CP0_CAUSE a podle kódu výjimky zavolá příslušný handler v poli exception_handlers | ||
+ | |||
+ | == inthandler.S == | ||
+ | === IRQ_finder === | ||
+ | * SAVE_ALL - zjednodušeně řečeno uloží stav procesoru do nového zásobníku | ||
+ | * CLI - zastaví další přerušení a přepne se do kernel módu | ||
+ | * přečte registry CP0_CAUSE a CP0_STATUS, vybere pouze bity čekajících přerušení a uloží do t2 | ||
+ | * do argumentů a0, a1 uloží obsah registrů GISR a GIMR, opět vybere do a0 bity čekajících | ||
+ | * pokud je zde čekající přerušení (t2 != 0) tak skáče na irq_dispatch() s argumenty a0, a1 | ||
+ | * jinak do registru UART_THR vloží znak m a tuhne pomocí cyklu | ||
+ | * RESTORE_ALL_AND_RET - zjednodušeně řečeno načte původní stav procesoru před přerušením a končí instrukcí ret | ||
== setup.c == | == setup.c == | ||
=== init_arch === | === init_arch === | ||
* v registru CP0_STATUS vypne mód 64bit a ostatní koprocesory, zapne pouze CP0 | * v registru CP0_STATUS vypne mód 64bit a ostatní koprocesory, zapne pouze CP0 | ||
- | * | + | * start_kernel() |
=== setup_arch === | === setup_arch === | ||
Řádka 35: | Řádka 45: | ||
* cli - vypne všechna přerušení | * cli - vypne všechna přerušení | ||
* uart1_init() na zjištenou rychlost | * uart1_init() na zjištenou rychlost | ||
- | * | + | * flashinit() |
+ | * check_eth_setting() | ||
+ | * prom_printf() - přivítání, verze | ||
+ | * nastaví GPIO A - 2, 3, 7, 8 na output a 1 - LEDky ??svítí červená? | ||
+ | * check_system_image() pro tři různé offsety ve flash paměti, vybere se ten funkční | ||
+ | * když je obraz v pořádku a user_interrupt(3sec) vrací 0, tak | ||
+ | ** přečtení celé hlavičky obrazu | ||
+ | ** flashread() - překopírování obrazu do SDRAM na určenou adresu | ||
+ | ** znovu ověří user_interrupt(0), zda uživatel nezmáčknul reset během načítání obrazu, ale tentokrát bez čekání | ||
+ | ** zastaví všechna přerušení pomocí GIMR0 | ||
+ | ** nastaví GPIO A-2 na output a 1 - červená stále svítí | ||
+ | ** prom_printf() - oznámení skoku na systém | ||
+ | ** cli - zastaví přerušení i v koprocesoru | ||
+ | ** flush_icache() a flush_dcache() | ||
+ | ** skok na počátek obrazu linuxu, bez návratu | ||
+ | * jinak při user_interrupt() vypíše prom_printf() escape a nastaví GPIOA-2 na output a 0 | ||
+ | ** dále pro oba případy (poškozený obraz, user_interrupt) | ||
+ | ** eth_driver_object_init() | ||
+ | ** eth_startup(0) | ||
+ | ** sti - zapnutí všech přerušení | ||
+ | ** tftpd_entry() | ||
+ | ** monitor() | ||
+ | |||
+ | === user_interrupt === | ||
+ | * nastaví GPIOA-0 na vstup | ||
+ | * spustí druhý časovač na odpočet tří sekund | ||
+ | * provádí smyčku dokud časovač není 0 | ||
+ | ** ověří zda jsou data na UARTu, když jo tak je přečte, pokud je tam ESC, tak vrací 0 | ||
+ | ** ověří zda na GPIOA-0 je 0, když ano, tak nastaví časovač na 1sec a po tu dobu musí být reset stisknutý, aby vrátilo 1 | ||
+ | * jinak vrací 0 | ||
+ | |||
+ | === check_system_image === | ||
+ | * přečte hlavičku firmwaru a ověří podpis memcmp() - první 4 bajty, když nesedí tak prom_printf() error | ||
+ | * spočítá kontrolní součet pro celou délku obrazu, když nesedí, tak prom_printf() error | ||
+ | * pokud nedojde k chybě tak vrací počáteční adresu obrazu | ||
=== uart1_init === | === uart1_init === | ||
Řádka 47: | Řádka 91: | ||
=== set_bridge_clock === | === set_bridge_clock === | ||
* nastaví v registru BDGCR hodnoty dělení rychlosti jednotlivých sběrnic, v závislosti na rychlosti cpu a hodnoty 0xBD01010C ??význam? | * nastaví v registru BDGCR hodnoty dělení rychlosti jednotlivých sběrnic, v závislosti na rychlosti cpu a hodnoty 0xBD01010C ??význam? | ||
+ | |||
+ | == ethInt_8186.c == | ||
+ | === eth_driver_object_init === | ||
+ | * inicializuje pole ETH[0] odpovídajícími hodnotami | ||
+ | * vynuluje ETH0_rx_buf a ETH0_tx_buf | ||
+ | |||
+ | === eth_startup === | ||
+ | * eth_hw_reset(0) | ||
+ | * eth_desc_init(0) | ||
+ | * request_IRQ() na funkci eth_interrupt() | ||
+ | |||
+ | === eth_hw_reset === | ||
+ | * memcpy() - zkopíruje si MAC adresu do lokální proměnné | ||
+ | * prohodí pořadí bajtů v MAC adrese a vepíše ji do NIC_ID | ||
+ | * pomocí registru NIC_CR resetuje ethernet čip a počká 0xffff cyklů | ||
+ | * do NIC_MAR píše ffffffffffffffff | ||
+ | * nastavuje velikost gap v NIC_TCR | ||
+ | * v NIC_RCR zapíná příjem všech paketů | ||
+ | * nastavení módu v NIC_MII na full 100Mbit | ||
+ | * v NIC_RXRINGNO nastaví 64 deskriptorů | ||
+ | * do NIC_TXFDPL vloží adresu na frontu tx, po převodu na fyzickou adresu | ||
+ | * to samé s NIC_RXFDP, fronta rx | ||
+ | * NIC_IMR a NIC_ISR - zapnout a vynulovat všechna přerušení | ||
+ | * konfigurace NIO_IOCMD - nastavení rx a tx front atd. | ||
+ | |||
+ | === eth_desc_init === | ||
+ | * nastaví buffer pro každý z deskriptorů rx, SetOwnByNic() nastaví hlavičku | ||
+ | |||
+ | === SetOwnByNic === | ||
+ | * na základě předaných parametrů nastaví hlavičku pro rx deskriptor | ||
+ | |||
+ | === eth_interrupt === | ||
+ | * pokračuje ovládáním ethernet ovladače, POKRAČOVÁNÍ! | ||
+ | |||
+ | == string.c == | ||
+ | === memcmp === | ||
+ | * porovná všechny bajty daných dvou polí a vrací 0 při shodě | ||
+ | |||
+ | === memcpy === | ||
+ | * zkopíruje obsah jednoho pole do druhého | ||
+ | |||
+ | == init.c == | ||
+ | === serial_outc === | ||
+ | * počká 3210 cyklů na vyprázdnění transmitter bufferu u UART0 (rtl_inb UART_LSR) | ||
+ | * rtl_outb - UART_THR - vepíše žádaný znak do UARTu | ||
+ | * pokud vepsaný znak je LF, tak je vepsáno ještě CR | ||
+ | |||
+ | == flash.c == | ||
+ | === flashinit === | ||
+ | * vepíše na adresy 0xBExxxxxx několik hodnot ??význam? | ||
+ | * přečte první čtyři bajty na 0xBE000000 - id výrobce a zařízení | ||
+ | * vypíše to pomocí prom_printf() | ||
+ | * ověří podle tabulky typů paměti zda se jedná o známý typ | ||
+ | ** když ne, tak prom_printf() chyba a ukončí funkci | ||
+ | * jinak jede dál, nastaví registr MCR správně podle zjištěného typu paměti | ||
+ | * zkusí za první flash pamětí najít druhou, vepíše několik hodnot ??význam? | ||
+ | * přečte idčka a ověří zda se shodují s první pamětí, když ano, tak se zdvojnásobí velikosti | ||
+ | * vypíše celkovou velikost paměti - prom_printf() | ||
+ | * inicializuje strukturu map podle tabulkových hodnot | ||
+ | |||
+ | === check_eth_setting === | ||
+ | * pro RTL8186 neprovádní nic | ||
+ | |||
+ | === flashread === | ||
+ | * když potřebná délka je 0 vrací hned 1 | ||
+ | * pokud zdrojová adresa není zarovnána na 16 bitů, je potřeba první a poslední bajt přečíst zvlášť | ||
+ | * jinak po dvou bajtech kopíruje pomocí memcpy() | ||
== misc.c == | == misc.c == | ||
Řádka 111: | Řádka 222: | ||
=== change_cp0_status === | === change_cp0_status === | ||
* podle masky aktualizuje hodnotu v registru CP0_STATUS | * podle masky aktualizuje hodnotu v registru CP0_STATUS | ||
+ | |||
+ | === irq_dispatch === | ||
+ | * pro každé validní id přerušení 0-6 provede do_IRQ() | ||
+ | |||
+ | === do_IRQ === | ||
+ | * pokud příslušné pole ve struktuře irq_action není null, tak se zavolá handler z této struktury | ||
+ | * jinak prom_printf() s irq číslem a zatuhneme | ||
== monitor.c == | == monitor.c == | ||
Řádka 126: | Řádka 244: | ||
=== timer_init === | === timer_init === | ||
* zapne nultý časovač jako timer, nastaví data na 35B60, čili 10ms a zapne přerušení (registry TCCNR, TC0DATA, TCIR) | * zapne nultý časovač jako timer, nastaví data na 35B60, čili 10ms a zapne přerušení (registry TCCNR, TC0DATA, TCIR) | ||
+ | |||
+ | === monitor === | ||
+ | * pokračuje sledováním vstupu ze sériového portu - POKRAČOVÁNÍ! | ||
+ | |||
+ | == eth_tftpd.c == | ||
+ | === tftpd_entry === | ||
+ | * inicializace pole arptable_tftp, server jako 192.168.1.6, klient jako 192.168.1.116 | ||
+ | * nastavení bootState na init | ||
+ | * inicializace struktury nic, sdílí pole s ethernet driverem | ||
+ | * block_expected na 0 - číslo následujícího bloku dat | ||
+ | * one_tftp_lock na 0 | ||
+ | * it_is_EOF na 0 - není poslední blok | ||
+ | * address_to_store na 0x80300000 | ||
+ | * file_length_to_server, file_length_to_client - délka přijatého souboru přes tftp - 0 | ||
+ | * SERVER_port na 2098 |
Aktuální verze z 24. 5. 2010, 14:49
Obsah |
head.S
entry point
- vloží do registru sp adresu na strukturu init_task_union, resp. na její poslední volné místo
- vynuluje prostor pro statické proměnné bootloaderu, následovaný za code segmentem
- zavolá init_arch()
exception_matrix
- přečte registr CP0_CAUSE a podle kódu výjimky zavolá příslušný handler v poli exception_handlers
inthandler.S
IRQ_finder
- SAVE_ALL - zjednodušeně řečeno uloží stav procesoru do nového zásobníku
- CLI - zastaví další přerušení a přepne se do kernel módu
- přečte registry CP0_CAUSE a CP0_STATUS, vybere pouze bity čekajících přerušení a uloží do t2
- do argumentů a0, a1 uloží obsah registrů GISR a GIMR, opět vybere do a0 bity čekajících
- pokud je zde čekající přerušení (t2 != 0) tak skáče na irq_dispatch() s argumenty a0, a1
- jinak do registru UART_THR vloží znak m a tuhne pomocí cyklu
- RESTORE_ALL_AND_RET - zjednodušeně řečeno načte původní stav procesoru před přerušením a končí instrukcí ret
setup.c
init_arch
- v registru CP0_STATUS vypne mód 64bit a ostatní koprocesory, zapne pouze CP0
- start_kernel()
setup_arch
- nastaví ST0_BEV v CP0_STATUS na 0 - bootstrap mode a zapne přerušení 0, 2, 3, 4, 5 ??ST0_BEV význam?
traps.c
flush_icache
- za zastavených přerušení nastaví druhý bit CP0_XCONTEXT na 0 a pak na 1 ?? efekt?
flush_dcache
- za zastavených přerušení nastaví první bit CP0_XCONTEXT na 0 a pak na 1 ?? efekt?
main.c
start_kernel
- flush_icache() a flush_dcache()
- setup_arch()
- exception_init()
- init_IRQ()
- rtl_outl - GPIO F data - 0
- check_cpu_speed() - uloží do lokální proměnné
- set_bridge_clock() na zjištěnou rychlost
- rtl_outl - GPIO F data - 1
- cli - vypne všechna přerušení
- uart1_init() na zjištenou rychlost
- flashinit()
- check_eth_setting()
- prom_printf() - přivítání, verze
- nastaví GPIO A - 2, 3, 7, 8 na output a 1 - LEDky ??svítí červená?
- check_system_image() pro tři různé offsety ve flash paměti, vybere se ten funkční
- když je obraz v pořádku a user_interrupt(3sec) vrací 0, tak
- přečtení celé hlavičky obrazu
- flashread() - překopírování obrazu do SDRAM na určenou adresu
- znovu ověří user_interrupt(0), zda uživatel nezmáčknul reset během načítání obrazu, ale tentokrát bez čekání
- zastaví všechna přerušení pomocí GIMR0
- nastaví GPIO A-2 na output a 1 - červená stále svítí
- prom_printf() - oznámení skoku na systém
- cli - zastaví přerušení i v koprocesoru
- flush_icache() a flush_dcache()
- skok na počátek obrazu linuxu, bez návratu
- jinak při user_interrupt() vypíše prom_printf() escape a nastaví GPIOA-2 na output a 0
- dále pro oba případy (poškozený obraz, user_interrupt)
- eth_driver_object_init()
- eth_startup(0)
- sti - zapnutí všech přerušení
- tftpd_entry()
- monitor()
user_interrupt
- nastaví GPIOA-0 na vstup
- spustí druhý časovač na odpočet tří sekund
- provádí smyčku dokud časovač není 0
- ověří zda jsou data na UARTu, když jo tak je přečte, pokud je tam ESC, tak vrací 0
- ověří zda na GPIOA-0 je 0, když ano, tak nastaví časovač na 1sec a po tu dobu musí být reset stisknutý, aby vrátilo 1
- jinak vrací 0
check_system_image
- přečte hlavičku firmwaru a ověří podpis memcmp() - první 4 bajty, když nesedí tak prom_printf() error
- spočítá kontrolní součet pro celou délku obrazu, když nesedí, tak prom_printf() error
- pokud nedojde k chybě tak vrací počáteční adresu obrazu
uart1_init
- rtl_outb - UART_LCR - 8bit words, no parity, one stop bit
- rtl_outb - UART_DLM, UART_DLL - nastasvení baudrate v závislosti na rychlosti cpu
- rtl_outb - UART_LCR, UART_FCR - vypnutí FIFO a reset, znovu nastavení 8bit words
- prázdná smyčka, 4096 opakování
- rtl_outb - UART_FCR, UART_MCR - vynulování, disable flow control
- prom_printf() - oznámení načtení uart
set_bridge_clock
- nastaví v registru BDGCR hodnoty dělení rychlosti jednotlivých sběrnic, v závislosti na rychlosti cpu a hodnoty 0xBD01010C ??význam?
ethInt_8186.c
eth_driver_object_init
- inicializuje pole ETH[0] odpovídajícími hodnotami
- vynuluje ETH0_rx_buf a ETH0_tx_buf
eth_startup
- eth_hw_reset(0)
- eth_desc_init(0)
- request_IRQ() na funkci eth_interrupt()
eth_hw_reset
- memcpy() - zkopíruje si MAC adresu do lokální proměnné
- prohodí pořadí bajtů v MAC adrese a vepíše ji do NIC_ID
- pomocí registru NIC_CR resetuje ethernet čip a počká 0xffff cyklů
- do NIC_MAR píše ffffffffffffffff
- nastavuje velikost gap v NIC_TCR
- v NIC_RCR zapíná příjem všech paketů
- nastavení módu v NIC_MII na full 100Mbit
- v NIC_RXRINGNO nastaví 64 deskriptorů
- do NIC_TXFDPL vloží adresu na frontu tx, po převodu na fyzickou adresu
- to samé s NIC_RXFDP, fronta rx
- NIC_IMR a NIC_ISR - zapnout a vynulovat všechna přerušení
- konfigurace NIO_IOCMD - nastavení rx a tx front atd.
eth_desc_init
- nastaví buffer pro každý z deskriptorů rx, SetOwnByNic() nastaví hlavičku
SetOwnByNic
- na základě předaných parametrů nastaví hlavičku pro rx deskriptor
eth_interrupt
- pokračuje ovládáním ethernet ovladače, POKRAČOVÁNÍ!
string.c
memcmp
- porovná všechny bajty daných dvou polí a vrací 0 při shodě
memcpy
- zkopíruje obsah jednoho pole do druhého
init.c
serial_outc
- počká 3210 cyklů na vyprázdnění transmitter bufferu u UART0 (rtl_inb UART_LSR)
- rtl_outb - UART_THR - vepíše žádaný znak do UARTu
- pokud vepsaný znak je LF, tak je vepsáno ještě CR
flash.c
flashinit
- vepíše na adresy 0xBExxxxxx několik hodnot ??význam?
- přečte první čtyři bajty na 0xBE000000 - id výrobce a zařízení
- vypíše to pomocí prom_printf()
- ověří podle tabulky typů paměti zda se jedná o známý typ
- když ne, tak prom_printf() chyba a ukončí funkci
- jinak jede dál, nastaví registr MCR správně podle zjištěného typu paměti
- zkusí za první flash pamětí najít druhou, vepíše několik hodnot ??význam?
- přečte idčka a ověří zda se shodují s první pamětí, když ano, tak se zdvojnásobí velikosti
- vypíše celkovou velikost paměti - prom_printf()
- inicializuje strukturu map podle tabulkových hodnot
check_eth_setting
- pro RTL8186 neprovádní nic
flashread
- když potřebná délka je 0 vrací hned 1
- pokud zdrojová adresa není zarovnána na 16 bitů, je potřeba první a poslední bajt přečíst zvlášť
- jinak po dvou bajtech kopíruje pomocí memcpy()
misc.c
prom_printf
- vsprintf() - pouze předání argumentů, buffer je null
vsprintf
- projde celý řetězec fmt pro každý znak, dokud není null
- když přečtený znak není %, tak
- když buffer není null, tak se do něj tento znak vloží
- jinak se na daný znak volá putchar - serial_outc()
- jinak se pomocí zjednodušených algoritmů přečtou znaky a vyhodnotí, využívá funkci SprintF()
- vrací počet vepsaných znaků
SprintF
- vsprintf() - stejné argumenty
irq.c
exception_init
- clear_cp0_status - bit ST0_BEV
- set_except_vector() - vepíše do všech vyjímkových handlerů (32) funkci do_reserved()
- memcpy() - zkopíruje kód exception_matrix na adresu 0x80000080 - místo příjmu výjimky
- flush_icache()
- sti - zapíná přerušení
set_except_vector
- vloží adresu na danou metodu na určený index pole exception_handlers - ovladače pro chytání jednotlivých výjimek
clear_cp0_status
- na označené bity v masce uloží hodnotu 0
do_reserved
- prom_printf() - vypíše chybu a uvízne v nekonečném cyklu
init_IRQ
- ExceptionToIrq_setup()
request_IRQ
- ověří jestli číslo přerušení je menší než jejich počet - 64, jinak vrací -1
- vloží předané dev_id do předané struktury
- setup_IRQ() na dané hodnoty
- unmask_IRQ() na dané číslo přerušení
- vrací hodnotu GIMR0
setup_IRQ
- save_and_cli
- do pole irq_action nastaví na příslušný index přerušení zadanou strukturu
- restore_flags
free_IRQ
- mask_IRQ()
mask_IRQ
- vypne bit přerušení v GIMR0
unmask_IRQ
- zapne přerušení daného čísla v GIMR0 - speciální registr pro konfiguraci přerušení
ExceptionToIrq_setup
- change_cp0_status() - CP0_IM - vypíná přerušení
- set_except_vector() - jako handler pro výjimky typu přerušení nastavuje IRQ_finder
- change_cp0_status() - zapíná přerušení
change_cp0_status
- podle masky aktualizuje hodnotu v registru CP0_STATUS
irq_dispatch
- pro každé validní id přerušení 0-6 provede do_IRQ()
do_IRQ
- pokud příslušné pole ve struktuře irq_action není null, tak se zavolá handler z této struktury
- jinak prom_printf() s irq číslem a zatuhneme
monitor.c
check_cpu_speed
- request_IRQ() - žádá o timer interrupt na strukturu irq_timer, kde je handler timer_interrupt()
- timer_init()
- algoritmicky spočítá, kolik instrukcí je provedeno v jednom 10ms bloku
- vypne přerušení timeru (registry TCCNR, TCIR)
- free_IRQ() - uvolní timer interrupt
- vrací rychlost procesoru v MHz
timer_interrupt
- inkrementuje jiffies
timer_init
- zapne nultý časovač jako timer, nastaví data na 35B60, čili 10ms a zapne přerušení (registry TCCNR, TC0DATA, TCIR)
monitor
- pokračuje sledováním vstupu ze sériového portu - POKRAČOVÁNÍ!
eth_tftpd.c
tftpd_entry
- inicializace pole arptable_tftp, server jako 192.168.1.6, klient jako 192.168.1.116
- nastavení bootState na init
- inicializace struktury nic, sdílí pole s ethernet driverem
- block_expected na 0 - číslo následujícího bloku dat
- one_tftp_lock na 0
- it_is_EOF na 0 - není poslední blok
- address_to_store na 0x80300000
- file_length_to_server, file_length_to_client - délka přijatého souboru přes tftp - 0
- SERVER_port na 2098