Subversion Repositories Kolibri OS

Rev

Rev 1541 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                  ;;
  3. ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.     ;;
  4. ;; Distributed under terms of the GNU General Public License        ;;
  5. ;;                                                                  ;;
  6. ;;  PCnet driver for KolibriOS                                      ;;
  7. ;;                                                                  ;;
  8. ;;  By hidnplayr & clevermouse                                      ;;
  9. ;;                                                                  ;;
  10. ;;  Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar      ;;
  11. ;;                                                                  ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                              ;;
  13. ;;             Version 2, June 1991                                 ;;
  14. ;;                                                                  ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. ; $Revision: 1564 $
  18.  
  19. format MS COFF
  20.  
  21.         API_VERSION             equ 0x01000100
  22.  
  23.         DEBUG                   equ 1
  24.         __DEBUG__               equ 1
  25.         __DEBUG_LEVEL__         equ 1
  26.  
  27.         MAX_DEVICES equ 4
  28.         MAX_ETH_FRAME_SIZE equ 1514
  29.  
  30. include 'proc32.inc'
  31. include 'imports.inc'
  32. include 'fdo.inc'
  33. include 'netdrv.inc'
  34.  
  35.  
  36. public START
  37. public service_proc
  38. public version
  39.  
  40.  
  41. virtual at ebx
  42.  
  43.         device:
  44.  
  45.         ETH_DEVICE
  46.  
  47. ; device specific
  48.  
  49.       .private:
  50.       .mode_            dw ?
  51.       .tlen_rlen        dw ?
  52.       .phys_addr        dp ?
  53.       .reserved         dw ?
  54.       .filter           dq ?
  55.       .rx_ring_phys     dd ?
  56.       .tx_ring_phys     dd ?
  57.  
  58.       .cur_rx           db ?
  59.       .cur_tx           db ?
  60.       .dirty_rx         dd ?
  61.       .dirty_tx         dd ?
  62.       .tx_full          db ?
  63.       .options          dd ?
  64.       .full_duplex      db ?
  65.       .chip_version     dd ?
  66.       .mii              db ?
  67.       .ltint            db ?
  68.       .dxsuflo          db ?
  69.       .fset             db ?
  70.       .fdx              db ?
  71.  
  72.       .rx_buffer        dd ?
  73.       .tx_buffer        dd ?
  74.  
  75.       .io_addr          dd ?
  76.       .irq_line         db ?
  77.       .pci_bus          db ?
  78.       .pci_dev          db ?
  79.  
  80.  
  81.       .access_read_csr          dd ?
  82.       .access_write_csr         dd ?
  83.       .access_read_bcr          dd ?
  84.       .access_write_bcr         dd ?
  85.       .access_read_rap          dd ?
  86.       .access_write_rap         dd ?
  87.       .access_reset             dd ?
  88.  
  89.       device_size       = $ - device
  90.  
  91. end virtual
  92.  
  93. struc buf_head {
  94.         .base           dd ?
  95.         .length         dw ?
  96.         .status         dw ?
  97.         .msg_length     dw ?
  98.         .misc           dw ?
  99.         .reserved       dd ?
  100.  
  101.         .size:
  102. }
  103.  
  104. virtual at 0
  105.  buf_head buf_head
  106. end virtual
  107.  
  108.         PCNET_PORT_AUI                equ 0x00
  109.         PCNET_PORT_10BT               equ 0x01
  110.         PCNET_PORT_GPSI               equ 0x02
  111.         PCNET_PORT_MII                equ 0x03
  112.         PCNET_PORT_PORTSEL            equ 0x03
  113.         PCNET_PORT_ASEL               equ 0x04
  114.         PCNET_PORT_100                equ 0x40
  115.         PCNET_PORT_FD                 equ 0x80
  116.  
  117.         PCNET_DMA_MASK                equ 0xffffffff
  118.  
  119.         PCNET_LOG_TX_BUFFERS          equ 2
  120.         PCNET_LOG_RX_BUFFERS          equ 2
  121.  
  122.         PCNET_TX_RING_SIZE            equ 4
  123.         PCNET_TX_RING_MOD_MASK        equ (PCNET_TX_RING_SIZE-1)
  124.         PCNET_TX_RING_LEN_BITS        equ (PCNET_LOG_TX_BUFFERS shl 12)
  125.  
  126.         PCNET_RX_RING_SIZE            equ 4
  127.         PCNET_RX_RING_MOD_MASK        equ (PCNET_RX_RING_SIZE-1)
  128.         PCNET_RX_RING_LEN_BITS        equ (PCNET_LOG_RX_BUFFERS shl 4)
  129.  
  130.         PCNET_PKT_BUF_SZ              equ 1544
  131.         PCNET_PKT_BUF_SZ_NEG          equ 0xf9f8
  132.  
  133.         PCNET_WIO_RDP                 equ 0x10
  134.         PCNET_WIO_RAP                 equ 0x12
  135.         PCNET_WIO_RESET               equ 0x14
  136.         PCNET_WIO_BDP                 equ 0x16
  137.         PCNET_DWIO_RDP                equ 0x10
  138.         PCNET_DWIO_RAP                equ 0x14
  139.         PCNET_DWIO_RESET              equ 0x18
  140.         PCNET_DWIO_BDP                equ 0x1C
  141.         PCNET_TOTAL_SIZE              equ 0x20
  142.  
  143. ; CSR registers
  144.  
  145.         PCNET_CSR_CSR                 equ 0x00
  146.         PCNET_CSR_IAB0                equ 0x01
  147.         PCNET_CSR_IAB1                equ 0x02
  148.         PCNET_CSR_IMR                 equ 0x03
  149.         PCNET_CSR_TFEAT               equ 0x04
  150.         PCNET_CSR_EXTCTL1             equ 0x05
  151.         PCNET_CSR_DTBLLEN             equ 0x06
  152.         PCNET_CSR_EXTCTL2             equ 0x07
  153.         PCNET_CSR_MAR0                equ 0x08
  154.         PCNET_CSR_MAR1                equ 0x09
  155.         PCNET_CSR_MAR2                equ 0x0A
  156.         PCNET_CSR_MAR3                equ 0x0B
  157.         PCNET_CSR_PAR0                equ 0x0C
  158.         PCNET_CSR_PAR1                equ 0x0D
  159.         PCNET_CSR_PAR2                equ 0x0E
  160.         PCNET_CSR_MODE                equ 0x0F
  161.         PCNET_CSR_RXADDR0             equ 0x18
  162.         PCNET_CSR_RXADDR1             equ 0x19
  163.         PCNET_CSR_TXADDR0             equ 0x1E
  164.         PCNET_CSR_TXADDR1             equ 0x1F
  165.         PCNET_CSR_TXPOLL              equ 0x2F
  166.         PCNET_CSR_RXPOLL              equ 0x31
  167.         PCNET_CSR_RXRINGLEN           equ 0x4C
  168.         PCNET_CSR_TXRINGLEN           equ 0x4E
  169.         PCNET_CSR_DMACTL              equ 0x50
  170.         PCNET_CSR_BUSTIMER            equ 0x52
  171.         PCNET_CSR_MEMERRTIMEO         equ 0x64
  172.         PCNET_CSR_ONNOWMISC           equ 0x74
  173.         PCNET_CSR_ADVFEAT             equ 0x7A
  174.         PCNET_CSR_MACCFG              equ 0x7D
  175.         PCNET_CSR_CHIPID0             equ 0x58
  176.         PCNET_CSR_CHIPID1             equ 0x59
  177.  
  178. ; Control and Status Register (CSR0)
  179.  
  180.         PCNET_CSR_INIT                equ 1 shl 0
  181.         PCNET_CSR_START               equ 1 shl 1
  182.         PCNET_CSR_STOP                equ 1 shl 2
  183.         PCNET_CSR_TX                  equ 1 shl 3
  184.         PCNET_CSR_TXON                equ 1 shl 4
  185.         PCNET_CSR_RXON                equ 1 shl 5
  186.         PCNET_CSR_INTEN               equ 1 shl 6
  187.         PCNET_CSR_INTR                equ 1 shl 7
  188.         PCNET_CSR_IDONE               equ 1 shl 8
  189.         PCNET_CSR_TINT                equ 1 shl 9
  190.         PCNET_CSR_RINT                equ 1 shl 10
  191.         PCNET_CSR_MERR                equ 1 shl 11
  192.         PCNET_CSR_MISS                equ 1 shl 12
  193.         PCNET_CSR_CERR                equ 1 shl 13
  194.  
  195. ; Interrupt masks and deferral control (CSR3)
  196.  
  197.         PCNET_IMR_BSWAP               equ 0x0004
  198.         PCNET_IMR_ENMBA               equ 0x0008  ; enable modified backoff alg
  199.         PCNET_IMR_DXMT2PD             equ 0x0010
  200.         PCNET_IMR_LAPPEN              equ 0x0020  ; lookahead packet processing enb
  201.         PCNET_IMR_DXSUFLO             equ 0x0040  ; disable TX stop on underflow
  202.         PCNET_IMR_IDONE               equ 0x0100
  203.         PCNET_IMR_TINT                equ 0x0200
  204.         PCNET_IMR_RINT                equ 0x0400
  205.         PCNET_IMR_MERR                equ 0x0800
  206.         PCNET_IMR_MISS                equ 0x1000
  207.  
  208.         PCNET_IMR                     equ PCNET_IMR_TINT+PCNET_IMR_RINT+PCNET_IMR_IDONE+PCNET_IMR_MERR+PCNET_IMR_MISS
  209.  
  210. ; Test and features control (CSR4)
  211.  
  212.         PCNET_TFEAT_TXSTRTMASK        equ 0x0004
  213.         PCNET_TFEAT_TXSTRT            equ 0x0008
  214.         PCNET_TFEAT_RXCCOFLOWM        equ 0x0010  ; Rx collision counter oflow
  215.         PCNET_TFEAT_RXCCOFLOW         equ 0x0020
  216.         PCNET_TFEAT_UINT              equ 0x0040
  217.         PCNET_TFEAT_UINTREQ           equ 0x0080
  218.         PCNET_TFEAT_MISSOFLOWM        equ 0x0100
  219.         PCNET_TFEAT_MISSOFLOW         equ 0x0200
  220.         PCNET_TFEAT_STRIP_FCS         equ 0x0400
  221.         PCNET_TFEAT_PAD_TX            equ 0x0800
  222.         PCNET_TFEAT_TXDPOLL           equ 0x1000
  223.         PCNET_TFEAT_DMAPLUS           equ 0x4000
  224.  
  225. ; Extended control and interrupt 1 (CSR5)
  226.  
  227.         PCNET_EXTCTL1_SPND            equ 0x0001  ; suspend
  228.         PCNET_EXTCTL1_MPMODE          equ 0x0002  ; magic packet mode
  229.         PCNET_EXTCTL1_MPENB           equ 0x0004  ; magic packet enable
  230.         PCNET_EXTCTL1_MPINTEN         equ 0x0008  ; magic packet interrupt enable
  231.         PCNET_EXTCTL1_MPINT           equ 0x0010  ; magic packet interrupt
  232.         PCNET_EXTCTL1_MPPLBA          equ 0x0020  ; magic packet phys. logical bcast
  233.         PCNET_EXTCTL1_EXDEFEN         equ 0x0040  ; excessive deferral interrupt enb.
  234.         PCNET_EXTCTL1_EXDEF           equ 0x0080  ; excessive deferral interrupt
  235.         PCNET_EXTCTL1_SINTEN          equ 0x0400  ; system interrupt enable
  236.         PCNET_EXTCTL1_SINT            equ 0x0800  ; system interrupt
  237.         PCNET_EXTCTL1_LTINTEN         equ 0x4000  ; last TX interrupt enb
  238.         PCNET_EXTCTL1_TXOKINTD        equ 0x8000  ; TX OK interrupt disable
  239.  
  240. ; RX/TX descriptor len (CSR6)
  241.  
  242.         PCNET_DTBLLEN_RLEN            equ 0x0F00
  243.         PCNET_DTBLLEN_TLEN            equ 0xF000
  244.  
  245. ; Extended control and interrupt 2 (CSR7)
  246.  
  247.         PCNET_EXTCTL2_MIIPDTINTE      equ 0x0001
  248.         PCNET_EXTCTL2_MIIPDTINT       equ 0x0002
  249.         PCNET_EXTCTL2_MCCIINTE        equ 0x0004
  250.         PCNET_EXTCTL2_MCCIINT         equ 0x0008
  251.         PCNET_EXTCTL2_MCCINTE         equ 0x0010
  252.         PCNET_EXTCTL2_MCCINT          equ 0x0020
  253.         PCNET_EXTCTL2_MAPINTE         equ 0x0040
  254.         PCNET_EXTCTL2_MAPINT          equ 0x0080
  255.         PCNET_EXTCTL2_MREINTE         equ 0x0100
  256.         PCNET_EXTCTL2_MREINT          equ 0x0200
  257.         PCNET_EXTCTL2_STINTE          equ 0x0400
  258.         PCNET_EXTCTL2_STINT           equ 0x0800
  259.         PCNET_EXTCTL2_RXDPOLL         equ 0x1000
  260.         PCNET_EXTCTL2_RDMD            equ 0x2000
  261.         PCNET_EXTCTL2_RXFRTG          equ 0x4000
  262.         PCNET_EXTCTL2_FASTSPNDE       equ 0x8000
  263.  
  264. ; Mode (CSR15)
  265.  
  266.         PCNET_MODE_RXD                equ 0x0001  ; RX disable
  267.         PCNET_MODE_TXD                equ 0x0002  ; TX disable
  268.         PCNET_MODE_LOOP               equ 0x0004  ; loopback enable
  269.         PCNET_MODE_TXCRCD             equ 0x0008
  270.         PCNET_MODE_FORCECOLL          equ 0x0010
  271.         PCNET_MODE_RETRYD             equ 0x0020
  272.         PCNET_MODE_INTLOOP            equ 0x0040
  273.         PCNET_MODE_PORTSEL            equ 0x0180
  274.         PCNET_MODE_RXVPAD             equ 0x2000
  275.         PCNET_MODE_RXNOBROAD          equ 0x4000
  276.         PCNET_MODE_PROMISC            equ 0x8000
  277.  
  278. ; BCR (Bus Control Registers)
  279.  
  280.         PCNET_BCR_MMRA                equ 0x00    ; Master Mode Read Active
  281.         PCNET_BCR_MMW                 equ 0x01    ; Master Mode Write Active
  282.         PCNET_BCR_MISCCFG             equ 0x02
  283.         PCNET_BCR_LED0                equ 0x04
  284.         PCNET_BCR_LED1                equ 0x05
  285.         PCNET_BCR_LED2                equ 0x06
  286.         PCNET_BCR_LED3                equ 0x07
  287.         PCNET_BCR_DUPLEX              equ 0x09
  288.         PCNET_BCR_BUSCTL              equ 0x12
  289.         PCNET_BCR_EECTL               equ 0x13
  290.         PCNET_BCR_SSTYLE              equ 0x14
  291.         PCNET_BCR_PCILAT              equ 0x16
  292.         PCNET_BCR_PCISUBVENID         equ 0x17
  293.         PCNET_BCR_PCISUBSYSID         equ 0x18
  294.         PCNET_BCR_SRAMSIZE            equ 0x19
  295.         PCNET_BCR_SRAMBOUND           equ 0x1A
  296.         PCNET_BCR_SRAMCTL             equ 0x1B
  297.         PCNET_BCR_MIICTL              equ 0x20
  298.         PCNET_BCR_MIIADDR             equ 0x21
  299.         PCNET_BCR_MIIDATA             equ 0x22
  300.         PCNET_BCR_PCIVENID            equ 0x23
  301.         PCNET_BCR_PCIPCAP             equ 0x24
  302.         PCNET_BCR_DATA0               equ 0x25
  303.         PCNET_BCR_DATA1               equ 0x26
  304.         PCNET_BCR_DATA2               equ 0x27
  305.         PCNET_BCR_DATA3               equ 0x28
  306.         PCNET_BCR_DATA4               equ 0x29
  307.         PCNET_BCR_DATA5               equ 0x2A
  308.         PCNET_BCR_DATA6               equ 0x2B
  309.         PCNET_BCR_DATA7               equ 0x2C
  310.         PCNET_BCR_ONNOWPAT0           equ 0x2D
  311.         PCNET_BCR_ONNOWPAT1           equ 0x2E
  312.         PCNET_BCR_ONNOWPAT2           equ 0x2F
  313.         PCNET_BCR_PHYSEL              equ 0x31
  314.  
  315. ; RX status register
  316.  
  317.         PCNET_RXSTAT_BPE              equ 0x0080  ; bus parity error
  318.         PCNET_RXSTAT_ENP              equ 0x0100  ; end of packet
  319.         PCNET_RXSTAT_STP              equ 0x0200  ; start of packet
  320.         PCNET_RXSTAT_BUFF             equ 0x0400  ; buffer error
  321.         PCNET_RXSTAT_CRC              equ 0x0800  ; CRC error
  322.         PCNET_RXSTAT_OFLOW            equ 0x1000  ; rx overrun
  323.         PCNET_RXSTAT_FRAM             equ 0x2000  ; framing error
  324.         PCNET_RXSTAT_ERR              equ 0x4000  ; error summary
  325.         PCNET_RXSTAT_OWN              equ 0x8000
  326.  
  327. ; TX status register
  328.  
  329.         PCNET_TXSTAT_TRC              equ 0x0000000F      ; transmit retries
  330.         PCNET_TXSTAT_RTRY             equ 0x04000000      ; retry
  331.         PCNET_TXSTAT_LCAR             equ 0x08000000      ; lost carrier
  332.         PCNET_TXSTAT_LCOL             equ 0x10000000      ; late collision
  333.         PCNET_TXSTAT_EXDEF            equ 0x20000000      ; excessive deferrals
  334.         PCNET_TXSTAT_UFLOW            equ 0x40000000      ; transmit underrun
  335.         PCNET_TXSTAT_BUFF             equ 0x80000000      ; buffer error
  336.  
  337.         PCNET_TXCTL_OWN               equ 0x80000000
  338.         PCNET_TXCTL_ERR               equ 0x40000000      ; error summary
  339.         PCNET_TXCTL_ADD_FCS           equ 0x20000000      ; add FCS to pkt
  340.         PCNET_TXCTL_MORE_LTINT        equ 0x10000000
  341.         PCNET_TXCTL_ONE               equ 0x08000000
  342.         PCNET_TXCTL_DEF               equ 0x04000000
  343.         PCNET_TXCTL_STP               equ 0x02000000
  344.         PCNET_TXCTL_ENP               equ 0x01000000
  345.         PCNET_TXCTL_BPE               equ 0x00800000
  346.         PCNET_TXCTL_MBO               equ 0x0000F000
  347.         PCNET_TXCTL_BUFSZ             equ 0x00000FFF
  348.  
  349.  
  350.  
  351.  
  352. section '.flat' code readable align 16
  353.  
  354. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  355. ;;                        ;;
  356. ;; proc START             ;;
  357. ;;                        ;;
  358. ;; (standard driver proc) ;;
  359. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  360.  
  361. proc START stdcall, state:dword
  362.  
  363.         cmp [state], 1
  364.         jne .exit
  365.  
  366.   .entry:
  367.  
  368.         DEBUGF 1,"Loading PCnet driver\n"
  369.         stdcall RegService, my_service, service_proc
  370.         ret
  371.  
  372.   .fail:
  373.   .exit:
  374.         xor eax, eax
  375.         ret
  376.  
  377. endp
  378.  
  379.  
  380. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  381. ;;                        ;;
  382. ;; proc SERVICE_PROC      ;;
  383. ;;                        ;;
  384. ;; (standard driver proc) ;;
  385. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  386.  
  387. align 4
  388. proc service_proc stdcall, ioctl:dword
  389.  
  390.         mov     edx, [ioctl]
  391.         mov     eax, [IOCTL.io_code]
  392.  
  393. ;------------------------------------------------------
  394.  
  395.         cmp     eax, 0 ;SRV_GETVERSION
  396.         jne     @F
  397.  
  398.         cmp     [IOCTL.out_size], 4
  399.         jl      .fail
  400.         mov     eax, [IOCTL.output]
  401.         mov     [eax], dword API_VERSION
  402.  
  403.         xor     eax, eax
  404.         ret
  405.  
  406. ;------------------------------------------------------
  407.   @@:
  408.         cmp     eax, 1 ;SRV_HOOK
  409.         jne     .fail
  410.  
  411.         cmp     [IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  412.         jl      .fail
  413.  
  414.         mov     eax, [IOCTL.input]
  415.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  416.         jne     .fail                                   ; other types arent supported for this card yet
  417.  
  418. ; check if the device is already listed
  419.  
  420.         mov     ecx, [devices]
  421.         test    ecx, ecx
  422.         jz      .firstdevice
  423.  
  424.         mov     esi, device_list
  425. ;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
  426.         mov     ax , [eax+1]                            ;
  427.   .nextdevice:
  428.         mov     ebx, [esi]
  429.         cmp     ax , word [device.pci_bus]              ; compare with pci and device num in device list (notice the usage of word instead of byte)
  430.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  431.         add     esi, 4
  432.         loop    .nextdevice
  433.  
  434. ; This device doesnt have its own eth_device structure yet, lets create one
  435.  
  436.   .firstdevice:
  437.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  438.         jge     .fail
  439.  
  440.         allocate_and_clear ebx, device_size, .fail
  441.  
  442. ; Fill in the direct call addresses into the struct
  443.  
  444.         mov     [device.reset], reset
  445.         mov     [device.transmit], transmit
  446.         mov     [device.get_MAC], read_mac
  447.         mov     [device.set_MAC], write_mac
  448.         mov     [device.unload], unload
  449.         mov     [device.name], my_service
  450.  
  451. ; save the pci bus and device numbers
  452.  
  453.         mov     eax, [IOCTL.input]
  454.         mov     cl , [eax+1]
  455.         mov     [device.pci_bus], cl
  456.         mov     cl , [eax+2]
  457.         mov     [device.pci_dev], cl
  458.  
  459. ; Now, it's time to find the base io addres of the PCI device
  460.  
  461.         find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
  462.  
  463. ; We've found the io address, find IRQ now
  464.  
  465.         find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
  466.  
  467.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  468.         [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
  469.  
  470.         allocate_and_clear [device.tx_buffer], PCNET_RX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
  471.         allocate_and_clear [device.rx_buffer], PCNET_TX_RING_SIZE * (PCNET_PKT_BUF_SZ + buf_head.size), .err
  472.  
  473. ; Ok, the eth_device structure is ready, let's probe the device
  474. ; Because initialization fires IRQ, IRQ handler must be aware of this device
  475.         mov     eax, [devices]                                        ; Add the device structure to our device list
  476.         mov     [device_list+4*eax], ebx                                 ; (IRQ handler uses this list to find device)
  477.         inc     [devices]                                             ;
  478.  
  479.         call    probe                                                   ; this function will output in eax
  480.         test    eax, eax
  481.         jnz     .destroy                                                        ; If an error occured, exit
  482.  
  483.         mov     [device.type], NET_TYPE_ETH
  484.         call    NetRegDev
  485.         cmp     eax, -1
  486.         je      .destroy
  487.  
  488.         ret
  489.  
  490. ; If the device was already loaded, find the device number and return it in eax
  491.  
  492.   .find_devicenum:
  493.         DEBUGF  1,"Trying to find device number of already registered device\n"
  494.         mov     ebx, eax
  495.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  496.                                                                         ; into a device number in edi
  497.         mov     eax, edi                                                ; Application wants it in eax instead
  498.         DEBUGF  1,"Kernel says: %u\n", eax
  499.         ret
  500.  
  501. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  502.  
  503.   .destroy:
  504.         ; todo: reset device into virgin state
  505.  
  506.         dec     [devices]
  507.   .err:
  508.         DEBUGF  1,"Error, removing all data !\n"
  509.         stdcall KernelFree, [device.rx_buffer]
  510.         stdcall KernelFree, [device.tx_buffer]
  511.         stdcall KernelFree, ebx
  512.  
  513.   .fail:
  514.         or      eax, -1
  515.         ret
  516.  
  517. ;------------------------------------------------------
  518. endp
  519.  
  520.  
  521. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  522. ;;                                                                        ;;
  523. ;;        Actual Hardware dependent code starts here                      ;;
  524. ;;                                                                        ;;
  525. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  526.  
  527. align 4
  528. unload:
  529.         ; TODO: (in this particular order)
  530.         ;
  531.         ; - Stop the device
  532.         ; - Detach int handler
  533.         ; - Remove device from local list (RTL8139_LIST)
  534.         ; - call unregister function in kernel
  535.         ; - Remove all allocated structures and buffers the card used
  536.  
  537.         or      eax,-1
  538.  
  539. ret
  540.  
  541.  
  542. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  543. ;;
  544. ;;  probe: enables the device (if it really is a PCnet device)
  545. ;;
  546. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  547.  
  548. align 4
  549. probe:
  550.         mov     edx, [device.io_addr]
  551.  
  552.         call    wio_reset
  553.  
  554.         xor     ecx, ecx
  555.         call    wio_read_csr
  556.         cmp     eax, 4
  557.         jne     .try_dwio
  558.  
  559.         ; Try Word I/O
  560.         mov     ax , 88
  561.         add     edx, PCNET_WIO_RAP
  562.         out     dx , ax
  563.         nop
  564.         nop
  565.         in      ax , dx
  566.         sub     edx, PCNET_WIO_RAP
  567.         cmp     ax , 88
  568.         jne     .try_dwio
  569.  
  570.         call    switch_to_wio
  571.  
  572.         jmp     .L1
  573.  
  574.   .try_dwio:
  575.         call    dwio_reset
  576.  
  577.         xor     ecx, ecx
  578.         call    dwio_read_csr
  579.         cmp     eax, 4
  580.         jne     .no_dev
  581.  
  582.         ; Try Dword I/O
  583.         add     edx, PCNET_DWIO_RAP
  584.         mov     eax, 88
  585.         out     dx , eax
  586.         nop
  587.         nop
  588.         in      eax, dx
  589.         sub     edx, PCNET_DWIO_RAP
  590.         and     eax, 0xffff
  591.         cmp     eax, 88
  592.         jne     .no_dev
  593.  
  594.         call    switch_to_dwio
  595.  
  596.         jmp     .L1
  597.  
  598.   .no_dev:
  599.         DEBUGF 1,"PCnet device not found!\n"
  600.         mov     eax, 1
  601.         ret
  602.   .L1:
  603.  
  604.         mov     ecx, PCNET_CSR_CHIPID0
  605.         call    [device.access_read_csr]
  606.         mov     esi, eax
  607.  
  608.         mov     ecx, PCNET_CSR_CHIPID1
  609.         call    [device.access_read_csr]
  610.         shl     eax, 16
  611.         or      eax, esi
  612.  
  613.         mov     ecx, eax
  614.         and     ecx, 0xfff
  615.         cmp     ecx, 3
  616.         jne     .no_dev
  617.  
  618.         shr     eax, 12
  619.         and     eax, 0xffff
  620.         mov     [device.chip_version], eax
  621.  
  622.         DEBUGF 1,"chip version ok\n"
  623.         mov     [device.fdx], 0
  624.         mov     [device.mii], 0
  625.         mov     [device.fset], 0
  626.         mov     [device.dxsuflo], 0
  627.         mov     [device.ltint], 0
  628.  
  629.         cmp     eax, 0x2420
  630.         je      .L2
  631.         cmp     eax, 0x2430
  632.         je      .L2
  633.  
  634.         mov     [device.fdx], 1
  635.  
  636.         cmp     eax, 0x2621
  637.         je      .L4
  638.         cmp     eax, 0x2623
  639.         je      .L5
  640.         cmp     eax, 0x2624
  641.         je      .L6
  642.         cmp     eax, 0x2625
  643.         je      .L7
  644.         cmp     eax, 0x2626
  645.         je      .L8
  646.         cmp     eax, 0x2627
  647.         je      .L9
  648.  
  649.         DEBUGF 1,"Invalid chip rev\n"
  650.         jmp     .no_dev
  651.   .L2:
  652.         mov     [device.name], device_l2
  653.         jmp     .L10
  654.   .L4:
  655.         mov     [device.name], device_l4
  656. ;        mov     [device.fdx], 1
  657.         jmp     .L10
  658.   .L5:
  659.         mov     [device.name], device_l5
  660. ;        mov     [device.fdx], 1
  661.         mov     [device.mii], 1
  662.         mov     [device.fset], 1
  663.         mov     [device.ltint], 1
  664.         jmp     .L10
  665.   .L6:
  666.         mov     [device.name], device_l6
  667. ;        mov     [device.fdx], 1
  668.         mov     [device.mii], 1
  669.         mov     [device.fset], 1
  670.         jmp     .L10
  671.   .L7:
  672.         mov     [device.name], device_l7
  673. ;        mov     [device.fdx], 1
  674.         mov     [device.mii], 1
  675.         jmp     .L10
  676.   .L8:
  677.         mov     [device.name], device_l8
  678. ;        mov     [device.fdx], 1
  679.         mov     ecx, PCNET_CSR_RXPOLL
  680.         call    dword [device.access_read_bcr]
  681.         call    dword [device.access_write_bcr]
  682.         jmp     .L10
  683.   .L9:
  684.         mov     [device.name], device_l9
  685. ;        mov     [device.fdx], 1
  686.         mov     [device.mii], 1
  687.   .L10:
  688.         DEBUGF 1,"device name: %s\n",[device.name]
  689.  
  690.         cmp     [device.fset], 1
  691.         jne     .L11
  692.         mov     ecx, PCNET_BCR_BUSCTL
  693.         call    [device.access_read_bcr]
  694.         or      eax, 0x800
  695.         call    [device.access_write_bcr]
  696.  
  697.         mov     ecx, PCNET_CSR_DMACTL
  698.         call    [device.access_read_csr]
  699. ;        and     eax, 0xc00
  700. ;        or      eax, 0xc00
  701.         mov     eax, 0xc00
  702.         call    [device.access_write_csr]
  703.  
  704.         mov     [device.dxsuflo],1
  705.         mov     [device.ltint],1
  706.   .L11:
  707.  
  708.         make_bus_master [device.pci_bus], [device.pci_dev]
  709.  
  710.         mov     eax, PCNET_PORT_ASEL
  711.         mov     [device.options], eax
  712.         mov     [device.mode_], word 0x0003
  713.         mov     [device.tlen_rlen], word (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
  714.  
  715.         mov     dword [device.filter], 0
  716.         mov     dword [device.filter+4], 0
  717.  
  718.         mov     eax, PCNET_IMR
  719.         mov     ecx, PCNET_CSR_IMR                      ; Write interrupt mask
  720.         call    [device.access_write_csr]
  721.  
  722. align 4
  723. reset:
  724.  
  725. ; attach int handler
  726.  
  727.         movzx   eax, [device.irq_line]
  728.         DEBUGF  1,"Attaching int handler to irq %x\n",eax:1
  729.         stdcall AttachIntHandler, eax, int_handler, dword 0
  730.         test    eax, eax
  731.         jnz     @f
  732.         DEBUGF  1,"\nCould not attach int handler!\n"
  733. ;        or      eax, -1
  734. ;        ret
  735.   @@:
  736.  
  737.         mov     edx, [device.io_addr]
  738.         call    [device.access_reset]
  739.  
  740.         ; Switch pcnet32 to 32bit mode
  741.         mov     ecx, PCNET_BCR_SSTYLE
  742.         mov     eax, 2
  743.         call    [device.access_write_bcr]
  744.  
  745.         ; set/reset autoselect bit
  746.         mov     ecx, PCNET_BCR_MISCCFG
  747.         call    [device.access_read_bcr]
  748.         and     eax,not 2
  749.         test    [device.options], PCNET_PORT_ASEL
  750.         jz      .L1
  751.         or      eax, 2
  752.   .L1:
  753.         call    [device.access_write_bcr]
  754.  
  755.  
  756.         ; Handle full duplex setting
  757.         cmp     byte [device.full_duplex], 0
  758.         je      .L2
  759.         mov     ecx, PCNET_BCR_DUPLEX
  760.         call    [device.access_read_bcr]
  761.         and     eax, not 3
  762.         test    [device.options], PCNET_PORT_FD
  763.         jz      .L3
  764.         or      eax, 1
  765.         cmp     [device.options], PCNET_PORT_FD or PCNET_PORT_AUI
  766.         jne     .L4
  767.         or      eax, 2
  768.         jmp     .L4
  769.   .L3:
  770.         test    [device.options], PCNET_PORT_ASEL
  771.         jz      .L4
  772.         cmp     [device.chip_version], 0x2627
  773.         jne     .L4
  774.         or      eax, 3
  775.   .L4:
  776.         mov     ecx, PCNET_BCR_DUPLEX
  777.         call    [device.access_write_bcr]
  778.   .L2:
  779.  
  780.  
  781.         ; set/reset GPSI bit in test register
  782.         mov     ecx, 124
  783.         call    [device.access_read_csr]
  784.         mov     ecx, [device.options]
  785.         and     ecx, PCNET_PORT_PORTSEL
  786.         cmp     ecx, PCNET_PORT_GPSI
  787.         jne     .L5
  788.         or      eax, 0x10
  789.   .L5:
  790.         call    [device.access_write_csr]
  791.         cmp     [device.mii], 0
  792.         je      .L6
  793.         test    [device.options], PCNET_PORT_ASEL
  794.         jnz     .L6
  795.         mov     ecx, PCNET_BCR_MIICTL
  796.         call    [device.access_read_bcr]
  797.         and     eax,not 0x38
  798.         test    [device.options], PCNET_PORT_FD
  799.         jz      .L7
  800.         or      eax, 0x10
  801.   .L7:
  802.         test    [device.options], PCNET_PORT_100
  803.         jz      .L8
  804.         or      eax, 0x08
  805.   .L8:
  806.         call    [device.access_write_bcr]
  807.         jmp     .L9
  808. .L6:
  809.         test    [device.options], PCNET_PORT_ASEL
  810.         jz      .L9
  811.         mov     ecx, PCNET_BCR_MIICTL
  812.         DEBUGF 1,"ASEL, enable auto-negotiation\n"
  813.         call    [device.access_read_bcr]
  814.         and     eax, not 0x98
  815.         or      eax, 0x20
  816.         call    [device.access_write_bcr]
  817. .L9:
  818.         cmp     [device.ltint],0
  819.         je      .L10
  820.         mov     ecx,5
  821.         call    [device.access_read_csr]
  822.         or      eax,(1 shl 14)
  823.         call    [device.access_write_csr]
  824. .L10:
  825.         mov     eax,[device.options]
  826.         and     eax,PCNET_PORT_PORTSEL
  827.         shl     eax,7
  828.         mov     [device.mode_],ax
  829.         mov     dword [device.filter], -1
  830.         mov     dword [device.filter+4], -1
  831.  
  832.         call    read_mac
  833.  
  834.         lea     esi, [device.mac]
  835.         lea     edi, [device.phys_addr]
  836.         movsd
  837.         movsw
  838.  
  839.         call    init_ring
  840.  
  841.         lea     eax, [device.private]
  842.         GetRealAddr
  843.  
  844.         push    eax
  845.         and     eax, 0xffff
  846.         mov     ecx, 1
  847.         call    [device.access_write_csr]
  848.         pop     eax
  849.         shr     eax,16
  850.         mov     ecx,2
  851.         call    [device.access_write_csr]
  852.  
  853.         mov     ecx,4
  854.         mov     eax,0x0915
  855.         call    [device.access_write_csr]
  856.  
  857.         mov     ecx,0
  858.         mov     eax,1
  859.         call    [device.access_write_csr]
  860.  
  861.         mov     [device.tx_full],0
  862.         mov     [device.cur_rx],0
  863.         mov     [device.cur_tx],0
  864.         mov     [device.dirty_rx],0
  865.         mov     [device.dirty_tx],0
  866.  
  867.         mov     ecx,100
  868. .L11:
  869.         push    ecx
  870.         xor     ecx,ecx
  871.         call    [device.access_read_csr]
  872.         pop     ecx
  873.         test    ax,0x100
  874.         jnz     .L12
  875.         loop    .L11
  876. .L12:
  877.  
  878.         DEBUGF 1,"hardware reset\n"
  879.         xor     ecx, ecx
  880.         mov     eax, 0x0002
  881.         call    [device.access_write_csr]
  882.  
  883.         xor     ecx, ecx
  884.         call    [device.access_read_csr]
  885.  
  886.         xor     ecx, ecx
  887.         mov     eax, PCNET_CSR_INTEN or PCNET_CSR_START
  888.         call    [device.access_write_csr]
  889.  
  890. ; Set the mtu, kernel will be able to send now
  891.         mov     [device.mtu], 1514
  892.  
  893.         DEBUGF 1,"PCNET reset complete\n"
  894.         xor     eax, eax
  895.         ret
  896.  
  897.  
  898. align 4
  899. init_ring:
  900.  
  901.         mov     ecx, PCNET_RX_RING_SIZE
  902.         mov     edi, [device.rx_buffer]
  903.         mov     eax, edi
  904.         GetRealAddr
  905.         mov     [device.rx_ring_phys], eax
  906.         add     eax, PCNET_RX_RING_SIZE * buf_head.size
  907.   .rx_init:
  908.         mov     [edi + buf_head.base], eax
  909.         mov     [edi + buf_head.length], PCNET_PKT_BUF_SZ_NEG
  910.         mov     [edi + buf_head.status], 0x8000
  911.         and     dword [edi + buf_head.msg_length], 0
  912.         and     dword [edi + buf_head.reserved], 0
  913.         add     eax, PCNET_PKT_BUF_SZ
  914.         add     edi, buf_head.size
  915.         loop    .rx_init
  916.  
  917.         mov     ecx, PCNET_TX_RING_SIZE
  918.         mov     edi, [device.tx_buffer]
  919.         mov     eax, edi
  920.         GetRealAddr
  921.         mov     [device.tx_ring_phys], eax
  922.         add     eax, PCNET_TX_RING_SIZE * buf_head.size
  923.   .tx_init:
  924.         mov     [edi + buf_head.base], eax
  925.         and     dword [edi + buf_head.length], 0
  926.         and     dword [edi + buf_head.msg_length], 0
  927.         and     dword [edi + buf_head.reserved], 0
  928.         add     eax, PCNET_PKT_BUF_SZ
  929.         add     edi, buf_head.size
  930.         loop    .tx_init
  931.  
  932.         mov     [device.tlen_rlen], (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
  933.  
  934.         ret
  935.  
  936.  
  937.  
  938.  
  939. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  940. ;;                                         ;;
  941. ;; Transmit                                ;;
  942. ;;                                         ;;
  943. ;; In: buffer pointer in [esp+4]           ;;
  944. ;;     size of buffer in [esp+8]           ;;
  945. ;;     pointer to device structure in ebx  ;;
  946. ;;                                         ;;
  947. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  948.  
  949. align 4
  950. transmit:
  951.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
  952.         mov     eax, [esp+4]
  953.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  954.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  955.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  956.         [eax+13]:2,[eax+12]:2
  957.  
  958.         cmp     dword [esp+8], 1514
  959.         jg      .finish                         ; packet is too long
  960.         cmp     dword [esp+8], 60
  961.         jl      .finish                         ; packet is too short
  962.  
  963. ; check descriptor
  964.         movzx   eax, [device.cur_tx]
  965.         imul    edi, eax, PCNET_PKT_BUF_SZ
  966.         shl     eax, 4
  967.         add     eax, [device.tx_buffer]
  968.         add     edi, [device.tx_buffer]
  969.         add     edi, PCNET_TX_RING_SIZE * buf_head.size
  970.  
  971.         test    byte [eax + buf_head.status + 1], 80h
  972.         jnz     .nospace
  973. ; descriptor is free, copy data
  974.         mov     esi, [esp+4]
  975.         mov     ecx, [esp+8]
  976.         mov     edx, ecx
  977.         shr     ecx, 2
  978.         and     edx, 3
  979.         rep     movsd
  980.         mov     ecx, edx
  981.         rep     movsb
  982. ; set length
  983.         mov     ecx, [esp+8]
  984.         neg     ecx
  985.         mov     [eax + buf_head.length], cx
  986. ; put to transfer queue
  987.         mov     [eax + buf_head.status], 0x8300
  988.  
  989. ; trigger an immediate send
  990.         xor     ecx, ecx         ; CSR0
  991.         call    [device.access_read_csr]
  992.         or      eax, PCNET_CSR_TX
  993.         call    [device.access_write_csr]
  994.  
  995. ; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
  996.         inc     [device.cur_tx]
  997.         and     [device.cur_tx], 3
  998.         DEBUGF  2," - Packet Sent! "
  999.  
  1000. .finish:
  1001.         DEBUGF  2," - Done!\n"
  1002.         stdcall KernelFree, [esp+4]
  1003.         ret     8
  1004.  
  1005. .nospace:
  1006.         DEBUGF  1, 'ERROR: no free transmit descriptors\n'
  1007. ; todo: maybe somehow notify the kernel about the error?
  1008.         stdcall KernelFree, [esp+4]
  1009.         ret     8
  1010.  
  1011.  
  1012.  
  1013. ;;;;;;;;;;;;;;;;;;;;;;;
  1014. ;;                   ;;
  1015. ;; Interrupt handler ;;
  1016. ;;                   ;;
  1017. ;;;;;;;;;;;;;;;;;;;;;;;
  1018.  
  1019. align 4
  1020. int_handler:
  1021.  
  1022. ;       DEBUGF  1,"IRQ %x ",eax:2                   ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
  1023.  
  1024. ; find pointer of device wich made IRQ occur
  1025.  
  1026.         mov     esi, device_list
  1027.         mov     ecx, [devices]
  1028.         test    ecx, ecx
  1029.         jz      .abort
  1030.   .nextdevice:
  1031.         mov     ebx, dword [esi]
  1032.         mov     edx, [device.io_addr]     ; get IRQ reason
  1033.  
  1034.         push    ecx
  1035.         xor     ecx, ecx ; CSR0
  1036.         call    [device.access_read_csr]
  1037.         pop     ecx
  1038.  
  1039.         test    al , al
  1040.         js      .got_it
  1041.  
  1042.         add     esi, 4
  1043.         loop    .nextdevice
  1044.  
  1045.         ret                                         ; If no device was found, abort (The irq was probably for a device, not registered to this driver
  1046.  
  1047.   .got_it:
  1048. ;-------------------------------------------------------
  1049. ; Possible reasons:
  1050. ; initialization done - ignore
  1051. ; transmit done - ignore
  1052. ; packet received - handle
  1053. ; Clear ALL IRQ reasons.
  1054. ; N.B. One who wants to handle more than one reason must be ready
  1055. ; to two or more reasons in one IRQ.
  1056.         xor     ecx, ecx
  1057.         call    [device.access_write_csr]
  1058. ; Received packet ok?
  1059.  
  1060.         test    ax, PCNET_CSR_RINT
  1061.         jz      @f
  1062.  
  1063. .receiver_test_loop:
  1064.         movzx   eax, [device.cur_rx]
  1065. ;        and     eax, PCNET_RX_RING_MOD_MASK
  1066.         mov     edi, eax
  1067.  
  1068.         imul    esi, eax, PCNET_PKT_BUF_SZ      ;
  1069.         add     esi, [device.rx_buffer]         ; esi now points to rx buffer
  1070.         add     esi, PCNET_RX_RING_SIZE * buf_head.size
  1071.  
  1072.         shl     edi, 4                          ; desc * 16 (16 is size of one ring entry)
  1073.         add     edi, [device.rx_buffer]     ; edi now points to current rx ring entry
  1074.  
  1075.         mov     cx , [edi + buf_head.status]
  1076.  
  1077.         test    cx , PCNET_RXSTAT_OWN           ; If this bit is set, the controller OWN's the packet, if not, we do
  1078.         jnz     .abort
  1079.  
  1080.         test    cx , PCNET_RXSTAT_ENP
  1081.         jz      .abort
  1082.  
  1083.         test    cx , PCNET_RXSTAT_STP
  1084.         jz      .abort
  1085.  
  1086.         movzx   ecx, [edi + buf_head.msg_length]        ; get packet length in ecx
  1087.         sub     ecx, 4                          ;
  1088.  
  1089.         push    ecx
  1090.         stdcall KernelAlloc, ecx                ; Allocate a buffer to put packet into
  1091.         pop     ecx
  1092.         test    eax, eax                        ; Test if we allocated succesfully
  1093.         jz      .abort                          ;
  1094.  
  1095.         push    .receiver_test_loop             ;
  1096.         push    ecx                             ; for eth_receiver
  1097.         push    eax                             ;
  1098.  
  1099.         xchg    edi, eax
  1100.         push    ecx
  1101.         shr     ecx, 2
  1102.         cld
  1103.         rep     movsd
  1104.         pop     ecx
  1105.         and     ecx, 3
  1106.         rep     movsb
  1107.  
  1108. ;       mov     word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG
  1109.         mov     word [eax + buf_head.status], PCNET_RXSTAT_OWN      ; Set OWN bit back to 1 (controller may write to tx-buffer again now)
  1110.  
  1111.         inc     [device.cur_rx]           ; update descriptor
  1112.         and     [device.cur_rx], 3        ;
  1113.  
  1114.         jmp     EthReceiver                     ; Send the copied packet to kernel
  1115.  
  1116.   .abort:
  1117.  
  1118.   @@:
  1119.  
  1120.         ret
  1121.  
  1122.  
  1123.  
  1124.  
  1125. ;;;;;;;;;;;;;;;;;;;;;;;
  1126. ;;                   ;;
  1127. ;; Write MAC address ;;
  1128. ;;                   ;;
  1129. ;;;;;;;;;;;;;;;;;;;;;;;
  1130.  
  1131. align 4
  1132. write_mac:      ; in: mac pushed onto stack (as 3 words)
  1133.  
  1134.         DEBUGF  1,"Writing MAC: %x-%x-%x-%x-%x-%x",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
  1135.  
  1136.         mov     edx, [device.io_addr]
  1137.         add     dx, 2
  1138.         xor     eax, eax
  1139.  
  1140.         mov     ecx, PCNET_CSR_PAR0
  1141.        @@:
  1142.         pop     ax
  1143.         call    [device.access_write_csr]
  1144.         DEBUGF  1,"."
  1145.         inc     ecx
  1146.         cmp     ecx, PCNET_CSR_PAR2
  1147.         jl      @r
  1148.  
  1149.         DEBUGF  1,"\n"
  1150.  
  1151. ; Notice this procedure does not ret, but continues to read_mac instead.
  1152.  
  1153. ;;;;;;;;;;;;;;;;;;;;;;
  1154. ;;                  ;;
  1155. ;; Read MAC address ;;
  1156. ;;                  ;;
  1157. ;;;;;;;;;;;;;;;;;;;;;;
  1158. align 4
  1159. read_mac:
  1160.         DEBUGF  1,"Reading MAC"
  1161.  
  1162.         mov     edx, [device.io_addr]
  1163.         add     dx, 6
  1164.        @@:
  1165.         dec     dx
  1166.         dec     dx
  1167.         in      ax, dx
  1168.         push    ax
  1169.         DEBUGF  1,"."
  1170.         cmp     edx, [device.io_addr]
  1171.         jg      @r
  1172.  
  1173.         DEBUGF  1," %x-%x-%x-%x-%x-%x\n",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
  1174.  
  1175.         lea     edi, [device.mac]
  1176.         pop     ax
  1177.         stosw
  1178.         pop     ax
  1179.         stosw
  1180.         pop     ax
  1181.         stosw
  1182.  
  1183.         ret
  1184.  
  1185. align 4
  1186. switch_to_wio:
  1187.  
  1188.         DEBUGF  1,"Switching to 16-bit mode\n"
  1189.  
  1190.         mov     [device.access_read_csr], wio_read_csr
  1191.         mov     [device.access_write_csr], wio_write_csr
  1192.         mov     [device.access_read_bcr], wio_read_bcr
  1193.         mov     [device.access_write_bcr], wio_write_bcr
  1194.         mov     [device.access_read_rap], wio_read_rap
  1195.         mov     [device.access_write_rap], wio_write_rap
  1196.         mov     [device.access_reset], wio_reset
  1197.  
  1198.         ret
  1199.  
  1200. align 4
  1201. switch_to_dwio:
  1202.  
  1203.         DEBUGF  1,"Switching to 32-bit mode\n"
  1204.  
  1205.         mov     [device.access_read_csr], dwio_read_csr
  1206.         mov     [device.access_write_csr], dwio_write_csr
  1207.         mov     [device.access_read_bcr], dwio_read_bcr
  1208.         mov     [device.access_write_bcr], dwio_write_bcr
  1209.         mov     [device.access_read_rap], dwio_read_rap
  1210.         mov     [device.access_write_rap], dwio_write_rap
  1211.         mov     [device.access_reset], dwio_reset
  1212.  
  1213.         ret
  1214.  
  1215.  
  1216. ; ecx - index
  1217. ; return:
  1218. ; eax - data
  1219. align 4
  1220. wio_read_csr:
  1221.  
  1222.         add     edx, PCNET_WIO_RAP
  1223.         mov     ax , cx
  1224.         out     dx , ax
  1225.         add     edx, PCNET_WIO_RDP - PCNET_WIO_RAP
  1226.         in      ax , dx
  1227.         and     eax, 0xffff
  1228.         sub     edx, PCNET_WIO_RDP
  1229.  
  1230.         ret
  1231.  
  1232.  
  1233. ; eax - data
  1234. ; ecx - index
  1235. align 4
  1236. wio_write_csr:
  1237.  
  1238.         add     edx, PCNET_WIO_RAP
  1239.         xchg    eax, ecx
  1240.         out     dx , ax
  1241.         xchg    eax, ecx
  1242.         add     edx, PCNET_WIO_RDP - PCNET_WIO_RAP
  1243.         out     dx , ax
  1244.         sub     edx, PCNET_WIO_RDP
  1245.  
  1246.         ret
  1247.  
  1248.  
  1249. ; ecx - index
  1250. ; return:
  1251. ; eax - data
  1252. align 4
  1253. wio_read_bcr:
  1254.  
  1255.         add     edx, PCNET_WIO_RAP
  1256.         mov     ax , cx
  1257.         out     dx , ax
  1258.         add     edx, PCNET_WIO_BDP - PCNET_WIO_RAP
  1259.         in      ax , dx
  1260.         and     eax, 0xffff
  1261.         sub     edx, PCNET_WIO_BDP
  1262.  
  1263.         ret
  1264.  
  1265.  
  1266. ; eax - data
  1267. ; ecx - index
  1268. align 4
  1269. wio_write_bcr:
  1270.  
  1271.         add     edx, PCNET_WIO_RAP
  1272.         xchg    eax, ecx
  1273.         out     dx , ax
  1274.         xchg    eax, ecx
  1275.         add     edx, PCNET_WIO_BDP - PCNET_WIO_RAP
  1276.         out     dx , ax
  1277.         sub     edx, PCNET_WIO_BDP
  1278.  
  1279.         ret
  1280.  
  1281. align 4
  1282. wio_read_rap:
  1283.  
  1284.         add     edx, PCNET_WIO_RAP
  1285.         in      ax , dx
  1286.         and     eax, 0xffff
  1287.         sub     edx, PCNET_WIO_RAP
  1288.  
  1289.         ret
  1290.  
  1291. ; eax - val
  1292. align 4
  1293. wio_write_rap:
  1294.  
  1295.         add     edx, PCNET_WIO_RAP
  1296.         out     dx , ax
  1297.         sub     edx, PCNET_WIO_RAP
  1298.  
  1299.         ret
  1300.  
  1301. align 4
  1302. wio_reset:
  1303.  
  1304.         push    eax
  1305.         add     edx, PCNET_WIO_RESET
  1306.         in      ax , dx
  1307.         pop     eax
  1308.         sub     edx, PCNET_WIO_RESET
  1309.  
  1310.         ret
  1311.  
  1312.  
  1313.  
  1314. ; ecx - index
  1315. ; return:
  1316. ; eax - data
  1317. align 4
  1318. dwio_read_csr:
  1319.  
  1320.         add     edx, PCNET_DWIO_RAP
  1321.         mov     eax, ecx
  1322.         out     dx , eax
  1323.         add     edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
  1324.         in      eax, dx
  1325.         and     eax, 0xffff
  1326.         sub     edx, PCNET_DWIO_RDP
  1327.  
  1328.         ret
  1329.  
  1330.  
  1331. ; ecx - index
  1332. ; eax - data
  1333. align 4
  1334. dwio_write_csr:
  1335.  
  1336.         add     edx, PCNET_DWIO_RAP
  1337.         xchg    eax, ecx
  1338.         out     dx , eax
  1339.         add     edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
  1340.         xchg    eax, ecx
  1341.         out     dx , eax
  1342.         sub     edx, PCNET_DWIO_RDP
  1343.  
  1344.         ret
  1345.  
  1346. ; ecx - index
  1347. ; return:
  1348. ; eax - data
  1349. align 4
  1350. dwio_read_bcr:
  1351.  
  1352.         add     edx, PCNET_DWIO_RAP
  1353.         mov     eax, ecx
  1354.         out     dx , eax
  1355.         add     edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
  1356.         in      eax, dx
  1357.         and     eax, 0xffff
  1358.         sub     edx, PCNET_DWIO_BDP
  1359.  
  1360.         ret
  1361.  
  1362.  
  1363. ; ecx - index
  1364. ; eax - data
  1365. align 4
  1366. dwio_write_bcr:
  1367.  
  1368.         add     edx, PCNET_DWIO_RAP
  1369.         xchg    eax, ecx
  1370.         out     dx , eax
  1371.         add     edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
  1372.         xchg    eax, ecx
  1373.         out     dx , eax
  1374.         sub     edx, PCNET_DWIO_BDP
  1375.  
  1376.         ret
  1377.  
  1378. align 4
  1379. dwio_read_rap:
  1380.  
  1381.         add     edx, PCNET_DWIO_RAP
  1382.         in      eax, dx
  1383.         and     eax, 0xffff
  1384.         sub     edx, PCNET_DWIO_RAP
  1385.  
  1386.         ret
  1387.  
  1388.  
  1389. ; eax - val
  1390. align 4
  1391. dwio_write_rap:
  1392.  
  1393.         add     edx, PCNET_DWIO_RAP
  1394.         out     dx , eax
  1395.         sub     edx, PCNET_DWIO_RAP
  1396.  
  1397.         ret
  1398.  
  1399. align 4
  1400. dwio_reset:
  1401.  
  1402.         push    eax
  1403.         add     edx, PCNET_DWIO_RESET
  1404.         in      eax, dx
  1405.         pop     eax
  1406.         sub     edx, PCNET_DWIO_RESET
  1407.  
  1408.         ret
  1409.  
  1410.  
  1411.  
  1412. ; End of code
  1413.  
  1414. align 4                                       ; Place all initialised data here
  1415.  
  1416. devices     dd 0
  1417. version       dd (5 shl 16) or (API_VERSION and 0xFFFF)
  1418. my_service    db 'PCnet',0                    ; max 16 chars include zero
  1419.  
  1420. device_l2     db "PCnet/PCI 79C970",0
  1421. device_l4     db "PCnet/PCI II 79C970A",0
  1422. device_l5     db "PCnet/FAST 79C971",0
  1423. device_l6     db "PCnet/FAST+ 79C972",0
  1424. device_l7     db "PCnet/FAST III 79C973",0
  1425. device_l8     db "PCnet/Home 79C978",0
  1426. device_l9     db "PCnet/FAST III 79C975",0
  1427.  
  1428. options_mapping:
  1429. dd PCNET_PORT_ASEL                                      ;  0 Auto-select
  1430. dd PCNET_PORT_AUI                                       ;  1 BNC/AUI
  1431. dd PCNET_PORT_AUI                                       ;  2 AUI/BNC
  1432. dd PCNET_PORT_ASEL                                      ;  3 not supported
  1433. dd PCNET_PORT_10BT or PCNET_PORT_FD                     ;  4 10baseT-FD
  1434. dd PCNET_PORT_ASEL                                      ;  5 not supported
  1435. dd PCNET_PORT_ASEL                                      ;  6 not supported
  1436. dd PCNET_PORT_ASEL                                      ;  7 not supported
  1437. dd PCNET_PORT_ASEL                                      ;  8 not supported
  1438. dd PCNET_PORT_MII                                       ;  9 MII 10baseT
  1439. dd PCNET_PORT_MII or PCNET_PORT_FD                      ; 10 MII 10baseT-FD
  1440. dd PCNET_PORT_MII                                       ; 11 MII (autosel)
  1441. dd PCNET_PORT_10BT                                      ; 12 10BaseT
  1442. dd PCNET_PORT_MII or PCNET_PORT_100                     ; 13 MII 100BaseTx
  1443. dd PCNET_PORT_MII or PCNET_PORT_100 or PCNET_PORT_FD    ; 14 MII 100BaseTx-FD
  1444. dd PCNET_PORT_ASEL                                      ; 15 not supported
  1445.  
  1446. include_debug_strings                                   ; All data wich FDO uses will be included here
  1447.  
  1448. section '.data' data readable writable align 16         ; place all uninitialized data place here
  1449.  
  1450. device_list rd MAX_DEVICES                                 ; This list contains all pointers to device structures the driver is handling
  1451.