From ba3fb040e167bd1894f0d3d3af213cbe1b48ba4c Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Sun, 20 Jun 2010 22:36:52 +0000 Subject: [PATCH] Net-branch: another work in progress: dec21x4x driver. Only works in MS Virtual-PC for now. (not on real hardware yet) git-svn-id: svn://kolibrios.org@1502 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/branches/net/drivers/dec21x4x.asm | 1467 ++++++++++++++++++++++ kernel/branches/net/drivers/netdrv.inc | 69 +- 2 files changed, 1517 insertions(+), 19 deletions(-) create mode 100644 kernel/branches/net/drivers/dec21x4x.asm diff --git a/kernel/branches/net/drivers/dec21x4x.asm b/kernel/branches/net/drivers/dec21x4x.asm new file mode 100644 index 0000000000..d1a398b461 --- /dev/null +++ b/kernel/branches/net/drivers/dec21x4x.asm @@ -0,0 +1,1467 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; DEC 21x4x driver for KolibriOS ;; +;; ;; +;; Based on dec21140.Asm from Solar OS by ;; +;; Eugen Brasoveanu, ;; +;; Ontanu Bogdan Valentin ;; +;; ;; +;; Written by hidnplayr@kolibrios.org ;; +;; ;; +;; 0.1 - 5 june 2010 ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +format MS COFF + + API_VERSION equ 0x01000100 + + DEBUG equ 1 + __DEBUG__ equ 1 + __DEBUG_LEVEL__ equ 1 + +include 'proc32.inc' +include 'imports.inc' +include 'fdo.inc' +include 'netdrv.inc' + +OS_BASE equ 0 +new_app_base equ 0x60400000 +PROC_BASE equ OS_BASE+0x0080000 + +public START +public service_proc +public version + + +virtual at ebx + + device: + + ETH_DEVICE + +; device specific + .rx_p_des dd ? ; descriptors ring with received packets + .tx_p_des dd ? ; descriptors ring with 'to transmit' packets + .tx_free_des dd ? ; Tx descriptors available + .tx_wr_des dd ? ; Tx current descriptor to write data to + .tx_rd_des dd ? ; Tx current descriptor to read TX completion + .rx_crt_des dd ? ; Rx current descriptor + + .io_addr dd ? + .pci_bus db ? + .pci_dev db ? + .irq_line db ? + + .size = $ - device + +end virtual + + + +MAX_DEVICES equ 16 + +;------------------------------------------- +; configuration registers +;------------------------------------------- +CFCS equ 4 ; configuration and status register + +CSR0 equ 0x00 ; Bus mode +CSR1 equ 0x08 ; Transmit Poll Command +CSR2 equ 0x10 ; Receive Poll Command +CSR3 equ 0x18 ; Receive list base address +CSR4 equ 0x20 ; Transmit list base address +CSR5 equ 0x28 ; Status +CSR6 equ 0x30 ; Operation mode +CSR7 equ 0x38 ; Interrupt enable +CSR8 equ 0x40 ; Missed frames and overflow counter +CSR9 equ 0x48 ; Boot ROM, serial ROM, and MII management +CSR10 equ 0x50 ; Boot ROM programming address +;CSR11 General-purpose timer 0x58 +CSR12 equ 0x60 ; General-purpose port +CSR13 equ 0x68 +;CSR14 Reserved 0x70 +;CSR15 Watchdog timer 0x78 + +;--------bits/commands of CSR0------------------- +CSR0_RESET equ 1b + +CSR0_WIE equ 1 SHL 24 ; Write and Invalidate Enable +CSR0_RLE equ 1 SHL 23 ; PCI Read Line Enable +CSR0_RML equ 1 SHL 21 ; PCI Read Multiple + +CSR0_CACHEALIGN_NONE equ 00b SHL 14 +CSR0_CACHEALIGN_32 equ 01b SHL 14 +CSR0_CACHEALIGN_64 equ 10b SHL 14 +CSR0_CACHEALIGN_128 equ 11b SHL 14 + +; using values from linux driver.. :P +CSR0_DEFAULT equ CSR0_WIE+CSR0_RLE+CSR0_RML+CSR0_CACHEALIGN_NONE ;32 + +;------- CSR5 -STATUS- bits -------------------------------- +CSR5_TI equ 1 SHL 0 ; Transmit interupt - frame transmition completed +CSR5_TPS equ 1 SHL 1 ; Transmit process stopped +CSR5_TU equ 1 SHL 2 ; Transmit Buffer unavailable +CSR5_TJT equ 1 SHL 3 ; Transmit Jabber Timeout (transmitter had been excessively active) +CSR5_UNF equ 1 SHL 5 ; Transmit underflow - FIFO underflow +CSR5_RI equ 1 SHL 6 ; Receive Interrupt +CSR5_RU equ 1 SHL 7 ; Receive Buffer unavailable +CSR5_RPS equ 1 SHL 8 ; Receive Process stopped +CSR5_RWT equ 1 SHL 9 ; Receive Watchdow Timeout +CSR5_ETI equ 1 SHL 10 ; Early transmit Interrupt +CSR5_GTE equ 1 SHL 11 ; General Purpose Timer Expired +CSR5_FBE equ 1 SHL 13 ; Fatal bus error +CSR5_ERI equ 1 SHL 14 ; Early receive Interrupt +CSR5_AIS equ 1 SHL 15 ; Abnormal interrupt summary +CSR5_NIS equ 1 SHL 16 ; normal interrupt summary +CSR5_RS_SH equ 1 SHL 17 ; Receive process state -shift +CSR5_RS_MASK equ 111b ; -mask +CSR5_TS_SH equ 1 SHL 20 ; Transmit process state -shift +CSR5_TS_MASK equ 111b ; -mask +CSR5_EB_SH equ 1 SHL 23 ; Error bits -shift +CSR5_EB_MASK equ 111b ; Error bits -mask + +;CSR5 TS values +CSR5_TS_STOPPED equ 000b +CSR5_TS_RUNNING_FETCHING_DESC equ 001b +CSR5_TS_RUNNING_WAITING_TX equ 010b +CSR5_TS_RUNNING_READING_BUFF equ 011b +CSR5_TS_RUNNING_SETUP_PCKT equ 101b +CSR5_TS_SUSPENDED equ 110b +CSR5_TS_RUNNING_CLOSING_DESC equ 111b + +;------- CSR6 -OPERATION MODE- bits -------------------------------- +CSR6_HP equ 1 SHL 0 ; Hash/Perfect Receive Filtering mode +CSR6_SR equ 1 SHL 1 ; Start/Stop receive +CSR6_HO equ 1 SHL 2 ; Hash only Filtering mode +CSR6_PB equ 1 SHL 3 ; Pass bad frames +CSR6_IF equ 1 SHL 4 ; Inverse filtering +CSR6_SB equ 1 SHL 5 ; Start/Stop backoff counter +CSR6_PR equ 1 SHL 6 ; Promiscuos mode -default after reset +CSR6_PM equ 1 SHL 7 ; Pass all multicast +CSR6_F equ 1 SHL 9 ; Full Duplex mode +CSR6_OM_SH equ 1 SHL 10 ; Operating Mode -shift +CSR6_OM_MASK equ 11b ; -mask +CSR6_FC equ 1 SHL 12 ; Force Collision Mode +CSR6_ST equ 1 SHL 13 ; Start/Stop Transmission Command +CSR6_TR_SH equ 1 SHL 14 ; Threshold Control -shift +CSR6_TR_MASK equ 11b ; -mask +CSR6_CA equ 1 SHL 17 ; Capture Effect Enable +CSR6_PS equ 1 SHL 18 ; Port select SRL / MII/SYM +CSR6_HBD equ 1 SHL 19 ; Heartbeat Disable +CSR6_SF equ 1 SHL 21 ; Store and Forward -transmit full packet only +CSR6_TTM equ 1 SHL 22 ; Transmit Threshold Mode - +CSR6_PCS equ 1 SHL 23 ; PCS active and MII/SYM port operates in symbol mode +CSR6_SCR equ 1 SHL 24 ; Scrambler Mode +CSR6_MBO equ 1 SHL 25 ; Must Be One +CSR6_RA equ 1 SHL 30 ; Receive All +CSR6_SC equ 1 SHL 31 ; Special Capture Effect Enable + + +;------- CSR7 -INTERRUPT ENABLE- bits -------------------------------- +CSR7_TI equ 1 SHL 0 ; transmit Interrupt Enable (set with CSR7<16> & CSR5<0> ) +CSR7_TS equ 1 SHL 1 ; transmit Stopped Enable (set with CSR7<15> & CSR5<1> ) +CSR7_TU equ 1 SHL 2 ; transmit buffer underrun Enable (set with CSR7<16> & CSR5<2> ) +CSR7_TJ equ 1 SHL 3 ; transmit jabber timeout enable (set with CSR7<15> & CSR5<3> ) +CSR7_UN equ 1 SHL 5 ; underflow Interrupt enable (set with CSR7<15> & CSR5<5> ) +CSR7_RI equ 1 SHL 6 ; receive Interrupt enable (set with CSR7<16> & CSR5<5> ) +CSR7_RU equ 1 SHL 7 ; receive buffer unavailable enable (set with CSR7<15> & CSR5<7> ) +CSR7_RS equ 1 SHL 8 ; Receive stopped enable (set with CSR7<15> & CSR5<8> ) +CSR7_RW equ 1 SHL 9 ; receive watchdog timeout enable (set with CSR7<15> & CSR5<9> ) +CSR7_ETE equ 1 SHL 10 ; Early transmit Interrupt enable (set with CSR7<15> & CSR5<10> ) +CSR7_GPT equ 1 SHL 11 ; general purpose timer enable (set with CSR7<15> & CSR5<11> ) +CSR7_FBE equ 1 SHL 13 ; Fatal bus error enable (set with CSR7<15> & CSR5<13> ) +CSR7_ERE equ 1 SHL 14 ; Early receive enable (set with CSR7<16> & CSR5<14> ) +CSR7_AI equ 1 SHL 15 ; Abnormal Interrupt Summary Enable (enables CSR5<0,3,7,8,9,10,13>) +CSR7_NI equ 1 SHL 16 ; Normal Interrup Enable (enables CSR5<0,2,6,11,14>) +CSR7_DEFAULT equ CSR7_TI+CSR7_TS+CSR7_RI+CSR7_RS+CSR7_TU+CSR7_TJ+CSR7_UN+\ + CSR7_RU+CSR7_RW+CSR7_FBE+CSR7_AI+CSR7_NI + +;----------- descriptor structure --------------------- +struc DES { + .DES0 DD ? ; bit 31 is 'own' and rest is 'status' + .DES1 DD ? ; control bits + bytes-count buffer 1 + bytes-count buffer 2 + .DES2 DD ? ; pointer to buffer1 + .DES3 DD ? ; pointer to buffer2 or in this case to next descriptor, as we use a chained structure + .realaddr dd ? + .size = 64 +} + +virtual at 0 + DES DES +end virtual + +;common to Rx and Tx +DES0_OWN equ 1 SHL 31 ; if set, the NIC controls the descriptor, otherwise driver 'owns' the descriptors + +;receive +RDES0_ZER equ 1 SHL 0 ; must be 0 if legal length :D +RDES0_CE equ 1 SHL 1 ; CRC error, valid only on last desc (RDES0<8>=1) +RDES0_DB equ 1 SHL 2 ; dribbling bit - not multiple of 8 bits, valid only on last desc (RDES0<8>=1) +RDES0_RE equ 1 SHL 3 ; Report on MII error.. i dont realy know what this means :P +RDES0_RW equ 1 SHL 4 ; received watchdog timer expiration - must set CSR5<9>, valid only on last desc (RDES0<8>=1) +RDES0_FT equ 1 SHL 5 ; frame type: 0->IEEE802.0 (len<1500) 1-> ETHERNET frame (len>1500), valid only on last desc (RDES0<8>=1) +RDES0_CS equ 1 SHL 6 ; Collision seen, valid only on last desc (RDES0<8>=1) +RDES0_TL equ 1 SHL 7 ; Too long(>1518)-NOT AN ERROR, valid only on last desc (RDES0<8>=1) +RDES0_LS equ 1 SHL 8 ; Last descriptor of current frame +RDES0_FS equ 1 SHL 9 ; First descriptor of current frame +RDES0_MF equ 1 SHL 10 ; Multicast frame, valid only on last desc (RDES0<8>=1) +RDES0_RF equ 1 SHL 11 ; Runt frame, valid only on last desc (RDES0<8>=1) and id overflow +RDES0_DT_SERIAL equ 00b SHL 12 ; Data type-Serial recv frame, valid only on last desc (RDES0<8>=1) +RDES0_DT_INTERNAL equ 01b SHL 12 ; Data type-Internal loopback recv frame, valid only on last desc (RDES0<8>=1) +RDES0_DT_EXTERNAL equ 11b SHL 12 ; Data type-External loopback recv frame, valid only on last desc (RDES0<8>=1) +RDES0_DE equ 1 SHL 14 ; Descriptor error - cant own a new desc and frame doesnt fit, valid only on last desc (RDES0<8>=1) +RDES0_ES equ 1 SHL 15 ; Error Summmary - bits 1+6+11+14, valid only on last desc (RDES0<8>=1) +RDES0_FL_SH equ 16 ; Field length shift, valid only on last desc (RDES0<8>=1) +RDES0_FL_MASK equ 11111111111111b ; Field length mask (+CRC), valid only on last desc (RDES0<8>=1) +RDES0_FF equ 1 SHL 30 ; Filtering fail-frame failed address recognition test(must CSR6<30>=1), valid only on last desc (RDES0<8>=1) + +RDES1_RBS1_MASK equ 11111111111b ; firsd buffer size MASK +RDES1_RBS2_SH equ 1 SHL 11 ; second buffer size SHIFT +RDES1_RBS2_MASK equ 11111111111b ; second buffer size MASK +RDES1_RCH equ 1 SHL 24 ; Second address chained - second address (buffer) is next desc address +RDES1_RER equ 1 SHL 25 ; Receive End of Ring - final descriptor, NIC must return to first desc + +;transmition +TDES0_DE equ 1 SHL 0 ; Deffered +TDES0_UF equ 1 SHL 1 ; Underflow error +TDES0_LF equ 1 SHL 2 ; Link fail report (only if CSR6<23>=1) +TDES0_CC_SH equ 3 ; Collision Count shift - no of collision before transmition +TDES0_CC_MASK equ 1111b ; Collision Count mask +TDES0_HF equ 1 SHL 7 ; Heartbeat fail +TDES0_EC equ 1 SHL 8 ; Excessive Collisions - >16 collisions +TDES0_LC equ 1 SHL 9 ; Late collision +TDES0_NC equ 1 SHL 10 ; No carrier +TDES0_LO equ 1 SHL 11 ; Loss of carrier +TDES0_TO equ 1 SHL 14 ; Transmit Jabber Timeout +TDES0_ES equ 1 SHL 15 ; Error summary TDES0<1+8+9+10+11+14>=1 + +TDES1_TBS1_MASK equ 11111111111b ; Buffer 1 size mask +TDES1_TBS2_SH equ 11 ; Buffer 2 size shift +TDES1_TBS2_MASK equ 11111111111b ; Buffer 2 size mask +TDES1_FT0 equ 1 SHL 22 ; Filtering type 0 +TDES1_DPD equ 1 SHL 23 ; Disabled padding for packets <64bytes, no padding +TDES1_TCH equ 1 SHL 24 ; Second address chained - second buffer pointer is to next desc +TDES1_TER equ 1 SHL 25 ; Transmit end of ring - final descriptor +TDES1_AC equ 1 SHL 26 ; Add CRC disable -pretty obvious +TDES1_SET equ 1 SHL 27 ; Setup packet +TDES1_FT1 equ 1 SHL 28 ; Filtering type 1 +TDES1_FS equ 1 SHL 29 ; First segment - buffer is first segment of frame +TDES1_LS equ 1 SHL 30 ; Last segment +TDES1_IC equ 1 SHL 31 ; Interupt on completion (CSR5<0>=1) valid when TDES1<30>=1 + +MAX_ETH_FRAME_SIZE equ 1514 + +RX_DES_COUNT equ 4 ; no of RX descriptors, must be power of 2 +RX_BUFF_SIZE equ 2048 ; size of buffer for each descriptor, must be multiple of 4 and <= 2048 TDES1_TBS1_MASK +TX_DES_COUNT equ 4 ; no of TX descriptors, must be power of 2 +TX_BUFF_SIZE equ 2048 ; size of buffer for each descriptor, used for memory allocation only + +RX_MEM_TOTAL_SIZE equ RX_DES_COUNT*(DES.size+RX_BUFF_SIZE) +TX_MEM_TOTAL_SIZE equ TX_DES_COUNT*(DES.size+TX_BUFF_SIZE) + +;============================================================================= +; serial ROM operations +;============================================================================= +CSR9_SR equ 1 SHL 11 ; SROM Select +CSR9_RD equ 1 SHL 14 ; ROM Read Operation +CSR9_SROM_DO equ 1 SHL 3 ; Data Out for SROM +CSR9_SROM_DI equ 1 SHL 2 ; Data In to SROM +CSR9_SROM_CK equ 1 SHL 1 ; clock for SROM +CSR9_SROM_CS equ 1 SHL 0 ; chip select.. always needed + +; assume dx is CSR9 (SROM port) +macro SROM_Delay { + push eax + in eax, dx + in eax, dx + in eax, dx + in eax, dx + in eax, dx + in eax, dx + in eax, dx + in eax, dx + in eax, dx + in eax, dx + pop eax +} + +macro Bit_Set a_bit { + in eax, dx + or eax, a_bit + out dx , eax +} + +macro Bit_Clear a_bit { + in eax, dx + and eax, NOT (a_bit) + out dx , eax +} + + +section '.flat' code readable align 16 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; proc START ;; +;; ;; +;; (standard driver proc) ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +proc START stdcall, state:dword + + cmp [state], 1 + jne .exit + + .entry: + + DEBUGF 2,"Loading dec21x4x driver\n" + stdcall RegService, my_service, service_proc + ret + + .fail: + .exit: + xor eax, eax + ret + +endp + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; proc SERVICE_PROC ;; +;; ;; +;; (standard driver proc) ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +proc service_proc stdcall, ioctl:dword + + mov edx, [ioctl] + mov eax, [IOCTL.io_code] + +;------------------------------------------------------ + + cmp eax, 0 ;SRV_GETVERSION + jne @F + + cmp [IOCTL.out_size], 4 + jl .fail + mov eax, [IOCTL.output] + mov [eax], dword API_VERSION + + xor eax, eax + ret + +;------------------------------------------------------ + @@: + cmp eax, 1 ;SRV_HOOK + jne .fail + + cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes + jl .fail + + mov eax, [IOCTL.input] + cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given + jne .fail ; other types arent supported for this card yet + +; check if the device is already listed + + mov esi, DEVICE_LIST + mov ecx, [devices] + test ecx, ecx + jz .firstdevice + +; mov eax, [IOCTL.input] ; get the pci bus and device numbers + mov ax , [eax+1] ; + .nextdevice: + mov ebx, [esi] + cmp ax , word [device.pci_bus] ; compare with pci and device num in device list (notice the usage of word instead of byte) + je .find_devicenum ; Device is already loaded, let's find it's device number + add esi, 4 + loop .nextdevice + + +; This device doesnt have its own eth_device structure yet, lets create one + .firstdevice: + cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card + jge .fail + + push edx + stdcall KernelAlloc, dword device.size ; Allocate the buffer for eth_device structure + pop edx + test eax, eax + jz .fail + mov ebx, eax ; ebx is always used as a pointer to the structure (in driver, but also in kernel code) + +; Fill in the direct call addresses into the struct + + mov [device.reset], reset + mov [device.transmit], transmit + mov [device.get_MAC], read_mac + mov [device.set_MAC], write_mac + mov [device.unload], unload + mov [device.name], my_service + +; save the pci bus and device numbers + + mov eax, [IOCTL.input] + mov cl , [eax+1] + mov [device.pci_bus], cl + mov cl , [eax+2] + mov [device.pci_dev], cl + +; Now, it's time to find the base io addres of the PCI device + + find_io [device.pci_bus], [device.pci_dev], [device.io_addr] + +; We've found the io address, find IRQ now + + find_irq [device.pci_bus], [device.pci_dev], [device.irq_line] + + DEBUGF 2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ + [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8 + + allocate_and_clear [device.rx_p_des], RX_DES_COUNT*(DES.size+RX_BUFF_SIZE), .err + allocate_and_clear [device.tx_p_des], TX_DES_COUNT*(DES.size+TX_BUFF_SIZE), .err + +; Ok, the eth_device structure is ready, let's probe the device +; Because initialization fires IRQ, IRQ handler must be aware of this device + mov eax, [devices] ; Add the device structure to our device list + mov [DEVICE_LIST+4*eax], ebx ; (IRQ handler uses this list to find device) + inc [devices] ; + + call probe ; this function will output in eax + test eax, eax + jnz .err2 ; If an error occured, exit + + call EthRegDev + cmp eax, -1 + je .destroy + + ret + +; If the device was already loaded, find the device number and return it in eax + + .find_devicenum: + DEBUGF 2,"Trying to find device number of already registered device\n" + mov ebx, eax + call EthStruc2Dev ; This kernel procedure converts a pointer to device struct in ebx + ; into a device number in edi + mov eax, edi ; Application wants it in eax instead + DEBUGF 2,"Kernel says: %u\n", eax + ret + +; If an error occured, remove all allocated data and exit (returning -1 in eax) + + .destroy: + ; todo: reset device into virgin state + + .err2: + dec [devices] + .err: + DEBUGF 2,"removing device structure\n" + stdcall KernelFree, [device.rx_p_des] + stdcall KernelFree, [device.tx_p_des] + stdcall KernelFree, ebx + + + .fail: + or eax, -1 + ret + +;------------------------------------------------------ +endp + + +;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; +;; ;; +;; Actual Hardware dependent code starts here ;; +;; ;; +;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; + + + +align 4 +unload: + ; TODO: (in this particular order) + ; + ; - Stop the device + ; - Detach int handler + ; - Remove device from local list (RTL8139_LIST) + ; - call unregister function in kernel + ; - Remove all allocated structures and buffers the card used + + or eax,-1 + +ret + + +macro status { + set_io CSR5 + in eax, dx + DEBUGF 1,"CSR5: %x\n", eax +} + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Probe ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +probe: + + DEBUGF 2,"Probing dec21x4x device: " + + make_bus_master [device.pci_bus], [device.pci_dev] + + movzx eax, [device.pci_bus] + movzx ecx, [device.pci_dev] + stdcall PciRead32, eax ,ecx ,0 ; get device/vendor id + + DEBUGF 1,"Vendor id: 0x%x\n", ax + + cmp ax , 0x1011 + jne .notfound + shr eax, 16 + + DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax ; TODO: use another method to detect chip! + + cmp ax , 0x0009 + je .supported_device + + cmp ax , 0x0019 + je .supported_device2 + + .notfound: + DEBUGF 1,"Device not supported!\n" + or eax, -1 + ret + + .supported_device2: + + ; wake up the 21143 + + movzx ecx, [device.pci_bus] + movzx edx, [device.pci_dev] + xor eax, eax + stdcall PciWrite32, ecx, edx, 0x40, eax + + + .supported_device: + call SROM_GetWidth ; TODO: use this value returned in ecx + ; in the read_word routine! + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Reset ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +reset: + + DEBUGF 2,"Resetting dec21x4x\n" + +;----------------------------------------------------------- +; board software reset - if fails, dont do nothing else + + set_io 0 + status + set_io CSR0 + mov eax, CSR0_RESET + out dx , eax + +; wait at least 50 PCI cycles + mov esi, 1000 + call Sleep + +;----------- +; setup CSR0 + + set_io 0 + status + set_io CSR0 + mov eax, CSR0_DEFAULT + out dx , eax + + +; wait at least 50 PCI cycles + mov esi, 1000 + call Sleep + +;----------------------------------- +; Read mac from eeprom to driver ram + + call read_mac_eeprom + +;-------------------------------- +; insert irq handler on given irq + + movzx eax, [device.irq_line] + DEBUGF 1,"Attaching int handler to irq %x\n", eax:1 + stdcall AttachIntHandler, eax, int_handler, dword 0 + test eax, eax + jnz @f + DEBUGF 1,"\nCould not attach int handler!\n" +; or eax, -1 +; ret + @@: + + set_io 0 + status + +;------------------------------------------ +; Setup RX descriptors (use chained method) + + mov eax, [device.rx_p_des] + call GetPgAddr + mov edx, eax + lea esi, [eax + RX_DES_COUNT*(DES.size)] ; jump over RX descriptors + + mov eax, [device.rx_p_des] + add eax, RX_DES_COUNT*(DES.size) ; jump over RX descriptors + + mov edi, [device.rx_p_des] + mov ecx, RX_DES_COUNT + + push edx ;; + .loop_rx_des: + add edx, DES.size + mov [edi+DES.DES0], DES0_OWN ; hardware owns buffer + mov [edi+DES.DES1], 1984+RDES1_RCH ; only size of first buffer, chained buffers + mov [edi+DES.DES2], esi ; hw buffer address + mov [edi+DES.DES3], edx ; pointer to next descriptor + mov [edi+DES.realaddr], eax ; virtual buffer address + + DEBUGF 1,"RX desc %u, buff addr: %x, next desc: %x, real buff addr: %x, real descr addr: %x \n", ecx, esi, edx, eax, edi + + add esi, RX_BUFF_SIZE + add eax, RX_BUFF_SIZE + add edi, DES.size + dec ecx + jnz .loop_rx_des + +; set last descriptor as LAST + sub edi, DES.size + or [edi+DES.DES1], RDES1_RER ; EndOfRing + pop edx ;; + mov [edi+DES.DES3], edx ;; + +;--------------------- +; Setup TX descriptors + + mov eax, [device.tx_p_des] + call GetPgAddr + mov edx, eax + lea esi, [eax + TX_DES_COUNT*(DES.size)] ; jump over TX descriptors + + mov eax, [device.tx_p_des] + add eax, TX_DES_COUNT*(DES.size) ; jump over TX descriptors + + mov edi, [device.tx_p_des] + mov ecx, TX_DES_COUNT + + push edx ;; + .loop_tx_des: + add edx, DES.size + mov [edi+DES.DES0], 0 ; owned by driver + mov [edi+DES.DES1], TDES1_TCH ; chained method + mov [edi+DES.DES2], esi ; pointer to buffer + mov [edi+DES.DES3], edx ; pointer to next descr + mov [edi+DES.realaddr], eax + + DEBUGF 1,"TX desc %u, buff addr: %x, next desc: %x, real buff addr: %x, real descr addr: %x \n", ecx, esi, edx, eax, edi + + add esi, TX_BUFF_SIZE + add eax, TX_BUFF_SIZE + add edi, DES.size + dec ecx + jnz .loop_tx_des + +; set last descriptor as LAST + sub edi, DES.size + or [edi+DES.DES1], TDES1_TER ; EndOfRing + pop edx ;;; + mov [edi+DES.DES3], edx ;;; + +;------------------ +; Reset descriptors + + mov [device.tx_wr_des], 0 + mov [device.tx_rd_des], 0 + mov [device.rx_crt_des], 0 + mov [device.tx_free_des], TX_DES_COUNT + +;-------------------------------------------- +; setup CSR3 & CSR4 (pointers to descriptors) + + set_io 0 + status + set_io CSR3 + mov eax, [device.rx_p_des] + call GetPgAddr + DEBUGF 1,"RX descriptor base address: %x\n", eax + out dx , eax + + set_io CSR4 + mov eax, [device.tx_p_des] + call GetPgAddr + DEBUGF 1,"TX descriptor base address: %x\n", eax + out dx , eax + +;------------------------------------------------------- +; setup interrupt mask register -expect IRQs from now on + + status + DEBUGF 1,"Enabling interrupts\n" + set_io CSR7 + mov eax, CSR7_DEFAULT + out dx , eax + status + +;---------- +; enable RX + + set_io 0 + status + DEBUGF 1,"Enable RX\n" + + set_io CSR6 + Bit_Set CSR6_SR; or CSR6_PR or CSR6_ST + DEBUGF 1,"CSR6: %x\n", eax + + status + + +; wait a bit + mov esi, 3000 + call Sleep + +;---------------------------------------------------- +; send setup packet to notify the board about the MAC + + call Send_Setup_Packet + + set_io 0 + status + + DEBUGF 1,"Reset done\n" + xor eax, eax + + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Send setup packet ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +Send_Setup_Packet: + + DEBUGF 1,"Sending setup packet\n" + +; if no descriptors available, out + mov ecx, 1000 +@@loop_wait_desc: + cmp [device.tx_free_des], 0 + jne @f + + dec ecx + jnz @@loop_wait_desc + + mov eax, -1 + ret + @@: + +; go to current send descriptor + mov edi, [device.tx_p_des] + mov eax, [device.tx_wr_des] + DEBUGF 1,"Got free descriptor: %u (%x)", eax, edi + mov edx, DES.size + mul edx + add edi, eax + DEBUGF 1,"=>%x\n", edi + +; if NOT sending FIRST setup packet, must set current descriptor to 0 size for both buffers, +; and go to next descriptor for real setup packet... ;; TODO: check if 2 descriptors are available + +; cmp [device.tx_packets], 0 +; je .not_first +; +; and [edi+DES.des1], 0 +; mov [edi+DES.des0], DES0_OWN +; +; go to next descriptor +; inc [device.tx_wr_des] +; and [device.tx_wr_des], TX_DES_COUNT-1 +; +; dec free descriptors count +; cmp [device.tx_free_des], 0 +; jz @f +; dec [device.tx_free_des] +; @@: +; +; ; recompute pointer to current descriptor +; mov edi, [device.tx_p_des] +; mov eax, [device.tx_wr_des] +; mov edx, DES.size +; mul edx +; add edi, eax + + .not_first: + + push edi +; copy setup packet to current descriptor + mov edi, [edi+DES.realaddr] +; copy once the address + lea esi, [device.mac] + DEBUGF 1,"copying packet to %x from %x\n", edi, esi + mov ecx, 3 ; mac is 6 bytes thus 3 words + .loop: + DEBUGF 1,"%x ", [esi]:4 + movsw + dec esi + dec esi + movsw + dec ecx + jnz .loop + + DEBUGF 1,"\n" + +; copy 15 times the broadcast address + mov ecx, 3*15 + mov eax, 0xffffffff + rep stosd + + pop edi + +; setup descriptor + DEBUGF 1,"setting up descriptor\n" + mov [edi+DES.DES1], TDES1_IC+TDES1_SET+TDES1_TCH+192 ; size must be EXACTLY 192 bytes + mov [edi+DES.DES0], DES0_OWN + + DEBUGF 1,"TDES0: %x\n", [edi+DES.DES0]:8 + DEBUGF 1,"TDES1: %x\n", [edi+DES.DES1]:8 + DEBUGF 1,"TDES2: %x\n", [edi+DES.DES2]:8 + DEBUGF 1,"TDES3: %x\n", [edi+DES.DES3]:8 + +; go to next descriptor + inc [device.tx_wr_des] + and [device.tx_wr_des], TX_DES_COUNT-1 + +; dec free descriptors count + cmp [device.tx_free_des], 0 + jz @f + dec [device.tx_free_des] + @@: + + wbinvd;;; + +; start tx + set_io 0 + status + set_io CSR6 + in eax, dx + test eax, CSR6_ST ; if NOT started, start now + jnz .already_started + or eax, CSR6_ST + DEBUGF 1,"Starting TX\n" + jmp .do_it + .already_started: + ; if already started, issue a Transmit Poll command + set_io CSR1 + mov eax, 0 + DEBUGF 1,"Issuing transmit poll command\n" + .do_it: + out dx , eax + status + + DEBUGF 1,"Sending setup packet, completed!\n" + + ret + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Transmit ;; +;; ;; +;; In: buffer pointer in [esp+4] ;; +;; size of buffer in [esp+8] ;; +;; pointer to device structure in ebx ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +transmit: + + DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8] + mov eax, [esp+4] + DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ + [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ + [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ + [eax+13]:2,[eax+12]:2 + + cmp dword [esp+8], MAX_ETH_FRAME_SIZE + ja .fail + + cmp [device.tx_free_des], 0 + je .fail + +;-------------------------- +; copy packet to crt buffer + + mov eax, [device.tx_wr_des] + mov edx, DES.size + mul edx + add eax, [device.tx_p_des] + mov edi, [eax+DES.realaddr] ; pointer to buffer + mov esi, [esp+4] + mov ecx, [esp+8] + DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi + rep movsb + +; set packet size + mov ecx, [eax+DES.DES1] + and ecx, TDES1_TER ; preserve 'End of Ring' bit + or ecx, [esp+8] ; set size + or ecx, TDES1_FS or TDES1_LS or TDES1_IC or TDES1_TCH ; first descr, last descr, interrupt on complete, chained modus + mov [eax+DES.DES1], ecx + +; set descriptor info + mov [eax+DES.DES0], DES0_OWN ; say it is now owned by the 21x4x + + DEBUGF 1,"TDES0: %x\n", [eax+DES.DES0]:8 + DEBUGF 1,"TDES1: %x\n", [eax+DES.DES1]:8 + DEBUGF 1,"TDES2: %x\n", [eax+DES.DES2]:8 + DEBUGF 1,"TDES3: %x\n", [eax+DES.DES3]:8 + + +; start tx + set_io 0 + status + set_io CSR6 + in eax, dx + test eax, CSR6_ST ; if NOT started, start now + jnz .already_started + or eax, CSR6_ST + DEBUGF 1,"Starting TX\n" + jmp .do_it + .already_started: + ; if already started, issues a Transmit Poll command + set_io CSR1 + mov eax, -1 + DEBUGF 1,"Sending transmit poll command\n" + .do_it: + out dx , eax + status + + + wbinvd;;;; + +; go to next descriptor + inc [device.tx_wr_des] + and [device.tx_wr_des], TX_DES_COUNT-1 + +; dec free descriptors count + test [device.tx_free_des], -1 + jz .end + dec [device.tx_free_des] + .end: + status + + DEBUGF 1,"transmit ok\n" + xor eax, eax + ret + + .fail: + DEBUGF 1,"transmit failed\n" + or eax, -1 + ret + + + +;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Interrupt handler ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +int_handler: + + DEBUGF 1,"IRQ %x ",eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO + +; find pointer of device wich made IRQ occur + + mov ecx, [devices] + test ecx, ecx + jz .fail + mov esi, DEVICE_LIST + .nextdevice: + mov ebx, dword [esi] + + set_io 0 + set_io CSR5 + in eax, dx + out dx , eax ; send it back to ACK + + and eax, CSR7_DEFAULT ; int mask + test eax, eax + jnz .got_it + + .continue: + add esi, 4 + dec ecx + jnz .nextdevice + + ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver) + + .got_it: + + DEBUGF 1,"CSR7: %x ", eax + +; looks like we've found it! + +; Lets found out why the irq occured then.. + +;---------------------------------- +; TX ok? + + test eax, CSR5_TI + jz .not_tx + push ax esi ecx + + DEBUGF 1,"TX ok!\n" + + ; go to current descriptor + mov edi, [device.tx_p_des] + + mov eax, [device.tx_rd_des] + mov edx, DES.size + mul edx + add edi, eax + + .loop_tx: + + ; done if all desc are free + cmp [device.tx_free_des], TX_DES_COUNT + jz .end_tx + + mov eax, [edi+DES.DES0] + + ; we stop at first desc that is owned be NIC + test eax, DES0_OWN + jnz .end_tx + + ; detect is setup packet + cmp eax, (0ffffffffh - DES0_OWN) ; all other bits are 1 + jne .not_setup_packet + DEBUGF 1,"Setup Packet detected\n" + .not_setup_packet: + + DEBUGF 1,"packet status: %x\n", eax + + ; next descriptor + add edi, DES.size + inc [device.tx_rd_des] + and [device.tx_rd_des], TX_DES_COUNT-1 + + ; inc free desc + inc [device.tx_free_des] + cmp [device.tx_free_des], TX_DES_COUNT + jle @f + mov [device.tx_free_des], TX_DES_COUNT + @@: + + jmp .loop_tx + .end_tx: + + ;------------------------------------------------------ + ; here must be called standard Ethernet Tx Irq Handler + ;------------------------------------------------------ + + pop ecx esi ax + +;---------------------------------- +; RX irq + .not_tx: + test eax, CSR5_RI + jz .not_rx + push ax esi ecx + + DEBUGF 1,"RX ok!\n" + + ;go to current descriptor + mov edi, [device.rx_p_des] + + mov eax, [device.rx_crt_des] + mov edx, DES.size + mul edx + add edi, eax + + .loop_rx_start_of_packet: + mov eax, [edi+DES.DES0] + + test eax, DES0_OWN + jnz .end_rx ; current desc is busy, nothing to do + + test eax, RDES0_FS + jz .end_rx ; current desc is NOT first packet, ERROR! + + test eax, RDES0_LS ; if not last desc of packet, error for now + jz .end_rx + +; .IF ZERO? +; ODS2 <"Net_Interrupt: packet > 1 descriptor, not supported yet :P"> +; jmp @@end_rx +; .ENDIF + + test eax, RDES0_ES + jnz .end_rx + +; .IF !ZERO? +; ODS2 <"Net_Interrupt: RX error"> +; jmp @@end_rx +; .ENDIF + + mov esi, [edi+DES.realaddr] + mov ecx, [edi+DES.DES0] + shr ecx, RDES0_FL_SH + and ecx, RDES0_FL_MASK + sub ecx, 4 ; crc + + DEBUGF 1,"Received packet!, size=%u, addr:%x\n", ecx, esi + + push esi edi ecx + stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into + pop ecx edi esi + test eax, eax + jz .fail + + push edi + push dword .continue_rx + push ecx eax + mov edi, eax + +; update statistics + inc [device.packets_rx] + + add dword [device.bytes_rx], ecx + adc dword [device.bytes_rx + 4], 0 + +; copy packet data + shr cx , 1 + jnc .nb + movsb + .nb: + shr cx , 1 + jnc .nw + movsw + .nw: + rep movsd + + jmp EthReceiver + + .continue_rx: + pop edi + + ; free descriptor + mov [edi+DES.DES0], DES0_OWN + + ; next descriptor + add edi, DES.size + + inc [device.rx_crt_des] + and [device.rx_crt_des], RX_DES_COUNT-1 + + jmp .loop_rx_start_of_packet + + .end_rx: + .fail: + pop ecx esi ax + .not_rx: + + jmp .continue + + + +align 4 +write_mac: ; in: mac pushed onto stack (as 3 words) + + DEBUGF 2,"Writing MAC: " + +; write data into driver cache + mov esi, esp + lea edi, [device.mac] + movsd + movsw + add esp, 6 + +; send setup packet (only if driver is started) + call Send_Setup_Packet + +align 4 +read_mac: + + DEBUGF 1,"Read_mac\n" + + ret + + + +align 4 +read_mac_eeprom: + + DEBUGF 1,"Read_mac_eeprom\n" + + lea edi, [device.mac] + mov esi, 20/2 ; read words, start address is 20 + .loop: + push esi edi + call SROM_Read_Word + pop edi esi + stosw + inc esi + cmp esi, 26/2 + jl .loop + + DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2 + + ret + +align 4 +write_mac_eeprom: + + DEBUGF 1,"Write_mac_eeprom\n" + + ret + + +align 4 +SROM_GetWidth: ; should be 6 or 8 according to some manuals (returns in ecx) + + DEBUGF 1,"SROM_GetWidth\n" + + call SROM_Idle + call SROM_EnterAccessMode + +; set_io 0 +; set_io CSR9 + + ; send 110b + + in eax, dx + or eax, CSR9_SROM_DI + call SROM_out + + in eax, dx + or eax, CSR9_SROM_DI + call SROM_out + + in eax, dx + and eax, not (CSR9_SROM_DI) + call SROM_out + + mov ecx,1 + .loop2: + Bit_Set CSR9_SROM_CK + SROM_Delay + + in eax, dx + and eax, CSR9_SROM_DO + jnz .not_zero + + Bit_Clear CSR9_SROM_CK + SROM_Delay + jmp .end_loop2 + .not_zero: + + Bit_Clear CSR9_SROM_CK + SROM_Delay + + inc ecx + cmp ecx, 12 + jle .loop2 + .end_loop2: + + DEBUGF 1,"Srom width=%u\n", ecx + + call SROM_Idle + call SROM_EnterAccessMode + call SROM_Idle + + ret + + +align 4 +SROM_out: + + out dx, eax + SROM_Delay + Bit_Set CSR9_SROM_CK + SROM_Delay + Bit_Clear CSR9_SROM_CK + SROM_Delay + + ret + + + +align 4 +SROM_EnterAccessMode: + + DEBUGF 1,"SROM_EnterAccessMode\n" + + set_io 0 + set_io CSR9 + mov eax, CSR9_SR + out dx, eax + SROM_Delay + + Bit_Set CSR9_RD + SROM_Delay + + Bit_Clear CSR9_SROM_CK + SROM_Delay + + Bit_Set CSR9_SROM_CS + SROM_Delay + + ret + + + +align 4 +SROM_Idle: + + DEBUGF 1,"SROM_Idle\n" + + call SROM_EnterAccessMode + +; set_io 0 +; set_io CSR9 + + mov ecx, 25 + .loop_clk: + + Bit_Clear CSR9_SROM_CK + SROM_Delay + Bit_Set CSR9_SROM_CK + SROM_Delay + + dec ecx + jnz .loop_clk + + + Bit_Clear CSR9_SROM_CK + SROM_Delay + Bit_Clear CSR9_SROM_CS + SROM_Delay + + xor eax, eax + out dx, eax + + ret + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Read serial EEprom word ;; +;; ;; +;; In: esi = read address ;; +;; OUT: ax = data word ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +align 4 +SROM_Read_Word: + + DEBUGF 1,"SROM_Read_word at: %x result: ", esi + + set_io 0 + set_io CSR9 + +; enter access mode + mov eax, CSR9_SR + CSR9_RD + out dx , eax + or eax, CSR9_SROM_CS + out dx , eax + + ; TODO: change this hard-coded 6-bit stuff to use value from srom_getwidth + +; send read command "110b" + address to read from + and esi, 111111b + or esi, 110b shl 6 + + mov ecx, 1 shl 9 + .loop_cmd: + mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS + test esi, ecx + jz @f + or eax, CSR9_SROM_DI + @@: + out dx , eax + SROM_Delay + or eax, CSR9_SROM_CK + out dx , eax + SROM_Delay + + shr ecx, 1 + jnz .loop_cmd + +; read data from SROM + + xor esi, esi + mov ecx, 17 ;;; TODO: figure out why 17, not 16 + .loop_read: + + mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS + CSR9_SROM_CK + out dx , eax + SROM_Delay + + in eax, dx + and eax, CSR9_SROM_DO + shr eax, 3 + shl esi, 1 + or esi, eax + + mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS + out dx , eax + SROM_Delay + + dec ecx + jnz .loop_read + + mov eax, esi + + DEBUGF 1,"%x\n", ax + + ret + + +; End of code + +align 4 ; Place all initialised data here + +devices dd 0 +version dd (5 shl 16) or (API_VERSION and 0xFFFF) +my_service db 'DEC21X4X',0 ; max 16 chars include zero + +include_debug_strings ; All data wich FDO uses will be included here + +section '.data' data readable writable align 16 ; place all uninitialized data place here + +DEVICE_LIST rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling + + diff --git a/kernel/branches/net/drivers/netdrv.inc b/kernel/branches/net/drivers/netdrv.inc index 3e0980ae99..a8acb7c381 100644 --- a/kernel/branches/net/drivers/netdrv.inc +++ b/kernel/branches/net/drivers/netdrv.inc @@ -15,9 +15,9 @@ PCI_REG_CAPABILITY_ID equ 0x0 ; capapility ID in pm register block PCI_REG_PM_STATUS equ 0x4 ; power management status register PCI_REG_PM_CTRL equ 0x4 ; power management control register - PCI_BIT_PIO equ 0 ; bit0: io space control - PCI_BIT_MMIO equ 1 ; bit1: memory space control - PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master + PCI_BIT_PIO equ 1 ; bit0: io space control + PCI_BIT_MMIO equ 2 ; bit1: memory space control + PCI_BIT_MASTER equ 4 ; bit2: device acts as a PCI master PAGESIZE equ 4096 @@ -66,7 +66,6 @@ macro allocate_and_clear dest, size, err { end if ; Clear the allocated buffer - ;mov edi, eax mov ecx, size/4 ; divide by 4 because of DWORD xor eax, eax rep stosd @@ -77,28 +76,21 @@ macro allocate_and_clear dest, size, err { macro find_io bus, dev, io { - local .check, .inc, .got - xor eax, eax mov esi, PCI_BASE_ADDRESS_0 movzx ecx, bus movzx edx, dev .check: - stdcall PciRead16, ecx ,edx ,esi + stdcall PciRead32, ecx ,edx ,esi - mov io , eax - and eax, PCI_BASE_ADDRESS_IO_MASK - test eax, eax + test eax, PCI_BASE_ADDRESS_IO_MASK jz .inc - mov eax, io - and eax, PCI_BASE_ADDRESS_SPACE_IO - test eax, eax + test eax, PCI_BASE_ADDRESS_SPACE_IO jz .inc - mov eax, io and eax, PCI_BASE_ADDRESS_IO_MASK mov io , eax jmp .got @@ -106,7 +98,7 @@ macro find_io bus, dev, io { .inc: add esi, 4 cmp esi, PCI_BASE_ADDRESS_5 - jbe .check + jle .check .got: @@ -124,6 +116,18 @@ macro find_irq bus, dev, irq { } +macro find_rev bus, dev, rev { + + push eax edx ecx + movzx ecx, bus + movzx edx, dev + stdcall PciRead8, ecx ,edx ,0x8 + mov rev, al + pop ecx edx eax + +} + + macro make_bus_master bus, dev { @@ -131,14 +135,12 @@ macro make_bus_master bus, dev { movzx edx, dev stdcall PciRead32, ecx ,edx, PCI_REG_COMMAND - or al, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) - and al, not (1 shl PCI_BIT_MMIO) + or al, PCI_BIT_MASTER or PCI_BIT_PIO + and al, not PCI_BIT_MMIO stdcall PciWrite32, ecx, edx, PCI_REG_COMMAND, eax } - - struc IOCTL { .handle dd ? .io_code dd ? @@ -197,3 +199,32 @@ macro ETH_DEVICE { .mac dp ? } + + +macro SLIP_DEVICE { +; pointers to procedures + .unload dd ? + .reset dd ? + .transmit dd ? + .set_mode dd ? + .get_mode dd ? +; status + .bytes_tx dq ? + .bytes_rx dq ? + .packets_tx dd ? + .packets_rx dd ? + .mode dd ? + .name dd ? +} + +macro GetRealAddr { + + push eax + call GetPgAddr + and dword [esp], (PAGESIZE - 1) + add eax, dword [esp] + add esp, 4 + +} + +