Subversion Repositories Kolibri OS

Rev

Rev 5074 | Rev 7251 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Broadcom NetXtreme 57xx driver for KolibriOS                   ;;
7
;;                                                                 ;;
8
;;                                                                 ;;
9
;;          GNU GENERAL PUBLIC LICENSE                             ;;
10
;;             Version 2, June 1991                                ;;
11
;;                                                                 ;;
12
;; Broadcom's programmers's manual for the BCM57xx                 ;;
13
;; http://www.broadcom.com/collateral/pg/57XX-PG105-R.pdf          ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
4663 hidnplayr 17
format PE DLL native
18
entry START
3545 hidnplayr 19
 
4663 hidnplayr 20
        CURRENT_API             = 0x0200
21
        COMPATIBLE_API          = 0x0100
22
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 23
 
24
        MAX_DEVICES             = 16
25
 
26
        __DEBUG__               = 1
27
        __DEBUG_LEVEL__         = 2
28
 
4663 hidnplayr 29
section '.flat' readable writable executable
30
 
31
include '../proc32.inc'
4467 hidnplayr 32
include '../struct.inc'
33
include '../macros.inc'
3545 hidnplayr 34
include '../fdo.inc'
5074 hidnplayr 35
include '../netdrv.inc'
3545 hidnplayr 36
 
4663 hidnplayr 37
struct  device          ETH_DEVICE
3545 hidnplayr 38
 
4663 hidnplayr 39
        mmio_addr       dd ?
40
        pci_bus         dd ?
41
        pci_dev         dd ?
42
        irq_line        db ?
3545 hidnplayr 43
 
4663 hidnplayr 44
        cur_tx          dd ?
45
        last_tx         dd ?
3545 hidnplayr 46
 
4663 hidnplayr 47
        rb 0x100 - ($ and 0xff) ; align 256
48
        rx_desc         rd 256/8
3545 hidnplayr 49
 
4663 hidnplayr 50
        rb 0x100 - ($ and 0xff) ; align 256
51
        tx_desc         rd 256/8
3545 hidnplayr 52
 
4663 hidnplayr 53
ends
3545 hidnplayr 54
 
55
 
56
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
57
;;                        ;;
58
;; proc START             ;;
59
;;                        ;;
60
;; (standard driver proc) ;;
61
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62
 
4663 hidnplayr 63
proc START c, reason:dword, cmdline:dword
3545 hidnplayr 64
 
4663 hidnplayr 65
        cmp     [reason], DRV_ENTRY
66
        jne     .fail
3545 hidnplayr 67
 
4663 hidnplayr 68
        DEBUGF  1,"Loading driver\n"
69
        invoke  RegService, my_service, service_proc
3545 hidnplayr 70
        ret
71
 
72
  .fail:
4663 hidnplayr 73
        xor     eax, eax
3545 hidnplayr 74
        ret
75
 
76
endp
77
 
78
 
79
 
80
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
81
;;                        ;;
82
;; proc SERVICE_PROC      ;;
83
;;                        ;;
84
;; (standard driver proc) ;;
85
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
86
 
87
proc service_proc stdcall, ioctl:dword
88
 
89
        mov     edx, [ioctl]
4470 hidnplayr 90
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 91
 
92
;------------------------------------------------------
93
 
94
        cmp     eax, 0 ;SRV_GETVERSION
95
        jne     @F
96
 
4470 hidnplayr 97
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 98
        jb      .fail
4470 hidnplayr 99
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 100
        mov     [eax], dword API_VERSION
101
 
102
        xor     eax, eax
103
        ret
104
 
105
;------------------------------------------------------
106
  @@:
107
        cmp     eax, 1 ;SRV_HOOK
108
        jne     .fail
109
 
4470 hidnplayr 110
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 111
        jb      .fail
112
 
4470 hidnplayr 113
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 114
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
115
        jne     .fail                                   ; other types arent supported for this card yet
116
 
117
; check if the device is already listed
118
 
119
        mov     esi, device_list
120
        mov     ecx, [devices]
121
        test    ecx, ecx
122
        jz      .firstdevice
123
 
4470 hidnplayr 124
;        mov     eax, [edx + IOCTL.input]                      ; get the pci bus and device numbers
3545 hidnplayr 125
        mov     ax, [eax+1]                             ;
126
  .nextdevice:
127
        mov     ebx, [esi]
4663 hidnplayr 128
        cmp     al, byte [ebx + device.pci_bus]
3545 hidnplayr 129
        jne     .next
4663 hidnplayr 130
        cmp     ah, byte [ebx + device.pci_dev]
3545 hidnplayr 131
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
132
  .next:
133
        add     esi, 4
134
        loop    .nextdevice
135
 
136
 
137
; This device doesnt have its own eth_device structure yet, lets create one
138
  .firstdevice:
139
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
140
        jae     .fail
141
 
4663 hidnplayr 142
        allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
3545 hidnplayr 143
 
144
; Fill in the direct call addresses into the struct
145
 
4663 hidnplayr 146
        mov     [ebx + device.reset], reset
147
        mov     [ebx + device.transmit], transmit
148
        mov     [ebx + device.unload], unload
149
        mov     [ebx + device.name], my_service
3545 hidnplayr 150
 
151
; save the pci bus and device numbers
152
 
4470 hidnplayr 153
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 154
        movzx   ecx, byte [eax+1]
4663 hidnplayr 155
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 156
        movzx   ecx, byte [eax+2]
4663 hidnplayr 157
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 158
 
159
; Now, it's time to find the base mmio addres of the PCI device
160
 
4663 hidnplayr 161
        stdcall PCI_find_mmio32, [ebx + device.pci_bus], [ebx + device.pci_dev]
3545 hidnplayr 162
 
163
; Create virtual mapping of the physical memory
164
 
165
        push    1Bh             ; PG_SW+PG_NOCACHE
166
        push    10000h          ; size of the map
167
        push    eax
4663 hidnplayr 168
        invoke  MapIoMem
169
        mov     [ebx + device.mmio_addr], eax
3545 hidnplayr 170
 
171
; We've found the mmio address, find IRQ now
172
 
4663 hidnplayr 173
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
174
        mov     [ebx + device.irq_line], al
3545 hidnplayr 175
 
176
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
4663 hidnplayr 177
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.mmio_addr]:8
3545 hidnplayr 178
 
179
; Ok, the eth_device structure is ready, let's probe the device
180
        call    probe                                                   ; this function will output in eax
181
        test    eax, eax
182
        jnz     .err                                                    ; If an error occured, exit
183
 
184
        mov     eax, [devices]                                          ; Add the device structure to our device list
185
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
186
        inc     [devices]                                               ;
187
 
4663 hidnplayr 188
        mov     [ebx + device.type], NET_TYPE_ETH
189
        invoke  NetRegDev
3545 hidnplayr 190
 
191
        cmp     eax, -1
192
        je      .destroy
193
 
194
        ret
195
 
196
; If the device was already loaded, find the device number and return it in eax
197
 
198
  .find_devicenum:
199
        DEBUGF  1,"Trying to find device number of already registered device\n"
4663 hidnplayr 200
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 201
                                                                        ; into a device number in edi
202
        mov     eax, edi                                                ; Application wants it in eax instead
203
        DEBUGF  1,"Kernel says: %u\n", eax
204
        ret
205
 
206
; If an error occured, remove all allocated data and exit (returning -1 in eax)
207
 
208
  .destroy:
209
        ; todo: reset device into virgin state
210
 
211
  .err:
4663 hidnplayr 212
        invoke  KernelFree, ebx
3545 hidnplayr 213
 
214
  .fail:
215
        or      eax, -1
216
        ret
217
 
218
;------------------------------------------------------
219
endp
220
 
221
 
222
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
223
;;                                                                        ;;
224
;;        Actual Hardware dependent code starts here                      ;;
225
;;                                                                        ;;
226
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
227
 
228
unload:
229
        ; TODO: (in this particular order)
230
        ;
231
        ; - Stop the device
232
        ; - Detach int handler
233
        ; - Remove device from local list (device_list)
234
        ; - call unregister function in kernel
235
        ; - Remove all allocated structures and buffers the card used
236
 
237
        or      eax, -1
238
 
239
ret
240
 
241
 
242
 
243
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
244
;;
4663 hidnplayr 245
;;  probe: enables the device (if it really is BCM57XX)
3545 hidnplayr 246
;;
247
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4663 hidnplayr 248
 
3545 hidnplayr 249
probe:
250
 
251
        DEBUGF  1,"Probe\n"
252
 
4663 hidnplayr 253
; Make the device a bus master
254
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
255
        or      al, PCI_CMD_MASTER
256
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 257
 
4663 hidnplayr 258
 
3545 hidnplayr 259
        ; TODO: validate the device
260
 
261
 
262
 
263
 
264
reset:
265
 
266
        DEBUGF  1,"Reset\n"
267
 
4663 hidnplayr 268
        movzx   eax, [ebx + device.irq_line]
3545 hidnplayr 269
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4663 hidnplayr 270
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 271
        test    eax, eax
272
        jnz     @f
273
        DEBUGF  1,"\nCould not attach int handler!\n"
274
;        or      eax, -1
275
;        ret
276
  @@:
277
 
278
        call    read_mac
279
 
280
; Set the mtu, kernel will be able to send now
4663 hidnplayr 281
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 282
 
283
; Set link state to unknown
4663 hidnplayr 284
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 285
 
286
        ret
287
 
288
 
289
 
290
 
291
align 4
292
read_mac:
293
 
294
        DEBUGF  1,"Read MAC\n"
295
 
4663 hidnplayr 296
        mov     esi, [ebx + device.mmio_addr]
297
        lea     edi, [ebx + device.mac]
3545 hidnplayr 298
        movsd
299
        movsw
300
 
301
  .mac_ok:
302
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
4663 hidnplayr 303
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
3545 hidnplayr 304
 
305
        ret
306
 
307
 
308
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
309
;;                                         ;;
310
;; Transmit                                ;;
311
;;                                         ;;
312
;; In: buffer pointer in [esp+4]           ;;
313
;;     size of buffer in [esp+8]           ;;
314
;;     pointer to device structure in ebx  ;;
315
;;                                         ;;
316
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4663 hidnplayr 317
 
318
proc transmit stdcall bufferptr, buffersize
319
 
320
        pushf
321
        cli
322
 
323
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
324
        mov     eax, [bufferptr]
325
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 326
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
327
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
328
        [eax+13]:2,[eax+12]:2
329
 
4663 hidnplayr 330
        cmp     [buffersize], 1514
3545 hidnplayr 331
        ja      .fail
4663 hidnplayr 332
        cmp     [buffersize], 60
3545 hidnplayr 333
        jb      .fail
334
 
335
 
336
 
337
 
4663 hidnplayr 338
 
3545 hidnplayr 339
; Update stats
4663 hidnplayr 340
        inc     [ebx + device.packets_tx]
341
        mov     eax, [buffersize]
342
        add     dword[ebx + device.bytes_tx], eax
343
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 344
 
4663 hidnplayr 345
        DEBUGF  1,"Transmit OK\n"
346
        popf
4334 hidnplayr 347
        xor     eax, eax
4663 hidnplayr 348
        ret
3545 hidnplayr 349
 
350
  .fail:
4663 hidnplayr 351
        DEBUGF  2,"Transmit failed\n"
352
        invoke  KernelFree, [bufferptr]
353
        popf
4334 hidnplayr 354
        or      eax, -1
4663 hidnplayr 355
        ret
3545 hidnplayr 356
 
4663 hidnplayr 357
endp
3545 hidnplayr 358
 
4663 hidnplayr 359
 
3545 hidnplayr 360
;;;;;;;;;;;;;;;;;;;;;;;
361
;;                   ;;
362
;; Interrupt handler ;;
363
;;                   ;;
364
;;;;;;;;;;;;;;;;;;;;;;;
365
 
366
align 4
367
int_handler:
368
 
369
        push    ebx esi edi
370
 
4663 hidnplayr 371
        DEBUGF  1,"INT\n"
3545 hidnplayr 372
;-------------------------------------------
373
; Find pointer of device wich made IRQ occur
374
 
375
        mov     ecx, [devices]
376
        test    ecx, ecx
377
        jz      .nothing
378
        mov     esi, device_list
379
  .nextdevice:
380
        mov     ebx, [esi]
381
 
4663 hidnplayr 382
;        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 383
;        mov     eax, [edi + REG_ICR]
384
        test    eax, eax
385
        jnz     .got_it
386
  .continue:
387
        add     esi, 4
388
        dec     ecx
389
        jnz     .nextdevice
390
  .nothing:
391
        pop     edi esi ebx
392
        xor     eax, eax
393
 
394
        ret
395
 
396
  .got_it:
397
 
398
        DEBUGF  1,"Device: %x Status: %x ", ebx, eax
399
 
400
        pop     edi esi ebx
401
        xor     eax, eax
402
        inc     eax
403
 
404
        ret
405
 
406
 
407
 
408
 
409
; End of code
410
 
4663 hidnplayr 411
data fixups
412
end data
3545 hidnplayr 413
 
4663 hidnplayr 414
include '../peimport.inc'
415
 
3545 hidnplayr 416
my_service      db 'BCM57XX',0                   ; max 16 chars include zero
417
 
418
include_debug_strings                           ; All data wich FDO uses will be included here
419
 
4663 hidnplayr 420
align 4
421
devices         dd 0
3545 hidnplayr 422
device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
423