/kernel/branches/Kolibri-acpi/bus/usb/ehci.inc |
---|
222,7 → 222,7 |
; ------------------------------ hardware fields ------------------------------ |
FrameList rd 1024 |
; Entry n corresponds to the head of the frame list to be executed in |
; the frames n,n+1024,n+2048,n+3096,... |
; the frames n,n+1024,n+2048,n+3072,... |
; The first bit of each entry is Terminate bit, 1 = the frame is empty. |
; Bits 1-2 are Type field, one of EHCI_TYPE_* constants. |
; Bits 3-4 must be zero. |
/kernel/branches/Kolibri-acpi/bus/usb/uhci.inc |
---|
126,7 → 126,7 |
; ------------------------------ hardware fields ------------------------------ |
FrameList rd 1024 |
; Entry n corresponds to the head of the frame list to be executed in |
; the frames n,n+1024,n+2048,n+3096,... |
; the frames n,n+1024,n+2048,n+3072,... |
; The first bit of each entry is Terminate bit, 1 = the frame is empty. |
; The second bit of each entry is QH/TD select bit, 1 = the entry points to |
; QH, 0 = to TD. |
/kernel/branches/Kolibri-acpi/data32.inc |
---|
375,9 → 375,6 |
PUTPIXEL rd 1 |
GETPIXEL rd 1 |
BgrDrawMode rd 1 |
BgrDataWidth rd 1 |
BgrDataHeight rd 1 |
REDRAW_BACKGROUND rb 4 |
MOUSE_PICTURE rd 1 |
480,6 → 477,12 |
mem_BACKGROUND rd 1 |
static_background_data rd 1 |
BgrDrawMode rd 1 |
BgrDataWidth rd 1 |
BgrDataHeight rd 1 |
skin_data rd 1 |
cache_ide0: |
cache_ide0_pointer rd 1 |
cache_ide0_size rd 1 ; not use |
553,7 → 556,6 |
FLOPPY_BUFF: rb 16*1024 |
BUTTON_INFO: rb 16*1024 |
BgrAuxTable: rb 32*1024 |
skin_data: rb 32*1024 |
;IDE_DMA: rb 32*1024 |
/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt |
---|
2394,8 → 2394,17 |
</UL> |
====================================================================== |
=========================== Function 52 ============================== |
====================================================================== |
WARNING: This function is obsolete and is only present in the |
documentation as a guide to understand/port the older network |
applications. For new programs, use function 74 |
====================================================================== |
=== Function 52, subfunction 0 - get network driver configuration. === |
====================================================================== |
Parameters: |
* eax = 52 - function number |
* ebx = 0 - subfunction number |
2558,6 → 2567,14 |
* for other ecx: eax = -1 indicates an error |
====================================================================== |
=========================== Function 53 ============================== |
====================================================================== |
WARNING: This function is obsolete and is only present in the |
documentation as a guide to understand/port the older network |
applications. For new programs, use function 75. |
====================================================================== |
============ Function 53, subfunction 0 - open UDP-socket. =========== |
====================================================================== |
Parameters: |
4581,6 → 4598,201 |
* function does not return value |
====================================================================== |
= Function 74, Subfunction -1, Get number of active network devices. = |
====================================================================== |
Parameters: |
* eax = 74 - function number |
* bl = -1 - subfunction number |
Returned value: |
* eax = number of active network devices |
====================================================================== |
======== Function 74, Subfunction 0, Get network device type. ======== |
====================================================================== |
Parameters: |
* eax = 74 - function number |
* bl = 0 - subfunction number |
* bh = device number |
Returned value: |
* eax = device type |
====================================================================== |
======== Function 74, Subfunction 1, Get network device name. ======== |
====================================================================== |
Parameters: |
* eax = 74 - function number |
* bl = 1 - subfunction number |
* bh = device number |
* ecx = pointer to 64 byte buffer |
Returned value: |
* eax = -1 on error |
* The network device name is written into the buffer, on success |
====================================================================== |
========= Function 74, Subfunction 2, Reset network device. ========== |
====================================================================== |
Parameters: |
* eax = 74 - function number |
* bl = 2 - subfunction number |
* bh = device number |
Returned value: |
* eax = -1 on error |
====================================================================== |
========== Function 74, Subfunction 3, Stop network device. ========== |
====================================================================== |
Parameters: |
* eax = 74 - function number |
* bl = 3 - subfunction number |
* bh = device number |
Returned value: |
* eax = -1 on error |
====================================================================== |
============== Function 75, Subfunction 0, Open socket. ============== |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 0 - subfunction number |
* ecx = domain |
* edx = type |
* esi = protocol |
Returned value: |
* eax = socket number, -1 on error |
====================================================================== |
============= Function 75, Subfunction 1, Close socket. ============== |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 1 - subfunction number |
* ecx = socket number |
Returned value: |
* eax = -1 on error |
====================================================================== |
================== Function 75, Subfunction 2, Bind. ================= |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 2 - subfunction number |
* ecx = socket number |
* edx = pointer to sockaddr structure |
* esi = length of sockaddr structure |
Returned value: |
* eax = -1 on error |
====================================================================== |
================= Function 75, Subfunction 3, Listen. ================ |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 3 - subfunction number |
* ecx = socket number |
* edx = backlog |
Returned value: |
* eax = -1 on error |
====================================================================== |
================ Function 75, Subfunction 4, Connect. ================ |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 4 - subfunction number |
* ecx = socket number |
* edx = pointer to sockaddr structure |
* esi = length of sockaddr structure |
Returned value: |
* eax = -1 on error |
====================================================================== |
================= Function 75, Subfunction 5, Accept. ================ |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 5 - subfunction number |
* ecx = socket number |
* edx = pointer to sockaddr structure |
* esi = length of sockaddr structure |
Returned value: |
* eax = -1 on error |
====================================================================== |
================== Function 75, Subfunction 6, Send. ================= |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 6 - subfunction number |
* ecx = socket number |
* edx = pointer to buffer |
* esi = length of buffer |
Returned value: |
* eax = number of bytes copied, -1 on error |
====================================================================== |
================ Function 75, Subfunction 7, Receive. ================ |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 7 - subfunction number |
* ecx = socket number |
* edx = pointer to buffer |
* esi = length of buffer |
* edi = flags |
Returned value: |
* eax = number of bytes copied, -1 on error |
====================================================================== |
=========== Function 75, Subfunction 8, Set socket options. ========== |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 8 - subfunction number |
* ecx = socket number |
* edx = pointer to optstruct |
Returned value: |
* eax = -1 on error |
Remarks: |
Optstruct: dd level |
dd optionname |
dd optlength |
db options... |
====================================================================== |
=========== Function 75, Subfunction 9, Get socket options. ========== |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 9 - subfunction number |
* ecx = socket number |
* edx = pointer to optstruct |
Returned value: |
* eax = -1 on error |
Remarks: |
Optstruct: dd level |
dd optionname |
dd optlength |
db options... |
====================================================================== |
============ Function 75, Subfunction 10, Get socketpair. =========== |
====================================================================== |
Parameters: |
* eax = 75 - function number |
* bl = 10 - subfunction number |
Returned value: |
* eax = socketnum1, -1 on error |
* ebx = socketnum2 |
Remarks: |
Optstruct: dd level |
dd optionname |
dd optlength |
db options... |
====================================================================== |
=============== Function -1 - terminate thread/process =============== |
====================================================================== |
Parameters: |
/kernel/branches/Kolibri-acpi/docs/usbapi.txt |
---|
4,8 → 4,8 |
print some information, reads and parses configuration descriptor. For every |
interface the kernel looks for class code of this interface and loads the |
corresponding COFF driver. Currently the correspondence is hardcoded into |
the kernel code and looks as follows: 3 = usbhid.obj, 8 = usbstor.obj, |
9 is handled by the kernel itself, other = usbother.obj. |
the kernel code and looks as follows: 3 = usbhid.obj, 7 = usbprint.obj, |
8 = usbstor.obj, 9 is handled by the kernel itself, other = usbother.obj. |
The driver must be standard driver in COFF format, exporting procedure |
named "START" and a variable named "version". Loader calls "START" procedure |
46,7 → 46,7 |
void* interfacedescr |
); |
The parameter 'controlpipe' is a handle of the control pipe for endpoint zero |
The parameter 'pipe0' is a handle of the control pipe for endpoint zero |
of the device. It can be used as the argument of USBControlTransferAsync. |
The parameter 'configdescr' points to USB configuration descriptor |
and all associated data, as returned by GET_DESCRIPTOR request. |
93,7 → 93,20 |
The parameter 'interval' is ignored for control and bulk endpoints. |
For interrupt endpoints, it sets the polling interval in milliseconds. |
The function returns a handle to the pipe or NULL on failure. |
The output handle becomes invalid when a) it is explicitly closed with |
the following function or b) the function DeviceDisconnected provided |
by the driver returns. |
void __stdcall USBClosePipe( |
void* pipe |
); |
Releases all resources associated with the given pipe. The only parameter |
must be a handle returned by USBOpenPipe. |
When a device is disconnected, all associated pipes are closed by the kernel; |
there is no need to ever call this function if all pipes are used continuously |
while a device is connected. |
void* __stdcall USBNormalTransferAsync( |
void* pipe, |
void* buffer, |
104,7 → 117,7 |
); |
void* __stdcall USBControlTransferAsync( |
void* pipe, |
void* config, |
void* setup, |
void* buffer, |
int size, |
void* callback, |
116,12 → 129,12 |
for given pipe. Type and direction of transfer are fixed for bulk and interrupt |
endpoints and are set in USBOpenPipe. The second function inserts a control |
transfer to the transfer queue for given pipe. Direction of a control transfer |
is concluded from 'config' packet, bit 7 of byte 0 is set for IN transfers |
is concluded from 'setup' packet, bit 7 of byte 0 is set for IN transfers |
and cleared for OUT transfers. These function return immediately; when data |
are transferred, the callback function will be called. |
The parameter 'pipe' is a handle returned by USBOpenPipe. |
The parameter 'config' of USBControlTransferAsync points to 8-byte |
The parameter 'setup' of USBControlTransferAsync points to 8-byte |
configuration packet as defined by USB. |
The parameter 'buffer' is a pointer to buffer. For IN transfers, it will be |
filled with the data. For OUT transfers, it should contain data to be |
174,10 → 187,12 |
; possible only for isochronous transfers |
USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer |
; possible only for isochronous transfers |
USB_STATUS_DISCONNECTED = 16 ; device disconnected |
USB_STATUS_CLOSED = 16 ; pipe closed, either explicitly with USBClosePipe |
; or due to device disconnect |
If several transfers are queued for the same pipe, their callback functions |
are called in the same order as they were queued. |
When the device is disconnected, all callback functions are called |
with USB_STATUS_DISCONNECTED. The call to DeviceDisconnected() occurs after |
When a pipe is closed, either explicitly with USBClosePipe, or |
implicitly due to device disconnect, all callback functions are called |
with USB_STATUS_CLOSED. The call to DeviceDisconnected() occurs after |
all callbacks. |
/kernel/branches/Kolibri-acpi/drivers/usbhid.asm |
---|
0,0 → 1,696 |
; standard driver stuff |
format MS COFF |
DEBUG = 1 |
; this is for DEBUGF macro from 'fdo.inc' |
__DEBUG__ = 1 |
__DEBUG_LEVEL__ = 1 |
include 'proc32.inc' |
include 'imports.inc' |
include 'fdo.inc' |
public START |
public version |
; USB constants |
DEVICE_DESCR_TYPE = 1 |
CONFIG_DESCR_TYPE = 2 |
STRING_DESCR_TYPE = 3 |
INTERFACE_DESCR_TYPE = 4 |
ENDPOINT_DESCR_TYPE = 5 |
DEVICE_QUALIFIER_DESCR_TYPE = 6 |
CONTROL_PIPE = 0 |
ISOCHRONOUS_PIPE = 1 |
BULK_PIPE = 2 |
INTERRUPT_PIPE = 3 |
; USB structures |
virtual at 0 |
config_descr: |
.bLength db ? |
.bDescriptorType db ? |
.wTotalLength dw ? |
.bNumInterfaces db ? |
.bConfigurationValue db ? |
.iConfiguration db ? |
.bmAttributes db ? |
.bMaxPower db ? |
.sizeof: |
end virtual |
virtual at 0 |
interface_descr: |
.bLength db ? |
.bDescriptorType db ? |
.bInterfaceNumber db ? |
.bAlternateSetting db ? |
.bNumEndpoints db ? |
.bInterfaceClass db ? |
.bInterfaceSubClass db ? |
.bInterfaceProtocol db ? |
.iInterface db ? |
.sizeof: |
end virtual |
virtual at 0 |
endpoint_descr: |
.bLength db ? |
.bDescriptorType db ? |
.bEndpointAddress db ? |
.bmAttributes db ? |
.wMaxPacketSize dw ? |
.bInterval db ? |
.sizeof: |
end virtual |
; Driver data for all devices |
virtual at 0 |
device_data: |
.type dd ? ; 1 = keyboard, 2 = mouse |
.intpipe dd ? ; interrupt pipe handle |
.packetsize dd ? |
.packet rb 8 ; packet with data from device |
.control rb 8 ; control packet to device |
.sizeof: |
end virtual |
; Driver data for mouse |
virtual at device_data.sizeof |
mouse_data: |
; no additional data |
.sizeof: |
end virtual |
; Driver data for keyboard |
virtual at device_data.sizeof |
keyboard_data: |
.handle dd ? ; keyboard handle from RegKeyboard |
.configpipe dd ? ; config pipe handle |
.prevpacket rb 8 ; previous packet with data from device |
.timer dd ? ; auto-repeat timer handle |
.repeatkey db ? ; auto-repeat key code |
.ledstate db ? ; state of LEDs |
align 4 |
.sizeof: |
end virtual |
section '.flat' code readable align 16 |
; The start procedure. |
START: |
; 1. Test whether the procedure is called with the argument DRV_ENTRY. |
; If not, return 0. |
xor eax, eax ; initialize return value |
cmp dword [esp+4], 1 ; compare the argument |
jnz .nothing |
; 2. Register self as a USB driver. |
; The name is my_driver = 'usbhid'; IOCTL interface is not supported; |
; usb_functions is an offset of a structure with callback functions. |
stdcall RegUSBDriver, my_driver, eax, usb_functions |
; 3. Return the returned value of RegUSBDriver. |
.nothing: |
ret 4 |
; This procedure is called when new HID device is detected. |
; It initializes the device. |
AddDevice: |
; Arguments are addressed through esp. In this point of the function, |
; [esp+4] = a handle of the config pipe, [esp+8] points to config_descr |
; structure, [esp+12] points to interface_descr structure. |
; 1. Check device type. Currently only mice and keyboards with |
; boot protocol are supported. |
; 1a. Get the subclass and the protocol. Since bInterfaceSubClass and |
; bInterfaceProtocol are subsequent in interface_descr, just one |
; memory reference is used for both. |
mov edx, [esp+12] |
push ebx ; save used register to be stdcall |
mov cx, word [edx+interface_descr.bInterfaceSubClass] |
; 1b. For boot protocol, subclass must be 1 and protocol must be either 1 for |
; a keyboard or 2 for a mouse. Check. |
cmp cx, 0x0101 |
jz .keyboard |
cmp cx, 0x0201 |
jz .mouse |
; 1c. If the device is neither a keyboard nor a mouse, print a message and |
; go to 6c. |
DEBUGF 1,'K : unknown HID device\n' |
jmp .nothing |
; 1d. If the device is a keyboard or a mouse, print a message and continue |
; configuring. |
.keyboard: |
DEBUGF 1,'K : USB keyboard detected\n' |
push keyboard_data.sizeof |
jmp .common |
.mouse: |
DEBUGF 1,'K : USB mouse detected\n' |
push mouse_data.sizeof |
.common: |
; 2. Allocate memory for device data. |
pop eax ; get size of device data |
; 2a. Call the kernel, saving and restoring register edx. |
push edx |
call Kmalloc |
pop edx |
; 2b. Check result. If failed, say a message and go to 6c. |
test eax, eax |
jnz @f |
DEBUGF 1,'K : no memory\n' |
jmp .nothing |
@@: |
xchg eax, ebx |
; HID devices use one IN interrupt endpoint for polling the device |
; and an optional OUT interrupt endpoint. We do not use the later, |
; but must locate the first. Look for the IN interrupt endpoint. |
; 3. Get the upper bound of all descriptors' data. |
mov eax, [esp+8+4] ; configuration descriptor |
movzx ecx, [eax+config_descr.wTotalLength] |
add eax, ecx |
; 4. Loop over all descriptors until |
; either end-of-data reached - this is fail |
; or interface descriptor found - this is fail, all further data |
; correspond to that interface |
; or endpoint descriptor found. |
; 4a. Loop start: eax points to the interface descriptor. |
.lookep: |
; 4b. Get next descriptor. |
movzx ecx, byte [edx] ; the first byte of all descriptors is length |
add edx, ecx |
; 4c. Check that at least two bytes are readable. The opposite is an error. |
inc edx |
cmp edx, eax |
jae .errorep |
dec edx |
; 4d. Check that this descriptor is not interface descriptor. The opposite is |
; an error. |
cmp byte [edx+endpoint_descr.bDescriptorType], INTERFACE_DESCR_TYPE |
jz .errorep |
; 4e. Test whether this descriptor is an endpoint descriptor. If not, continue |
; the loop. |
cmp byte [edx+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE |
jnz .lookep |
; 5. Check that the descriptor contains all required data and all data are |
; readable. If so, proceed to 7. |
cmp byte [edx+endpoint_descr.bLength], endpoint_descr.sizeof |
jb .errorep |
sub eax, endpoint_descr.sizeof |
cmp edx, eax |
jbe @f |
; 6. An error occured during processing endpoint descriptor. |
.errorep: |
; 6a. Print a message. |
DEBUGF 1,'K : error: invalid endpoint descriptor\n' |
; 6b. Free memory allocated for device data. |
.free: |
xchg eax, ebx |
call Kfree |
.nothing: |
; 6c. Return an error. |
xor eax, eax |
pop ebx |
ret 12 |
@@: |
; 7. Check that the endpoint is IN interrupt endpoint. If not, go to 6. |
test [edx+endpoint_descr.bEndpointAddress], 80h |
jz .errorep |
mov cl, [edx+endpoint_descr.bmAttributes] |
and cl, 3 |
cmp cl, INTERRUPT_PIPE |
jnz .errorep |
; 8. Open pipe for the endpoint. |
; 8a. Load parameters from the descriptor. |
movzx ecx, [edx+endpoint_descr.bEndpointAddress] |
movzx eax, [edx+endpoint_descr.bInterval] |
movzx edx, [edx+endpoint_descr.wMaxPacketSize] |
; 8b. Call the kernel, saving and restoring edx. |
push edx |
stdcall USBOpenPipe, [esp+4+24], ecx, edx, INTERRUPT_PIPE, eax |
pop edx |
; 8c. Check result. If failed, go to 6b. |
test eax, eax |
jz .free |
; We use 12 bytes for device type, interrupt pipe and interrupt packet size, |
; 8 bytes for a packet and 8 bytes for previous packet, used by a keyboard. |
; 9. Initialize device data. |
mov [ebx+device_data.intpipe], eax |
push 8 |
pop ecx |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
xor eax, eax |
mov [ebx+device_data.packetsize], edx |
mov dword [ebx+device_data.packet], eax |
mov dword [ebx+device_data.packet+4], eax |
mov edx, [esp+12+4] ; interface descriptor |
movzx ecx, [edx+interface_descr.bInterfaceProtocol] |
mov [ebx+device_data.type], ecx |
cmp ecx, 1 |
jnz @f |
mov [ebx+keyboard_data.handle], eax |
mov [ebx+keyboard_data.timer], eax |
mov [ebx+keyboard_data.repeatkey], al |
mov dword [ebx+keyboard_data.prevpacket], eax |
mov dword [ebx+keyboard_data.prevpacket+4], eax |
mov eax, [esp+4+4] |
mov [ebx+keyboard_data.configpipe], eax |
@@: |
; 10. Send the control packet SET_PROTOCOL(Boot Protocol) to the interface. |
lea eax, [ebx+device_data.control] |
mov dword [eax], 21h + (0Bh shl 8) + (0 shl 16) ; class request to interface + SET_PROTOCOL + Boot protocol |
and dword [eax+4], 0 |
mov dl, [edx+interface_descr.bInterfaceNumber] |
mov [eax+4], dl |
; Callback function is mouse_configured for mice and keyboard_configured1 for keyboards. |
mov edx, keyboard_configured1 |
cmp ecx, 1 |
jz @f |
mov edx, mouse_configured |
@@: |
stdcall USBControlTransferAsync, [esp+4+28], eax, 0, 0, edx, ebx, 0 |
; 11. Return with pointer to device data as returned value. |
xchg eax, ebx |
pop ebx |
ret 12 |
; This function is called when SET_PROTOCOL command for keyboard is done, |
; either successful or unsuccessful. |
keyboard_configured1: |
xor edx, edx |
; 1. Check the status of the transfer. |
; If the transfer was failed, go to the common error handler. |
cmp dword [esp+8], edx ; status is zero? |
jnz keyboard_data_ready.error |
; 2. Send the control packet SET_IDLE(infinity). HID auto-repeat is not useful. |
mov eax, [esp+20] |
push edx ; flags for USBControlTransferAsync |
push eax ; userdata for USBControlTransferAsync |
add eax, device_data.control |
mov dword [eax], 21h + (0Ah shl 8) + (0 shl 24) ; class request to interface + SET_IDLE + no autorepeat |
stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \ |
eax, edx, edx, keyboard_configured2; , <userdata>, <flags> |
; 3. Return. |
ret 20 |
; This function is called when SET_IDLE command for keyboard is done, |
; either successful or unsuccessful. |
keyboard_configured2: |
; Check the status of the transfer and go to the corresponding label |
; in the main handler. |
cmp dword [esp+8], 0 |
jnz keyboard_data_ready.error |
mov edx, [esp+20] |
push edx |
stdcall RegKeyboard, usbkbd_functions, edx |
pop edx |
mov [edx+keyboard_data.handle], eax |
jmp keyboard_data_ready.next |
; This function is called when another interrupt packet arrives, |
; processed either successfully or unsuccessfully. |
; It should parse the packet and initiate another transfer with |
; the same callback function. |
keyboard_data_ready: |
; 1. Check the status of the transfer. |
mov eax, [esp+8] |
test eax, eax |
jnz .error |
; Parse the packet, comparing with the previous packet. |
; For boot protocol, USB keyboard packet consists of the first byte |
; with status keys that are currently pressed. The second byte should |
; be ignored, and other 5 bytes denote keys that are currently pressed. |
push esi ebx ; save used registers to be stdcall |
; 2. Process control keys. |
; 2a. Initialize before loop for control keys. edx = mask for control bits |
; that were changed. |
mov ebx, [esp+20+8] |
movzx edx, byte [ebx+device_data.packet] ; get state of control keys |
xor dl, byte [ebx+keyboard_data.prevpacket] ; compare with previous state |
; 2b. If state of control keys has not changed, advance to 3. |
jz .nocontrol |
; 2c. Otherwise, loop over control keys; esi = bit number. |
xor esi, esi |
.controlloop: |
; 2d. Skip bits that have not changed. |
bt edx, esi |
jnc .controlnext |
push edx ; save register which is possibly modified by API |
; The state of the current control key has changed. |
; 2e. For extended control keys, send the prefix 0xE0. |
mov al, [control_keys+esi] |
test al, al |
jns @f |
push eax |
mov ecx, 0xE0 |
call SetKeyboardData |
pop eax |
and al, 0x7F |
@@: |
; 2f. If the current state of the control key is "pressed", send normal |
; scancode. Otherwise, the key is released, so set the high bit in scancode. |
movzx ecx, al |
bt dword [ebx+device_data.packet], esi |
jc @f |
or cl, 0x80 |
@@: |
call SetKeyboardData |
pop edx ; restore register which was possibly modified by API |
.controlnext: |
; 2g. We have 8 control keys. |
inc esi |
cmp esi, 8 |
jb .controlloop |
.nocontrol: |
; 3. Initialize before loop for normal keys. esi = index. |
push 2 |
pop esi |
.normalloop: |
; 4. Process one key which was pressed in the previous packet. |
; 4a. Get the next pressed key from the previous packet. |
movzx eax, byte [ebx+esi+keyboard_data.prevpacket] |
; 4b. Ignore special codes. |
cmp al, 3 |
jbe .normalnext1 |
; 4c. Ignore keys that are still pressed in the current packet. |
lea ecx, [ebx+device_data.packet] |
call haskey |
jz .normalnext1 |
; 4d. Say warning about keys with strange codes. |
cmp eax, normal_keys_number |
jae .badkey1 |
movzx ecx, [normal_keys+eax] |
jecxz .badkey1 |
; 4e. For extended keys, send the prefix 0xE0. |
push ecx ; save keycode |
test cl, cl |
jns @f |
push ecx |
mov ecx, 0xE0 |
call SetKeyboardData |
pop ecx |
@@: |
; 4f. Send the release event. |
or cl, 0x80 |
call SetKeyboardData |
; 4g. If this key is autorepeating, stop the timer. |
pop ecx ; restore keycode |
cmp cl, [ebx+keyboard_data.repeatkey] |
jnz .normalnext1 |
mov eax, [ebx+keyboard_data.timer] |
test eax, eax |
jz .normalnext1 |
stdcall CancelTimerHS, eax |
and [ebx+keyboard_data.timer], 0 |
jmp .normalnext1 |
.badkey1: |
DEBUGF 1,'K : unknown keycode: %x\n',al |
.normalnext1: |
; 5. Process one key which is pressed in the current packet. |
; 5a. Get the next pressed key from the current packet. |
movzx eax, byte [ebx+esi+device_data.packet] |
; 5b. Ignore special codes. |
cmp al, 3 |
jbe .normalnext2 |
; 5c. Ignore keys that were already pressed in the previous packet. |
lea ecx, [ebx+keyboard_data.prevpacket] |
call haskey |
jz .normalnext2 |
; 5d. Say warning about keys with strange codes. |
cmp eax, normal_keys_number |
jae .badkey2 |
movzx ecx, [normal_keys+eax] |
jecxz .badkey2 |
; 5e. For extended keys, send the prefix 0xE0. |
push ecx ; save keycode |
test cl, cl |
jns @f |
push ecx |
mov ecx, 0xE0 |
call SetKeyboardData |
pop ecx |
@@: |
; 5f. Send the press event. |
and cl, not 0x80 |
call SetKeyboardData |
; 5g. Stop the current auto-repeat timer, if present. |
mov eax, [ebx+keyboard_data.timer] |
test eax, eax |
jz @f |
stdcall CancelTimerHS, eax |
@@: |
; 5h. Start the auto-repeat timer. |
pop ecx ; restore keycode |
mov [ebx+keyboard_data.repeatkey], cl |
stdcall TimerHS, 25, 5, autorepeat_timer, ebx |
mov [ebx+keyboard_data.timer], eax |
jmp .normalnext2 |
.badkey2: |
DEBUGF 1,'K : unknown keycode: %x\n',al |
.normalnext2: |
; 6. Advance to next key. |
inc esi |
cmp esi, 8 |
jb .normalloop |
; 7. Save the packet data for future reference. |
mov eax, dword [ebx+device_data.packet] |
mov dword [ebx+keyboard_data.prevpacket], eax |
mov eax, dword [ebx+device_data.packet+4] |
mov dword [ebx+keyboard_data.prevpacket+4], eax |
pop ebx esi ; restore registers to be stdcall |
.next: |
; 8. Initiate transfer on the interrupt pipe. |
mov eax, [esp+20] |
push 1 ; flags for USBNormalTransferAsync |
push eax ; userdata for USBNormalTransferAsync |
add eax, device_data.packet |
stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \ |
eax, dword [eax+device_data.packetsize-device_data.packet], \ |
keyboard_data_ready;, <userdata>, <flags> |
; 9. Return. |
.nothing: |
ret 20 |
.error: |
; An error has occured. |
; 10. If an error is caused by the disconnect, do nothing, it is handled |
; in DeviceDisconnected. Otherwise, say a message. |
cmp eax, 16 |
jz @f |
push esi |
mov esi, errormsgkbd |
call SysMsgBoardStr |
pop esi |
@@: |
ret 20 |
; Auxiliary procedure for keyboard_data_ready. |
haskey: |
push 2 |
pop edx |
@@: |
cmp byte [ecx+edx], al |
jz @f |
inc edx |
cmp edx, 7 |
jbe @b |
@@: |
ret |
; Timer function for auto-repeat. |
autorepeat_timer: |
mov eax, [esp+4] |
movzx ecx, [eax+keyboard_data.repeatkey] |
test cl, cl |
jns @f |
push ecx |
mov ecx, 0xE0 |
call SetKeyboardData |
pop ecx |
and cl, not 0x80 |
@@: |
call SetKeyboardData |
ret 4 |
; This function is called to update LED state on the keyboard. |
SetKeyboardLights: |
mov eax, [esp+4] |
add eax, device_data.control |
mov dword [eax], 21h + (9 shl 8) + (2 shl 24) |
; class request to interface + SET_REPORT + Output zero report |
mov byte [eax+6], 1 |
mov edx, [esp+8] |
shr dl, 1 |
jnc @f |
or dl, 4 |
@@: |
lea ecx, [eax+keyboard_data.ledstate-device_data.control] |
mov [ecx], dl |
stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \ |
eax, ecx, 1, keyboard_data_ready.nothing, 0, 0 |
ret 8 |
; This function is called when it is safe to free keyboard data. |
CloseKeyboard: |
mov eax, [esp+4] |
push ebx |
call Kfree |
pop ebx |
ret 4 |
; This function is called when SET_PROTOCOL command for mouse is done, |
; either successful or unsuccessful. |
mouse_configured: |
; Check the status of the transfer and go to the corresponding label |
; in the main handler. |
cmp dword [esp+8], 0 |
jnz mouse_data_ready.error |
mov eax, [esp+20] |
add eax, device_data.packet |
jmp mouse_data_ready.next |
; This function is called when another interrupt packet arrives, |
; processed either successfully or unsuccessfully. |
; It should parse the packet and initiate another transfer with |
; the same callback function. |
mouse_data_ready: |
; 1. Check the status of the transfer. |
mov eax, [esp+8] |
test eax, eax |
jnz .error |
mov edx, [esp+16] |
; 2. Parse the packet. |
; For boot protocol, USB mouse packet consists of at least 3 bytes. |
; The first byte is state of mouse buttons, the next two bytes are |
; x and y movements. |
; Normal mice do not distinguish between boot protocol and report protocol; |
; in this case, scroll data are also present. Advanced mice, however, |
; support two different protocols, boot protocol is used for compatibility |
; and does not contain extended buttons or scroll data. |
mov eax, [esp+12] ; buffer |
push eax |
xor ecx, ecx |
cmp edx, 4 |
jbe @f |
movsx ecx, byte [eax+4] |
@@: |
push ecx |
xor ecx, ecx |
cmp edx, 3 |
jbe @f |
movsx ecx, byte [eax+3] |
neg ecx |
@@: |
push ecx |
xor ecx, ecx |
cmp edx, 2 |
jbe @f |
movsx ecx, byte [eax+2] |
neg ecx |
@@: |
push ecx |
movsx ecx, byte [eax+1] |
push ecx |
movzx ecx, byte [eax] |
push ecx |
call SetMouseData |
pop eax |
.next: |
; 3. Initiate transfer on the interrupt pipe. |
stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \ |
eax, dword [eax+device_data.packetsize-device_data.packet], mouse_data_ready, eax, 1 |
; 4. Return. |
ret 20 |
.error: |
; An error has occured. |
; 5. If an error is caused by the disconnect, do nothing, it is handled |
; in DeviceDisconnected. Otherwise, say a message. |
cmp eax, 16 |
jz @f |
push esi |
mov esi, errormsgmouse |
call SysMsgBoardStr |
pop esi |
@@: |
ret 20 |
; This function is called when the device is disconnected. |
DeviceDisconnected: |
push ebx ; save used register to be stdcall |
; 1. Say a message. Use different messages for keyboards and mice. |
mov ebx, [esp+4+4] |
push esi |
mov esi, disconnectmsgk |
cmp byte [ebx+device_data.type], 1 |
jz @f |
mov esi, disconnectmsgm |
@@: |
stdcall SysMsgBoardStr |
pop esi |
; 2. If device is keyboard, then we must unregister it as a keyboard and |
; possibly stop the auto-repeat timer. |
cmp byte [ebx+device_data.type], 1 |
jnz .nokbd |
mov eax, [ebx+keyboard_data.timer] |
test eax, eax |
jz @f |
stdcall CancelTimerHS, eax |
@@: |
mov ecx, [ebx+keyboard_data.handle] |
jecxz .nokbd |
stdcall DelKeyboard, ecx |
; If keyboard is registered, then we should free data in CloseKeyboard, not here. |
jmp .nothing |
.nokbd: |
; 3. Free the device data. |
xchg eax, ebx |
call Kfree |
; 4. Return. |
.nothing: |
pop ebx ; restore used register to be stdcall |
ret 4 ; purge one dword argument to be stdcall |
; strings |
my_driver db 'usbhid',0 |
errormsgmouse db 'K : USB transfer error, disabling mouse',10,0 |
errormsgkbd db 'K : USB transfer error, disabling keyboard',10,0 |
disconnectmsgm db 'K : USB mouse disconnected',10,0 |
disconnectmsgk db 'K : USB keyboard disconnected',10,0 |
; data for keyboard: correspondence between HID usage keys and PS/2 scancodes. |
EX = 80h |
label control_keys byte |
db 1Dh, 2Ah, 38h, 5Bh+EX, 1Dh+EX, 36h, 38h+EX, 5Ch+EX |
label normal_keys byte |
db 00h, 00h, 00h, 00h, 1Eh, 30h, 2Eh, 20h, 12h, 21h, 22h, 23h, 17h, 24h, 25h, 26h ; 0x |
db 32h, 31h, 18h, 19h, 10h, 13h, 1Fh, 14h, 16h, 2Fh, 11h, 2Dh, 15h, 2Ch, 02h, 03h ; 1x |
db 04h, 05h, 06h, 07h, 08h, 09h, 0Ah, 0Bh, 1Ch, 01h, 0Eh, 0Fh, 39h, 0Ch, 0Dh, 1Ah ; 2x |
db 1Bh, 2Bh, 2Bh, 27h, 28h, 29h, 33h, 34h, 35h, 3Ah, 3Bh, 3Ch, 3Dh, 3Eh, 3Fh, 40h ; 3x |
db 41h, 42h, 43h, 44h, 57h, 58h,37h+EX,46h,0,52h+EX,47h+EX,49h+EX,53h+EX,4Fh+EX,51h+EX,4Dh+EX ; 4x |
db 4Bh+EX,50h+EX,48h+EX,45h,35h+EX,37h,4Ah,4Eh,1Ch+EX,4Fh,50h,51h,4Bh,4Ch,4Dh,47h ; 5x |
db 48h, 49h, 52h, 53h, 56h,5Dh+EX,5Eh+EX,59h,64h,65h,66h, 67h, 68h, 69h, 6Ah, 6Bh ; 6x |
db 6Ch, 6Dh, 6Eh, 76h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h ; 7x |
db 00h, 00h, 00h, 00h, 00h, 7Eh, 00h, 73h, 70h, 7Dh, 79h, 7Bh, 5Ch, 00h, 00h, 00h ; 8x |
db 0F2h,0F1h,78h, 77h, 76h |
normal_keys_number = $ - normal_keys |
; Exported variable: kernel API version. |
align 4 |
version dd 50005h |
; Structure with callback functions. |
usb_functions: |
dd 12 |
dd AddDevice |
dd DeviceDisconnected |
; Structure with callback functions for keyboards. |
usbkbd_functions: |
dd 12 |
dd CloseKeyboard |
dd SetKeyboardLights |
; for DEBUGF macro |
include_debug_strings |
; for uninitialized data |
section '.data' data readable writable align 16 |
/kernel/branches/Kolibri-acpi/drivers/usbstor.asm |
---|
0,0 → 1,1609 |
; standard driver stuff |
format MS COFF |
DEBUG = 1 |
DUMP_PACKETS = 0 |
; this is for DEBUGF macro from 'fdo.inc' |
__DEBUG__ = 1 |
__DEBUG_LEVEL__ = 1 |
include 'proc32.inc' |
include 'imports.inc' |
include 'fdo.inc' |
public START |
public version |
; USB constants |
DEVICE_DESCR_TYPE = 1 |
CONFIG_DESCR_TYPE = 2 |
STRING_DESCR_TYPE = 3 |
INTERFACE_DESCR_TYPE = 4 |
ENDPOINT_DESCR_TYPE = 5 |
DEVICE_QUALIFIER_DESCR_TYPE = 6 |
CONTROL_PIPE = 0 |
ISOCHRONOUS_PIPE = 1 |
BULK_PIPE = 2 |
INTERRUPT_PIPE = 3 |
; USB structures |
virtual at 0 |
config_descr: |
.bLength db ? |
.bDescriptorType db ? |
.wTotalLength dw ? |
.bNumInterfaces db ? |
.bConfigurationValue db ? |
.iConfiguration db ? |
.bmAttributes db ? |
.bMaxPower db ? |
.sizeof: |
end virtual |
virtual at 0 |
interface_descr: |
.bLength db ? |
.bDescriptorType db ? |
.bInterfaceNumber db ? |
.bAlternateSetting db ? |
.bNumEndpoints db ? |
.bInterfaceClass db ? |
.bInterfaceSubClass db ? |
.bInterfaceProtocol db ? |
.iInterface db ? |
.sizeof: |
end virtual |
virtual at 0 |
endpoint_descr: |
.bLength db ? |
.bDescriptorType db ? |
.bEndpointAddress db ? |
.bmAttributes db ? |
.wMaxPacketSize dw ? |
.bInterval db ? |
.sizeof: |
end virtual |
; Mass storage protocol constants, USB layer |
REQUEST_GETMAXLUN = 0xFE ; get max lun |
REQUEST_BORESET = 0xFF ; bulk-only reset |
; Mass storage protocol structures, USB layer |
; Sent from host to device in the first stage of an operation. |
struc command_block_wrapper |
{ |
.Signature dd ? ; the constant 'USBC' |
.Tag dd ? ; identifies response with request |
.Length dd ? ; length of data-transport phase |
.Flags db ? ; one of CBW_FLAG_* |
CBW_FLAG_OUT = 0 |
CBW_FLAG_IN = 80h |
.LUN db ? ; addressed unit |
.CommandLength db ? ; the length of the following field |
.Command rb 16 |
.sizeof: |
} |
virtual at 0 |
command_block_wrapper command_block_wrapper |
end virtual |
; Sent from device to host in the last stage of an operation. |
struc command_status_wrapper |
{ |
.Signature dd ? ; the constant 'USBS' |
.Tag dd ? ; identifies response with request |
.LengthRest dd ? ; .Length - (size of data which were transferred) |
.Status db ? ; one of CSW_STATUS_* |
CSW_STATUS_OK = 0 |
CSW_STATUS_FAIL = 1 |
CSW_STATUS_FATAL = 2 |
.sizeof: |
} |
virtual at 0 |
command_status_wrapper command_status_wrapper |
end virtual |
; Constants of SCSI layer |
SCSI_REQUEST_SENSE = 3 |
SCSI_INQUIRY = 12h |
SCSI_READ_CAPACITY = 25h |
SCSI_READ10 = 28h |
SCSI_WRITE10 = 2Ah |
; Result of SCSI REQUEST SENSE command. |
SENSE_UNKNOWN = 0 |
SENSE_RECOVERED_ERROR = 1 |
SENSE_NOT_READY = 2 |
SENSE_MEDIUM_ERROR = 3 |
SENSE_HARDWARE_ERROR = 4 |
SENSE_ILLEGAL_REQUEST = 5 |
SENSE_UNIT_ATTENTION = 6 |
SENSE_DATA_PROTECT = 7 |
SENSE_BLANK_CHECK = 8 |
; 9 is vendor-specific |
SENSE_COPY_ABORTED = 10 |
SENSE_ABORTED_COMMAND = 11 |
SENSE_EQUAL = 12 |
SENSE_VOLUME_OVERFLOW = 13 |
SENSE_MISCOMPARE = 14 |
; 15 is reserved |
; Structures of SCSI layer |
; Result of SCSI INQUIRY request. |
struc inquiry_data |
{ |
.PeripheralDevice db ? ; lower 5 bits are PeripheralDeviceType |
; upper 3 bits are PeripheralQualifier |
.RemovableMedium db ? ; upper bit is RemovableMedium |
; other bits are for compatibility |
.Version db ? ; lower 3 bits are ANSI-Approved version |
; next 3 bits are ECMA version |
; upper 2 bits are ISO version |
.ResponseDataFormat db ? ; lower 4 bits are ResponseDataFormat |
; bit 6 is TrmIOP |
; bit 7 is AENC |
.AdditionalLength db ? |
dw ? ; reserved |
.Flags db ? |
.VendorID rb 8 ; vendor ID, big-endian |
.ProductID rb 16 ; product ID, big-endian |
.ProductRevBE dd ? ; product revision, big-endian |
.sizeof: |
} |
virtual at 0 |
inquiry_data inquiry_data |
end virtual |
struc sense_data |
{ |
.ErrorCode db ? ; lower 7 bits are error code: |
; 70h = current error, |
; 71h = deferred error |
; upper bit is InformationValid |
.SegmentNumber db ? ; number of segment descriptor |
; for commands COPY [+VERIFY], COMPARE |
.SenseKey db ? ; bits 0-3 are one of SENSE_* |
; bit 4 is reserved |
; bit 5 is IncorrectLengthIndicator |
; bits 6 and 7 are used by |
; sequential-access devices |
.Information dd ? ; command-specific |
.AdditionalLength db ? ; length of data starting here |
.CommandInformation dd ? ; command-specific |
.AdditionalSenseCode db ? ; \ more detailed error code |
.AdditionalSenseQual db ? ; / standard has a large table of them |
.FRUCode db ? ; which part of device has failed |
; (device-specific, not regulated) |
.SenseKeySpecific rb 3 ; depends on SenseKey |
.sizeof: |
} |
virtual at 0 |
sense_data sense_data |
end virtual |
; Device data |
; USB Mass storage device has one or more logical units, identified by LUN, |
; logical unit number. The highest value of LUN, that is, number of units |
; minus 1, can be obtained via control request Get Max LUN. |
virtual at 0 |
usb_device_data: |
.ConfigPipe dd ? ; configuration pipe |
.OutPipe dd ? ; pipe for OUT bulk endpoint |
.InPipe dd ? ; pipe for IN bulk endpoint |
.MaxLUN dd ? ; maximum Logical Unit Number |
.LogicalDevices dd ? ; pointer to array of usb_unit_data |
; 1 for a connected USB device, 1 for each disk device |
; the structure can be freed when .NumReferences decreases to zero |
.NumReferences dd ? ; number of references |
.ConfigRequest rb 8 ; buffer for configuration requests |
.LengthRest dd ? ; Length - (size of data which were transferred) |
; All requests to a given device are serialized, |
; only one request to a given device can be processed at a time. |
; The current request and all pending requests are organized in the following |
; queue, the head being the current request. |
; NB: the queue must be device-wide due to the protocol: |
; data stage is not tagged (unlike command_*_wrapper), so the only way to know |
; what request the data are associated with is to guarantee that only one |
; request is processing at the time. |
.RequestsQueue rd 2 |
.QueueLock rd 3 ; protects .RequestsQueue |
.InquiryData inquiry_data ; information about device |
; data for the current request |
.Command command_block_wrapper |
.DeviceDisconnected db ? |
.Status command_status_wrapper |
.Sense sense_data |
.sizeof: |
end virtual |
; Information about one logical device. |
virtual at 0 |
usb_unit_data: |
.Parent dd ? ; pointer to parent usb_device_data |
.LUN db ? ; index in usb_device_data.LogicalDevices array |
.DiskIndex db ? ; for name "usbhd<index>" |
.MediaPresent db ? |
db ? ; alignment |
.DiskDevice dd ? ; handle of disk device or NULL |
.SectorSize dd ? ; sector size |
; For some devices, the first request to the medium fails with 'unit not ready'. |
; When the code sees this status, it retries the command several times. |
; Two following variables track the retry count and total time for those; |
; total time is currently used only for debug output. |
.UnitReadyAttempts dd ? |
.TimerTicks dd ? |
.sizeof: |
end virtual |
; This is the structure for items in the queue usb_device_data.RequestsQueue. |
virtual at 0 |
request_queue_item: |
.Next dd ? ; next item in the queue |
.Prev dd ? ; prev item in the queue |
.ReqBuilder dd ? ; procedure to fill command_block_wrapper |
.Buffer dd ? ; input or output data |
; (length is command_block_wrapper.Length) |
.Callback dd ? ; procedure to call in the end of transfer |
.UserData dd ? ; passed as-is to .Callback |
; There are 3 possible stages of any request, one of them optional: |
; command stage (host sends command_block_wrapper to device), |
; optional data stage, |
; status stage (device sends command_status_wrapper to host). |
; Also, if a request fails, the code queues additional request |
; SCSI_REQUEST_SENSE; sense_data from SCSI_REQUEST_SENSE |
; contains some information about the error. |
.Stage db ? |
.sizeof: |
end virtual |
section '.flat' code readable align 16 |
; The start procedure. |
proc START |
virtual at esp |
dd ? ; return address |
.reason dd ? ; DRV_ENTRY or DRV_EXIT |
end virtual |
; 1. Test whether the procedure is called with the argument DRV_ENTRY. |
; If not, return 0. |
xor eax, eax ; initialize return value |
cmp [.reason], 1 ; compare the argument |
jnz .nothing |
; 2. Initialize: we have one global mutex. |
mov ecx, free_numbers_lock |
call MutexInit |
; 3. Register self as a USB driver. |
; The name is my_driver = 'usbstor'; IOCTL interface is not supported; |
; usb_functions is an offset of a structure with callback functions. |
stdcall RegUSBDriver, my_driver, 0, usb_functions |
; 4. Return the returned value of RegUSBDriver. |
.nothing: |
ret 4 |
endp |
; Helper procedures to work with requests queue. |
; Add a request to the queue. Stdcall with 5 arguments. |
proc queue_request |
push ebx esi |
virtual at esp |
rd 2 ; saved registers |
dd ? ; return address |
.device dd ? ; pointer to usb_device_data |
.ReqBuilder dd ? ; request_queue_item.ReqBuilder |
.Buffer dd ? ; request_queue_item.Buffer |
.Callback dd ? ; request_queue_item.Callback |
.UserData dd ? ; request_queue_item.UserData |
end virtual |
; 1. Allocate the memory for the request description. |
push request_queue_item.sizeof |
pop eax |
call Kmalloc |
test eax, eax |
jnz @f |
mov esi, nomemory |
call SysMsgBoardStr |
pop esi ebx |
ret 20 |
@@: |
; 2. Fill user-provided parts of the request description. |
push edi |
xchg eax, ebx |
lea esi, [.ReqBuilder+4] |
lea edi, [ebx+request_queue_item.ReqBuilder] |
movsd ; ReqBuilder |
movsd ; Buffer |
movsd ; Callback |
movsd ; UserData |
pop edi |
; 3. Set stage to zero: not started. |
mov [ebx+request_queue_item.Stage], 0 |
; 4. Lock the queue. |
mov esi, [.device] |
lea ecx, [esi+usb_device_data.QueueLock] |
call MutexLock |
; 5. Insert the request to the tail of the queue. |
add esi, usb_device_data.RequestsQueue |
mov edx, [esi+request_queue_item.Prev] |
mov [ebx+request_queue_item.Next], esi |
mov [ebx+request_queue_item.Prev], edx |
mov [edx+request_queue_item.Next], ebx |
mov [esi+request_queue_item.Prev], ebx |
; 6. Test whether the queue was empty |
; and the request should be started immediately. |
cmp [esi+request_queue_item.Next], ebx |
jnz .unlock |
; 8. If the step 6 shows that the request is the first in the queue, |
; start it. |
sub esi, usb_device_data.RequestsQueue |
call setup_request |
jmp .nothing |
.unlock: |
call MutexUnlock |
; 9. Return. |
.nothing: |
pop esi ebx |
ret 20 |
endp |
; The current request is completed. Call the callback, |
; remove the request from the queue, start the next |
; request if there is one. |
; esi points to usb_device_data |
proc complete_request |
; 1. Print common debug messages on fails. |
if DEBUG |
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FAIL |
jb .normal |
jz .fail |
DEBUGF 1, 'K : Fatal error during execution of command %x\n', [esi+usb_device_data.Command.Command]:2 |
jmp .normal |
.fail: |
DEBUGF 1, 'K : Command %x failed\n', [esi+usb_device_data.Command.Command]:2 |
.normal: |
end if |
; 2. Get the current request. |
mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next] |
; 3. Call the callback. |
stdcall [ebx+request_queue_item.Callback], esi, [ebx+request_queue_item.UserData] |
; 4. Lock the queue. |
lea ecx, [esi+usb_device_data.QueueLock] |
call MutexLock |
; 5. Remove the request. |
lea edx, [esi+usb_device_data.RequestsQueue] |
mov eax, [ebx+request_queue_item.Next] |
mov [eax+request_queue_item.Prev], edx |
mov [edx+request_queue_item.Next], eax |
; 6. Free the request memory. |
push eax edx |
xchg eax, ebx |
call Kfree |
pop edx ebx |
; 7. If there is a next request, start processing. |
cmp ebx, edx |
jnz setup_request |
; 8. Unlock the queue and return. |
lea ecx, [esi+usb_device_data.QueueLock] |
call MutexUnlock |
ret |
endp |
; Start processing the request. Called either by queue_request |
; or when the previous request has been processed. |
; Do not call directly, use queue_request. |
; Must be called when queue is locked; unlocks the queue when returns. |
proc setup_request |
xor eax, eax |
; 1. If DeviceDisconnected has been run, then all handles of pipes |
; are invalid, so we must fail immediately. |
; (That is why this function needs the locked queue: this |
; guarantee that either DeviceDisconnected has been already run, or |
; DeviceDisconnected will not return before the queue is unlocked.) |
cmp [esi+usb_device_data.DeviceDisconnected], al |
jnz .fatal |
; 2. If the previous command has encountered a fatal error, |
; perform reset recovery. |
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
jb .norecovery |
; 2a. Send Bulk-Only Mass Storage Reset command to config pipe. |
lea edx, [esi+usb_device_data.ConfigRequest] |
mov word [edx], (REQUEST_BORESET shl 8) + 21h ; class request |
mov word [edx+6], ax ; length = 0 |
stdcall USBControlTransferAsync, [esi+usb_device_data.ConfigPipe], edx, eax, eax, recovery_callback1, esi, eax |
; 2b. Fail here = fatal error. |
test eax, eax |
jz .fatal |
; 2c. Otherwise, unlock the queue and return. recovery_callback1 will continue processing. |
.unlock_return: |
lea ecx, [esi+usb_device_data.QueueLock] |
call MutexUnlock |
ret |
.norecovery: |
; 3. Send the command. Fail (no memory or device disconnected) = fatal error. |
; Otherwise, go to 2c. |
call request_stage1 |
test eax, eax |
jnz .unlock_return |
.fatal: |
; 4. Fatal error. Set status = FATAL, unlock the queue, complete the request. |
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
lea ecx, [esi+usb_device_data.QueueLock] |
call MutexUnlock |
jmp complete_request |
endp |
; Initiate USB transfer for the first stage of a request (send command). |
proc request_stage1 |
mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next] |
; 1. Set the stage to 1 = command stage. |
inc [ebx+request_queue_item.Stage] |
; 2. Generate the command. Zero-initialize and use the caller-provided proc. |
lea edx, [esi+usb_device_data.Command] |
xor eax, eax |
mov [edx+command_block_wrapper.CommandLength], 12 |
mov dword [edx+command_block_wrapper.Command], eax |
mov dword [edx+command_block_wrapper.Command+4], eax |
mov dword [edx+command_block_wrapper.Command+8], eax |
mov dword [edx+command_block_wrapper.Command+12], eax |
inc [edx+command_block_wrapper.Tag] |
stdcall [ebx+request_queue_item.ReqBuilder], edx, [ebx+request_queue_item.UserData] |
; 4. Initiate USB transfer. |
lea edx, [esi+usb_device_data.Command] |
if DUMP_PACKETS |
DEBUGF 1,'K : USBSTOR out:' |
mov eax, edx |
mov ecx, command_block_wrapper.sizeof |
call debug_dump |
DEBUGF 1,'\n' |
end if |
stdcall USBNormalTransferAsync, [esi+usb_device_data.OutPipe], edx, command_block_wrapper.sizeof, request_callback1, esi, 0 |
ret |
endp |
if DUMP_PACKETS |
proc debug_dump |
test ecx, ecx |
jz .done |
.loop: |
test ecx, 0Fh |
jnz @f |
DEBUGF 1,'\nK :' |
@@: |
DEBUGF 1,' %x',[eax]:2 |
inc eax |
dec ecx |
jnz .loop |
.done: |
ret |
endp |
end if |
; Called when the Reset command is completed, |
; either successfully or not. |
proc recovery_callback1 |
virtual at esp |
dd ? ; return address |
.pipe dd ? |
.status dd ? |
.buffer dd ? |
.length dd ? |
.calldata dd ? |
end virtual |
cmp [.status], 0 |
jnz .error |
; todo: reset pipes |
push ebx esi |
mov esi, [.calldata+8] |
call request_stage1 |
pop esi ebx |
test eax, eax |
jz .error |
ret 20 |
.error: |
DEBUGF 1, 'K : error %d while resetting', [.status] |
jmp request_callback1.common_error |
endp |
; Called when the first stage of request is completed, |
; either successfully or not. |
proc request_callback1 |
virtual at esp |
dd ? ; return address |
.pipe dd ? |
.status dd ? |
.buffer dd ? |
.length dd ? |
.calldata dd ? |
end virtual |
; 1. Initialize. |
mov ecx, [.calldata] |
mov eax, [.status] |
; 2. Test for error. |
test eax, eax |
jnz .error |
; No error. |
; 3. Increment the stage. |
mov edx, [ecx+usb_device_data.RequestsQueue+request_queue_item.Next] |
inc [edx+request_queue_item.Stage] |
; 4. If there is no data, skip this stage. |
cmp [ecx+usb_device_data.Command.Length], 0 |
jz ..request_get_status |
; 5. Initiate USB transfer. If this fails, go to the error handler. |
mov eax, [ecx+usb_device_data.InPipe] |
cmp [ecx+usb_device_data.Command.Flags], 0 |
js @f |
mov eax, [ecx+usb_device_data.OutPipe] |
if DUMP_PACKETS |
DEBUGF 1,'K : USBSTOR out:' |
push eax ecx |
mov eax, [edx+request_queue_item.Buffer] |
mov ecx, [ecx+usb_device_data.Command.Length] |
call debug_dump |
pop ecx eax |
DEBUGF 1,'\n' |
end if |
@@: |
stdcall USBNormalTransferAsync, eax, [edx+request_queue_item.Buffer], [ecx+usb_device_data.Command.Length], request_callback2, ecx, 0 |
test eax, eax |
jz .error |
; 6. Return. |
ret 20 |
.error: |
; Error. |
; 7. Print debug message and complete the request as failed. |
DEBUGF 1,'K : error %d after %d bytes in request stage\n',eax,[.length] |
.common_error: |
; TODO: add recovery after STALL |
mov ecx, [.calldata] |
mov [ecx+usb_device_data.Status.Status], CSW_STATUS_FATAL |
push ebx esi |
mov esi, ecx |
call complete_request |
pop esi ebx |
ret 20 |
endp |
; Called when the second stage of request is completed, |
; either successfully or not. |
proc request_callback2 |
virtual at esp |
dd ? ; return address |
.pipe dd ? |
.status dd ? |
.buffer dd ? |
.length dd ? |
.calldata dd ? |
end virtual |
if DUMP_PACKETS |
mov eax, [.calldata] |
mov eax, [eax+usb_device_data.InPipe] |
cmp [.pipe], eax |
jnz @f |
DEBUGF 1,'K : USBSTOR in:' |
push eax ecx |
mov eax, [.buffer+8] |
mov ecx, [.length+8] |
call debug_dump |
pop ecx eax |
DEBUGF 1,'\n' |
@@: |
end if |
; 1. Initialize. |
mov ecx, [.calldata] |
mov eax, [.status] |
; 2. Test for error. |
test eax, eax |
jnz .error |
; No error. |
..request_get_status: |
; 3. Increment the stage. |
mov edx, [ecx+usb_device_data.RequestsQueue+request_queue_item.Next] |
inc [edx+request_queue_item.Stage] |
; 4. Initiate USB transfer. If this fails, go to the error handler. |
lea edx, [ecx+usb_device_data.Status] |
stdcall USBNormalTransferAsync, [ecx+usb_device_data.InPipe], edx, command_status_wrapper.sizeof, request_callback3, ecx, 0 |
test eax, eax |
jz .error |
ret 20 |
.error: |
; Error. |
; 7. Print debug message and complete the request as failed. |
DEBUGF 1,'K : error %d after %d bytes in data stage\n',eax,[.length] |
jmp request_callback1.common_error |
endp |
; Called when the third stage of request is completed, |
; either successfully or not. |
proc request_callback3 |
virtual at esp |
dd ? ; return address |
.pipe dd ? |
.status dd ? |
.buffer dd ? |
.length dd ? |
.calldata dd ? |
end virtual |
if DUMP_PACKETS |
DEBUGF 1,'K : USBSTOR in:' |
mov eax, [.buffer] |
mov ecx, [.length] |
call debug_dump |
DEBUGF 1,'\n' |
end if |
; 1. Initialize. |
mov eax, [.status] |
; 2. Test for error. |
test eax, eax |
jnz .transfer_error |
; Transfer is OK. |
; 3. Validate the status. Invalid status = fatal error. |
push ebx esi |
mov esi, [.calldata+8] |
mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next] |
cmp [esi+usb_device_data.Status.Signature], 'USBS' |
jnz .invalid |
mov eax, [esi+usb_device_data.Command.Tag] |
cmp [esi+usb_device_data.Status.Tag], eax |
jnz .invalid |
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
ja .invalid |
; 4. The status block is valid. Check the status code. |
jz .complete |
; 5. If this command was not REQUEST_SENSE, copy status data to safe place. |
; Otherwise, the original command has failed, so restore the fail status. |
cmp byte [esi+usb_device_data.Command.Command], SCSI_REQUEST_SENSE |
jz .request_sense |
mov eax, [esi+usb_device_data.Status.LengthRest] |
mov [esi+usb_device_data.LengthRest], eax |
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FAIL |
jz .fail |
.complete: |
call complete_request |
.nothing: |
pop esi ebx |
ret 20 |
.request_sense: |
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FAIL |
jmp .complete |
.invalid: |
; 6. Invalid status block. Say error, set status to fatal and complete request. |
push esi |
mov esi, invresponse |
call SysMsgBoardStr |
pop esi |
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
jmp .complete |
.fail: |
; 7. The command has failed. |
; If this command was not REQUEST_SENSE, schedule the REQUEST_SENSE command |
; to determine the reason of fail. Otherwise, assume that there is no error data. |
cmp [esi+usb_device_data.Command.Command], SCSI_REQUEST_SENSE |
jz .fail_request_sense |
mov [ebx+request_queue_item.ReqBuilder], request_sense_req |
lea eax, [esi+usb_device_data.Sense] |
mov [ebx+request_queue_item.Buffer], eax |
call request_stage1 |
test eax, eax |
jnz .nothing |
.fail_request_sense: |
DEBUGF 1,'K : fail during REQUEST SENSE\n' |
mov byte [esi+usb_device_data.Sense], 0 |
jmp .complete |
.transfer_error: |
; TODO: add recovery after STALL |
DEBUGF 1,'K : error %d after %d bytes in status stage\n',eax,[.length] |
jmp request_callback1.common_error |
endp |
; Builder for SCSI_REQUEST_SENSE request. |
; edx = first argument = pointer to usb_device_data.Command, |
; second argument = custom data given to queue_request (ignored). |
proc request_sense_req |
mov [edx+command_block_wrapper.Length], sense_data.sizeof |
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
mov byte [edx+command_block_wrapper.Command+0], SCSI_REQUEST_SENSE |
mov byte [edx+command_block_wrapper.Command+4], sense_data.sizeof |
ret 8 |
endp |
; This procedure is called when new mass-storage device is detected. |
; It initializes the device. |
; Technically, initialization implies sending several USB queries, |
; so it is split in several procedures. The first is AddDevice, |
; other are callbacks which will be called at some time in the future, |
; when the device will respond. |
; The general scheme: |
; * AddDevice parses descriptors, opens pipes; if everything is ok, |
; AddDevice sends REQUEST_GETMAXLUN with callback known_lun_callback; |
; * known_lun_callback allocates memory for LogicalDevices and sends |
; SCSI_TEST_UNIT_READY to all logical devices with test_unit_ready_callback; |
; * test_unit_ready_callback checks whether the unit is ready; |
; if not, it repeats the same request several times; |
; if ok or there were too many attempts, it sends SCSI_INQUIRY with |
; callback inquiry_callback; |
; * inquiry_callback checks that a logical device is a block device |
; and the unit was ready; if so, it notifies the kernel about new disk device. |
proc AddDevice |
push ebx esi |
virtual at esp |
rd 2 ; saved registers ebx, esi |
dd ? ; return address |
.pipe0 dd ? ; handle of the config pipe |
.config dd ? ; pointer to config_descr |
.interface dd ? ; pointer to interface_descr |
end virtual |
; 1. Check device type. Currently only SCSI-command-set Bulk-only devices |
; are supported. |
; 1a. Get the subclass and the protocol. Since bInterfaceSubClass and |
; bInterfaceProtocol are subsequent in interface_descr, just one |
; memory reference is used for both. |
mov esi, [.interface] |
xor ebx, ebx |
mov cx, word [esi+interface_descr.bInterfaceSubClass] |
; 1b. For Mass-storage SCSI-command-set Bulk-only devices subclass must be 6 |
; and protocol must be 50h. Check. |
cmp cx, 0x5006 |
jz .known |
; There are devices with subclass 5 which use the same protocol 50h. |
; The difference is not important for the code except for this test, |
; so allow them to proceed also. |
cmp cx, 0x5005 |
jz .known |
; 1c. If the device is unknown, print a message and go to 11c. |
mov esi, unkdevice |
call SysMsgBoardStr |
jmp .nothing |
; 1d. If the device uses known command set, print a message and continue |
; configuring. |
.known: |
push esi |
mov esi, okdevice |
call SysMsgBoardStr |
pop esi |
; 2. Allocate memory for internal device data. |
; 2a. Call the kernel. |
mov eax, usb_device_data.sizeof |
call Kmalloc |
; 2b. Check return value. |
test eax, eax |
jnz @f |
; 2c. If failed, say a message and go to 11c. |
mov esi, nomemory |
call SysMsgBoardStr |
jmp .nothing |
@@: |
; 2d. If succeeded, zero the contents and continue configuring. |
xchg ebx, eax ; ebx will point to usb_device_data |
xor eax, eax |
mov [ebx+usb_device_data.OutPipe], eax |
mov [ebx+usb_device_data.InPipe], eax |
mov [ebx+usb_device_data.MaxLUN], eax |
mov [ebx+usb_device_data.LogicalDevices], eax |
mov dword [ebx+usb_device_data.ConfigRequest], eax |
mov dword [ebx+usb_device_data.ConfigRequest+4], eax |
mov [ebx+usb_device_data.Status.Status], al |
mov [ebx+usb_device_data.DeviceDisconnected], al |
; 2e. There is one reference: a connected USB device. |
inc eax |
mov [ebx+usb_device_data.NumReferences], eax |
; 2f. Save handle of configuration pipe for reset recovery. |
mov eax, [.pipe0] |
mov [ebx+usb_device_data.ConfigPipe], eax |
; 2g. Save the interface number for configuration requests. |
mov al, [esi+interface_descr.bInterfaceNumber] |
mov [ebx+usb_device_data.ConfigRequest+4], al |
; 2h. Initialize common fields in command wrapper. |
mov [ebx+usb_device_data.Command.Signature], 'USBC' |
mov [ebx+usb_device_data.Command.Tag], 'xxxx' |
; 2i. Initialize requests queue. |
lea eax, [ebx+usb_device_data.RequestsQueue] |
mov [eax+request_queue_item.Next], eax |
mov [eax+request_queue_item.Prev], eax |
lea ecx, [ebx+usb_device_data.QueueLock] |
call MutexInit |
; Bulk-only mass storage devices use one OUT bulk endpoint for sending |
; command/data and one IN bulk endpoint for receiving data/status. |
; Look for those endpoints. |
; 3. Get the upper bound of all descriptors' data. |
mov edx, [.config] ; configuration descriptor |
movzx ecx, [edx+config_descr.wTotalLength] |
add edx, ecx |
; 4. Loop over all descriptors until |
; either end-of-data reached - this is fail |
; or interface descriptor found - this is fail, all further data |
; correspond to that interface |
; or both endpoint descriptors found. |
; 4a. Loop start: esi points to the interface descriptor, |
.lookep: |
; 4b. Get next descriptor. |
movzx ecx, byte [esi] ; the first byte of all descriptors is length |
add esi, ecx |
; 4c. Check that at least two bytes are readable. The opposite is an error. |
inc esi |
cmp esi, edx |
jae .errorep |
dec esi |
; 4d. Check that this descriptor is not interface descriptor. The opposite is |
; an error. |
cmp byte [esi+endpoint_descr.bDescriptorType], INTERFACE_DESCR_TYPE |
jz .errorep |
; 4e. Test whether this descriptor is an endpoint descriptor. If not, continue |
; the loop. |
cmp byte [esi+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE |
jnz .lookep |
; 5. Check that the descriptor contains all required data and all data are |
; readable. The opposite is an error. |
cmp byte [esi+endpoint_descr.bLength], endpoint_descr.sizeof |
jb .errorep |
lea ecx, [esi+endpoint_descr.sizeof] |
cmp ecx, edx |
ja .errorep |
; 6. Check that the endpoint is bulk endpoint. The opposite is an error. |
mov cl, [esi+endpoint_descr.bmAttributes] |
and cl, 3 |
cmp cl, BULK_PIPE |
jnz .errorep |
; 7. Get the direction of this endpoint. |
movzx ecx, [esi+endpoint_descr.bEndpointAddress] |
shr ecx, 7 |
; 8. Test whether a pipe for this direction is already opened. If so, continue |
; the loop. |
cmp [ebx+usb_device_data.OutPipe+ecx*4], 0 |
jnz .lookep |
; 9. Open pipe for this endpoint. |
; 9a. Save registers. |
push ecx edx |
; 9b. Load parameters from the descriptor. |
movzx ecx, [esi+endpoint_descr.bEndpointAddress] |
movzx edx, [esi+endpoint_descr.wMaxPacketSize] |
movzx eax, [esi+endpoint_descr.bInterval] ; not used for USB1, may be important for USB2 |
; 9c. Call the kernel. |
stdcall USBOpenPipe, [ebx+usb_device_data.ConfigPipe], ecx, edx, BULK_PIPE, eax |
; 9d. Restore registers. |
pop edx ecx |
; 9e. Check result. If failed, go to 11b. |
test eax, eax |
jz .free |
; 9f. Save result. |
mov [ebx+usb_device_data.OutPipe+ecx*4], eax |
; 10. Test whether the second pipe is already opened. If not, continue loop. |
xor ecx, 1 |
cmp [ebx+usb_device_data.OutPipe+ecx*4], 0 |
jz .lookep |
jmp .created |
; 11. An error occured during processing endpoint descriptor. |
.errorep: |
; 11a. Print a message. |
DEBUGF 1,'K : error: invalid endpoint descriptor\n' |
.free: |
; 11b. Free the allocated usb_device_data. |
xchg eax, ebx |
call Kfree |
.nothing: |
; 11c. Return an error. |
xor eax, eax |
jmp .return |
.created: |
; 12. Pipes are opened. Send GetMaxLUN control request. |
lea eax, [ebx+usb_device_data.ConfigRequest] |
mov byte [eax], 0A1h ; class request from interface |
mov byte [eax+1], REQUEST_GETMAXLUN |
mov byte [eax+6], 1 ; transfer 1 byte |
lea ecx, [ebx+usb_device_data.MaxLUN] |
if DUMP_PACKETS |
DEBUGF 1,'K : GETMAXLUN: %x %x %x %x %x %x %x %x\n',[eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2 |
end if |
stdcall USBControlTransferAsync, [ebx+usb_device_data.ConfigPipe], eax, ecx, 1, known_lun_callback, ebx, 0 |
; 13. Return with pointer to device data as returned value. |
xchg eax, ebx |
.return: |
pop esi ebx |
ret 12 |
endp |
; This function is called when REQUEST_GETMAXLUN is done, |
; either successful or unsuccessful. |
proc known_lun_callback |
push ebx esi |
virtual at esp |
rd 2 ; saved registers |
dd ? ; return address |
.pipe dd ? |
.status dd ? |
.buffer dd ? |
.length dd ? |
.calldata dd ? |
end virtual |
; 1. Check the status. If the request failed, assume that MaxLUN is zero. |
mov ebx, [.calldata] |
mov eax, [.status] |
test eax, eax |
jz @f |
DEBUGF 1, 'K : GETMAXLUN failed with status %d, assuming zero\n', eax |
mov [ebx+usb_device_data.MaxLUN], 0 |
@@: |
; 2. Allocate the memory for logical devices. |
mov eax, [ebx+usb_device_data.MaxLUN] |
inc eax |
DEBUGF 1,'K : %d logical unit(s)\n',eax |
imul eax, usb_unit_data.sizeof |
push ebx |
call Kmalloc |
pop ebx |
; If failed, print a message and do nothing. |
test eax, eax |
jnz @f |
mov esi, nomemory |
call SysMsgBoardStr |
pop esi ebx |
ret 20 |
@@: |
mov [ebx+usb_device_data.LogicalDevices], eax |
; 3. Initialize logical devices and initiate TEST_UNIT_READY request. |
xchg esi, eax |
xor ecx, ecx |
.looplun: |
mov [esi+usb_unit_data.Parent], ebx |
mov [esi+usb_unit_data.LUN], cl |
xor eax, eax |
mov [esi+usb_unit_data.MediaPresent], al |
mov [esi+usb_unit_data.DiskDevice], eax |
mov [esi+usb_unit_data.SectorSize], eax |
mov [esi+usb_unit_data.UnitReadyAttempts], eax |
push ecx |
call GetTimerTicks |
mov [esi+usb_unit_data.TimerTicks], eax |
stdcall queue_request, ebx, test_unit_ready_req, 0, test_unit_ready_callback, esi |
pop ecx |
inc ecx |
add esi, usb_unit_data.sizeof |
cmp ecx, [ebx+usb_device_data.MaxLUN] |
jbe .looplun |
; 4. Return. |
pop esi ebx |
ret 20 |
endp |
; Builder for SCSI INQUIRY request. |
; edx = first argument = pointer to usb_device_data.Command, |
; second argument = custom data given to queue_request. |
proc inquiry_req |
mov eax, [esp+8] |
mov al, [eax+usb_unit_data.LUN] |
mov [edx+command_block_wrapper.Length], inquiry_data.sizeof |
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
mov [edx+command_block_wrapper.LUN], al |
mov byte [edx+command_block_wrapper.Command+0], SCSI_INQUIRY |
mov byte [edx+command_block_wrapper.Command+4], inquiry_data.sizeof |
ret 8 |
endp |
; Called when SCSI INQUIRY request is completed. |
proc inquiry_callback |
; 1. Check the status. |
mov ecx, [esp+4] |
cmp [ecx+usb_device_data.Status.Status], CSW_STATUS_OK |
jnz .fail |
; 2. The command has completed successfully. |
; Print a message showing device type, ignore anything but block devices. |
mov al, [ecx+usb_device_data.InquiryData.PeripheralDevice] |
and al, 1Fh |
DEBUGF 1,'K : peripheral device type is %x\n',al |
test al, al |
jnz .nothing |
DEBUGF 1,'K : direct-access mass storage device detected\n' |
; 3. We have found a new disk device. Increment number of references. |
lock inc [ecx+usb_device_data.NumReferences] |
; Unfortunately, we are now in the context of the USB thread, |
; so we can't notify the kernel immediately: it would try to do something |
; with a new disk, those actions would be synchronous and would require |
; waiting for results of USB requests, but we need to exit this callback |
; to allow the USB thread to continue working and handling those requests. |
; 4. Thus, create a temporary kernel thread which would do it. |
mov edx, [esp+8] |
push ebx ecx |
push 51 |
pop eax |
push 1 |
pop ebx |
mov ecx, new_disk_thread |
; edx = parameter |
int 0x40 |
pop ecx ebx |
cmp eax, -1 |
jnz .nothing |
; on error, reverse step 3 |
lock dec [ecx+usb_device_data.NumReferences] |
.nothing: |
ret 8 |
.fail: |
; 4. The command has failed. Print a message and do nothing. |
push esi |
mov esi, inquiry_fail |
call SysMsgBoardStr |
pop esi |
ret 8 |
endp |
; Builder for SCSI TEST_UNIT_READY request. |
; edx = first argument = pointer to usb_device_data.Command, |
; second argument = custom data given to queue_request. |
proc test_unit_ready_req |
mov eax, [esp+8] |
mov al, [eax+usb_unit_data.LUN] |
mov [edx+command_block_wrapper.Length], 0 |
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
mov [edx+command_block_wrapper.LUN], al |
ret 8 |
endp |
; Called when SCSI TEST_UNIT_READY request is completed. |
proc test_unit_ready_callback |
virtual at esp |
dd ? ; return address |
.device dd ? |
.calldata dd ? |
end virtual |
; 1. Check the status. |
mov ecx, [.device] |
mov edx, [.calldata] |
cmp [ecx+usb_device_data.Status.Status], CSW_STATUS_OK |
jnz .fail |
; 2. The command has completed successfully, |
; possibly after some repetitions. Print a debug message showing |
; number and time of those. Remember that media is ready and go to 4. |
DEBUGF 1,'K : media is ready\n' |
call GetTimerTicks |
sub eax, [edx+usb_unit_data.TimerTicks] |
DEBUGF 1,'K : %d attempts, %d ticks\n',[edx+usb_unit_data.UnitReadyAttempts],eax |
inc [edx+usb_unit_data.MediaPresent] |
jmp .inquiry |
.fail: |
; 3. The command has failed. |
; Retry the same request up to 3 times with 10ms delay; |
; if limit of retries is not reached, exit from the function. |
; Otherwise, go to 4. |
inc [edx+usb_unit_data.UnitReadyAttempts] |
cmp [edx+usb_unit_data.UnitReadyAttempts], 3 |
jz @f |
push ecx edx esi |
push 10 |
pop esi |
call Sleep |
pop esi edx ecx |
stdcall queue_request, ecx, test_unit_ready_req, 0, test_unit_ready_callback, edx |
ret 8 |
@@: |
DEBUGF 1,'K : media not ready\n' |
.inquiry: |
; 4. initiate INQUIRY request. |
lea eax, [ecx+usb_device_data.InquiryData] |
stdcall queue_request, ecx, inquiry_req, eax, inquiry_callback, edx |
ret 8 |
endp |
; Temporary thread for initial actions with a new disk device. |
proc new_disk_thread |
sub esp, 32 |
virtual at esp |
.name rb 32 ; device name |
.param dd ? ; contents of edx at the moment of int 0x40/eax=51 |
dd ? ; stack segment |
end virtual |
; We are ready to notify the kernel about a new disk device. |
mov esi, [.param] |
; 1. Generate name. |
; 1a. Find a free index. |
mov ecx, free_numbers_lock |
call MutexLock |
xor eax, eax |
@@: |
bsf edx, [free_numbers+eax] |
jnz @f |
add eax, 4 |
cmp eax, 4*4 |
jnz @b |
call MutexUnlock |
push esi |
mov esi, noindex |
call SysMsgBoardStr |
pop esi |
jmp .drop_reference |
@@: |
; 1b. Mark the index as busy. |
btr [free_numbers+eax], edx |
lea eax, [eax*8+edx] |
push eax |
call MutexUnlock |
pop eax |
; 1c. Generate a name of the form "usbhd<index>" in the stack. |
mov dword [esp], 'usbh' |
lea edi, [esp+5] |
mov byte [edi-1], 'd' |
push eax |
push -'0' |
push 10 |
pop ecx |
@@: |
cdq |
div ecx |
push edx |
test eax, eax |
jnz @b |
@@: |
pop eax |
add al, '0' |
stosb |
jnz @b |
pop ecx |
mov edx, esp |
; 3d. Store the index in usb_unit_data to free it later. |
mov [esi+usb_unit_data.DiskIndex], cl |
; 4. Notify the kernel about a new disk. |
; 4a. Add a disk. |
; stdcall queue_request, ecx, read_capacity_req, eax, read_capacity_callback, eax |
stdcall DiskAdd, disk_functions, edx, esi, 0 |
mov ebx, eax |
; 4b. If it failed, release the index and do nothing. |
test eax, eax |
jz .free_index |
; 4c. Notify the kernel that a media is present. |
stdcall DiskMediaChanged, eax, 1 |
; 5. Lock the requests queue, check that device is not disconnected, |
; store the disk handle, unlock the requests queue. |
mov ecx, [esi+usb_unit_data.Parent] |
add ecx, usb_device_data.QueueLock |
call MutexLock |
cmp byte [ecx+usb_device_data.DeviceDisconnected-usb_device_data.QueueLock], 0 |
jnz .disconnected |
mov [esi+usb_unit_data.DiskDevice], ebx |
call MutexUnlock |
jmp .exit |
.disconnected: |
call MutexUnlock |
stdcall disk_close, ebx |
jmp .exit |
.free_index: |
mov ecx, free_numbers_lock |
call MutexLock |
movzx eax, [esi+usb_unit_data.DiskIndex] |
bts [free_numbers], eax |
call MutexUnlock |
.drop_reference: |
mov esi, [esi+usb_unit_data.Parent] |
lock dec [esi+usb_device_data.NumReferences] |
jnz .exit |
mov eax, [esi+usb_device_data.LogicalDevices] |
call Kfree |
xchg eax, esi |
call Kfree |
.exit: |
or eax, -1 |
int 0x40 |
endp |
; This function is called when the device is disconnected. |
proc DeviceDisconnected |
push ebx esi |
virtual at esp |
rd 2 ; saved registers |
dd ? ; return address |
.device dd ? |
end virtual |
; 1. Say a message. |
mov esi, disconnectmsg |
call SysMsgBoardStr |
; 2. Lock the requests queue, set .DeviceDisconnected to 1, |
; unlock the requests queue. |
; Locking is required for synchronization with queue_request: |
; all USB callbacks are executed in the same thread and are |
; synchronized automatically, but queue_request can be running |
; from any thread which wants to do something with a filesystem. |
; Without locking, it would be possible that queue_request has |
; been started, has checked that device is not yet disconnected, |
; then DeviceDisconnected completes and all handles become invalid, |
; then queue_request tries to use them. |
mov esi, [.device] |
lea ecx, [esi+usb_device_data.QueueLock] |
call MutexLock |
mov [esi+usb_device_data.DeviceDisconnected], 1 |
call MutexUnlock |
; 3. Drop one reference to the structure and check whether |
; that was the last reference. |
lock dec [esi+usb_device_data.NumReferences] |
jz .free |
; 4. If not, there are some additional references due to disk devices; |
; notify the kernel that those disks are deleted. |
; Note that new disks cannot be added while we are looping here, |
; because new_disk_thread checks for .DeviceDisconnected. |
mov ebx, [esi+usb_device_data.MaxLUN] |
mov esi, [esi+usb_device_data.LogicalDevices] |
inc ebx |
.diskdel: |
mov eax, [esi+usb_unit_data.DiskDevice] |
test eax, eax |
jz @f |
stdcall DiskDel, eax |
@@: |
add esi, usb_unit_data.sizeof |
dec ebx |
jnz .diskdel |
; In this case, some operations with those disks are still possible, |
; so we can't do anything more now. disk_close will take care of the rest. |
.return: |
pop esi ebx |
ret 4 |
; 5. If there are no disk devices, free all resources which were allocated. |
.free: |
mov eax, [esi+usb_device_data.LogicalDevices] |
test eax, eax |
jz @f |
call Kfree |
@@: |
xchg eax, esi |
call Kfree |
jmp .return |
endp |
; Disk functions. |
DISK_STATUS_OK = 0 ; success |
DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable |
DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters |
DISK_STATUS_NO_MEDIA = 2 ; no media present |
DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data |
; Called when all operations with the given disk are done. |
proc disk_close |
push ebx esi |
virtual at esp |
rd 2 ; saved registers |
dd ? ; return address |
.userdata dd ? |
end virtual |
mov esi, [.userdata] |
mov ecx, free_numbers_lock |
call MutexLock |
movzx eax, [esi+usb_unit_data.DiskIndex] |
bts [free_numbers], eax |
call MutexUnlock |
mov esi, [esi+usb_unit_data.Parent] |
lock dec [esi+usb_device_data.NumReferences] |
jnz .nothing |
mov eax, [esi+usb_device_data.LogicalDevices] |
call Kfree |
xchg eax, esi |
call Kfree |
.nothing: |
pop esi ebx |
ret 4 |
endp |
; Returns sector size, capacity and flags of the media. |
proc disk_querymedia stdcall uses ebx esi edi, \ |
userdata:dword, mediainfo:dword |
; 1. Create event for waiting. |
xor esi, esi |
xor ecx, ecx |
call CreateEvent |
test eax, eax |
jz .generic_fail |
push eax |
push edx |
push ecx |
push 0 |
push 0 |
virtual at ebp-.localsize |
.locals: |
; two following dwords are the output of READ_CAPACITY |
.LastLBABE dd ? |
.SectorSizeBE dd ? |
.Status dd ? |
; two following dwords identify an event |
.event_code dd ? |
.event dd ? |
rd 3 ; saved registers |
.localsize = $ - .locals |
dd ? ; saved ebp |
dd ? ; return address |
.userdata dd ? |
.mediainfo dd ? |
end virtual |
; 2. Initiate SCSI READ_CAPACITY request. |
mov eax, [userdata] |
mov ecx, [eax+usb_unit_data.Parent] |
mov edx, esp |
stdcall queue_request, ecx, read_capacity_req, edx, read_capacity_callback, edx |
; 3. Wait for event. This destroys it. |
mov eax, [.event] |
mov ebx, [.event_code] |
call WaitEvent |
; 4. Get the status and results. |
pop ecx |
bswap ecx ; .LastLBA |
pop edx |
bswap edx ; .SectorSize |
pop eax ; .Status |
; 5. If the request has completed successfully, store results. |
test eax, eax |
jnz @f |
DEBUGF 1,'K : sector size is %d, last sector is %d\n',edx,ecx |
mov ebx, [mediainfo] |
mov [ebx], eax ; flags = 0 |
mov [ebx+4], edx ; sectorsize |
add ecx, 1 |
adc eax, 0 |
mov [ebx+8], ecx |
mov [ebx+12], eax ; capacity |
mov eax, [userdata] |
mov [eax+usb_unit_data.SectorSize], edx |
xor eax, eax |
@@: |
; 6. Restore the stack and return. |
pop ecx |
pop ecx |
ret |
.generic_fail: |
or eax, -1 |
ret |
endp |
; Builder for SCSI READ_CAPACITY request. |
; edx = first argument = pointer to usb_device_data.Command, |
; second argument = custom data given to queue_request, |
; pointer to disk_querymedia.locals. |
proc read_capacity_req |
mov eax, [esp+8] |
mov eax, [eax+disk_querymedia.userdata-disk_querymedia.locals] |
mov al, [eax+usb_unit_data.LUN] |
mov [edx+command_block_wrapper.Length], 8 |
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
mov [edx+command_block_wrapper.LUN], al |
mov byte [edx+command_block_wrapper.Command+0], SCSI_READ_CAPACITY |
ret 8 |
endp |
; Called when SCSI READ_CAPACITY request is completed. |
proc read_capacity_callback |
; Transform the status to return value of disk_querymedia |
; and set the event. |
mov ecx, [esp+4] |
xor eax, eax |
cmp [ecx+usb_device_data.Status.Status], al |
jz @f |
or eax, -1 |
@@: |
mov ecx, [esp+8] |
mov [ecx+disk_querymedia.Status-disk_querymedia.locals], eax |
push ebx esi edi |
mov eax, [ecx+disk_querymedia.event-disk_querymedia.locals] |
mov ebx, [ecx+disk_querymedia.event_code-disk_querymedia.locals] |
xor edx, edx |
xor esi, esi |
call RaiseEvent |
pop edi esi ebx |
ret 8 |
endp |
disk_write: |
mov al, SCSI_WRITE10 |
jmp disk_read_write |
disk_read: |
mov al, SCSI_READ10 |
; Reads from the device or writes to the device. |
proc disk_read_write stdcall uses ebx esi edi, \ |
userdata:dword, buffer:dword, startsector:qword, numsectors:dword |
; 1. Initialize. |
push eax ; .command |
mov eax, [userdata] |
mov eax, [eax+usb_unit_data.SectorSize] |
push eax ; .SectorSize |
push 0 ; .processed |
mov eax, [numsectors] |
mov eax, [eax] |
; 2. The transfer length for SCSI_{READ,WRITE}10 commands can not be greater |
; than 0xFFFF, so split the request to slices with <= 0xFFFF sectors. |
max_sectors_at_time = 0xFFFF |
.split: |
push eax ; .length_rest |
cmp eax, max_sectors_at_time |
jb @f |
mov eax, max_sectors_at_time |
@@: |
sub [esp], eax |
push eax ; .length_cur |
; 3. startsector must fit in 32 bits, otherwise abort the request. |
cmp dword [startsector+4], 0 |
jnz .generic_fail |
; 4. Create event for waiting. |
xor esi, esi |
xor ecx, ecx |
call CreateEvent |
test eax, eax |
jz .generic_fail |
push eax ; .event |
push edx ; .event_code |
push ecx ; .status |
virtual at ebp-.localsize |
.locals: |
.status dd ? |
.event_code dd ? |
.event dd ? |
.length_cur dd ? |
.length_rest dd ? |
.processed dd ? |
.SectorSize dd ? |
.command db ? |
rb 3 |
rd 3 ; saved registers |
.localsize = $ - .locals |
dd ? ; saved ebp |
dd ? ; return address |
.userdata dd ? |
.buffer dd ? |
.startsector dq ? |
.numsectors dd ? |
end virtual |
; 5. Initiate SCSI READ10 or WRITE10 request. |
mov eax, [userdata] |
mov ecx, [eax+usb_unit_data.Parent] |
stdcall queue_request, ecx, read_write_req, [buffer], read_write_callback, esp |
; 6. Wait for event. This destroys it. |
mov eax, [.event] |
mov ebx, [.event_code] |
call WaitEvent |
; 7. Get the status. If the operation has failed, abort. |
pop eax ; .status |
pop ecx ecx ; cleanup .event_code, .event |
pop ecx ; .length_cur |
test eax, eax |
jnz .return |
; 8. Otherwise, continue the loop started at step 2. |
add dword [startsector], ecx |
adc dword [startsector+4], eax |
imul ecx, [.SectorSize] |
add [buffer], ecx |
pop eax |
test eax, eax |
jnz .split |
push eax |
.return: |
; 9. Restore the stack, store .processed to [numsectors], return. |
pop ecx ; .length_rest |
pop ecx ; .processed |
mov edx, [numsectors] |
mov [edx], ecx |
pop ecx ; .SectorSize |
pop ecx ; .command |
ret |
.generic_fail: |
or eax, -1 |
pop ecx ; .length_cur |
jmp .return |
endp |
; Builder for SCSI READ10 or WRITE10 request. |
; edx = first argument = pointer to usb_device_data.Command, |
; second argument = custom data given to queue_request, |
; pointer to disk_read_write.locals. |
proc read_write_req |
mov eax, [esp+8] |
mov ecx, [eax+disk_read_write.userdata-disk_read_write.locals] |
mov cl, [ecx+usb_unit_data.LUN] |
mov [edx+command_block_wrapper.LUN], cl |
mov ecx, [eax+disk_read_write.length_cur-disk_read_write.locals] |
imul ecx, [eax+disk_read_write.SectorSize-disk_read_write.locals] |
mov [edx+command_block_wrapper.Length], ecx |
mov cl, [eax+disk_read_write.command-disk_read_write.locals] |
mov [edx+command_block_wrapper.Flags], CBW_FLAG_OUT |
cmp cl, SCSI_READ10 |
jnz @f |
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
@@: |
mov byte [edx+command_block_wrapper.Command], cl |
mov ecx, dword [eax+disk_read_write.startsector-disk_read_write.locals] |
bswap ecx |
mov dword [edx+command_block_wrapper.Command+2], ecx |
mov ecx, [eax+disk_read_write.length_cur-disk_read_write.locals] |
xchg cl, ch |
mov word [edx+command_block_wrapper.Command+7], cx |
ret 8 |
endp |
; Called when SCSI READ10 or WRITE10 request is completed. |
proc read_write_callback |
; 1. Initialize. |
push ebx esi edi |
virtual at esp |
rd 3 ; saved registers |
dd ? ; return address |
.device dd ? |
.calldata dd ? |
end virtual |
mov ecx, [.device] |
mov esi, [.calldata] |
; 2. Get the number of sectors which were read. |
; If the status is OK or FAIL, the field .LengthRest is valid. |
; Otherwise, it is invalid, so assume zero sectors. |
xor eax, eax |
cmp [ecx+usb_device_data.Status.Status], CSW_STATUS_FAIL |
ja .sectors_calculated |
mov eax, [ecx+usb_device_data.LengthRest] |
xor edx, edx |
div [esi+disk_read_write.SectorSize-disk_read_write.locals] |
test edx, edx |
jz @f |
inc eax |
@@: |
mov edx, eax |
mov eax, [esi+disk_read_write.length_cur-disk_read_write.locals] |
sub eax, edx |
jae .sectors_calculated |
xor eax, eax |
.sectors_calculated: |
; 3. Increase the total number of processed sectors. |
add [esi+disk_read_write.processed-disk_read_write.locals], eax |
; 4. Set status to OK if all sectors were read, to ERROR otherwise. |
cmp eax, [esi+disk_read_write.length_cur-disk_read_write.locals] |
setz al |
movzx eax, al |
dec eax |
mov [esi+disk_read_write.status-disk_read_write.locals], eax |
; 5. Set the event. |
mov eax, [esi+disk_read_write.event-disk_read_write.locals] |
mov ebx, [esi+disk_read_write.event_code-disk_read_write.locals] |
xor edx, edx |
xor esi, esi |
call RaiseEvent |
; 6. Return. |
pop edi esi ebx |
ret 8 |
endp |
; strings |
my_driver db 'usbstor',0 |
disconnectmsg db 'K : USB mass storage device disconnected',13,10,0 |
nomemory db 'K : no memory',13,10,0 |
unkdevice db 'K : unknown mass storage device',13,10,0 |
okdevice db 'K : USB mass storage device detected',13,10,0 |
transfererror db 'K : USB transfer error, disabling mass storage',13,10,0 |
invresponse db 'K : invalid response from mass storage device',13,10,0 |
fatalerr db 'K : mass storage device reports fatal error',13,10,0 |
inquiry_fail db 'K : INQUIRY command failed',13,10,0 |
;read_capacity_fail db 'K : READ CAPACITY command failed',13,10,0 |
;read_fail db 'K : READ command failed',13,10,0 |
noindex db 'K : failed to generate disk name',13,10,0 |
; Exported variable: kernel API version. |
align 4 |
version dd 50005h |
; Structure with callback functions. |
usb_functions: |
dd usb_functions_end - usb_functions |
dd AddDevice |
dd DeviceDisconnected |
usb_functions_end: |
disk_functions: |
dd disk_functions_end - disk_functions |
dd disk_close |
dd 0 ; closemedia |
dd disk_querymedia |
dd disk_read |
dd disk_write |
dd 0 ; flush |
dd 0 ; adjust_cache_size: use default cache |
disk_functions_end: |
free_numbers_lock rd 3 |
; 128 devices should be enough for everybody |
free_numbers dd -1, -1, -1, -1 |
; for DEBUGF macro |
include_debug_strings |
; for uninitialized data |
section '.data' data readable writable align 16 |
/kernel/branches/Kolibri-acpi/gui/event.inc |
---|
516,7 → 516,7 |
btr ecx, eax ; сбрасываем проверяемый бит маски |
; переходим на обработчик этого (eax) бита |
cmp eax, 10 |
jae .loop ; eax=[10..31], ignored (event 10...32) |
jae .loop ; eax=[10..31], ignored (event 11...32) |
cmp eax, 3 |
je .loop ; eax=3, ignored (event 4) |
/kernel/branches/Kolibri-acpi/gui/skincode.inc |
---|
17,21 → 17,16 |
stdcall load_file, ebx |
test eax, eax |
jz .notfound |
cmp dword [eax], 'SKIN' |
jnz .noskin |
cmp ebx, 32*1024 |
jb @f |
mov ebx, 32*1024 |
;-------------------------------------- |
align 4 |
xchg eax, [skin_data] |
test eax, eax |
jz @f |
stdcall kernel_free, eax |
@@: |
lea ecx, [ebx+3] |
shr ecx, 2 |
mov esi, eax |
mov edi, skin_data |
rep movsd |
stdcall kernel_free, eax |
call parse_skin_data |
xor eax, eax |
ret |
45,8 → 40,7 |
align 4 |
.noskin: |
stdcall kernel_free, eax |
push 2 |
pop eax |
mov eax, 2 |
ret |
;------------------------------------------------------------------------------ |
struct SKIN_HEADER |
98,7 → 92,7 |
;------------------------------------------------------------------------------ |
align 4 |
parse_skin_data: |
mov ebp, skin_data |
mov ebp, [skin_data] |
cmp [ebp+SKIN_HEADER.ident], 'SKIN' |
jne .exit |
109,7 → 103,7 |
rep stosd |
mov ebx, [ebp+SKIN_HEADER.params] |
add ebx, skin_data |
add ebx, [skin_data] |
mov eax, [ebx+SKIN_PARAMS.skin_height] |
mov [_skinh], eax |
mov eax, [ebx+SKIN_PARAMS.colors.inner] |
135,7 → 129,7 |
mov dword[_skinmargins+4], eax |
mov ebx, [ebp+SKIN_HEADER.bitmaps] |
add ebx, skin_data |
add ebx, [skin_data] |
;-------------------------------------- |
align 4 |
.lp1: |
160,7 → 154,7 |
dec eax |
jnz .not_oper |
mov esi, [ebx+SKIN_BITMAPS.data] |
add esi, skin_data |
add esi, [skin_data] |
mov eax, [esi+0] |
neg eax |
mov edx, skin_active.oper.data |
195,7 → 189,7 |
align 4 |
.next_bitmap: |
mov ecx, [ebx+SKIN_BITMAPS.data] |
add ecx, skin_data |
add ecx, [skin_data] |
mov [edx+4], eax |
mov eax, [ecx+0] |
mov [edx+8], eax |
207,7 → 201,7 |
align 4 |
.end_bitmaps: |
mov ebx, [ebp+SKIN_HEADER.buttons] |
add ebx, skin_data |
add ebx, [skin_data] |
;-------------------------------------- |
align 4 |
.lp2: |
396,7 → 390,8 |
;-------------------------------------- |
align 4 |
@@: |
cmp dword[skin_data], 'SKIN' |
mov eax, [skin_data] |
cmp [eax], dword 'SKIN' |
je @f |
xor eax, eax |
xor ebx, ebx |
438,7 → 433,8 |
;-------------------------------------- |
align 4 |
_noinside2: |
cmp dword[skin_data], 'SKIN' |
mov eax, [skin_data] |
cmp [eax], dword 'SKIN' |
jne no_skin_add_button |
;* close button |
mov edi, [BTN_ADDR] |
/kernel/branches/Kolibri-acpi/gui/window.inc |
---|
1024,6 → 1024,8 |
; no it's not, just activate the window |
call window._.window_activate |
xor eax, eax |
ret |
;-------------------------------------- |
align 4 |
.exit: |
/kernel/branches/Kolibri-acpi/kernel.asm |
---|
77,7 → 77,7 |
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices |
; Enabling the next line will enable serial output console |
debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used |
;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used |
; The following constant, if nonzero, duplicates debug output to the screen. |
debug_direct_print equ 0 |
163,35 → 163,6 |
include "bus/pci/pci16.inc" |
include "detect/biosdisk.inc" |
FDD_BUFF equ (OS_BASE+0x000D000) |
sys_pgdir equ (OS_BASE+0x006F000) |
VGABasePtr equ (OS_BASE+0x00A0000) |
RAMDISK equ (OS_BASE+0x0100000) |
CLEAN_ZONE equ 0x284000 |
IDE_DMA equ 0x284000 |
BOOT_VAR equ (OS_BASE+0x02E0000) |
TASK_COUNT equ (CURRENT_TASK+0x04) |
TASK_BASE equ (CURRENT_TASK+0x10) |
TASK_DATA equ (CURRENT_TASK+0x20) |
TASK_EVENT equ (CURRENT_TASK+0x20) |
BPSLine_calc_area equ (OS_BASE+0x02C4000) |
d_width_calc_area equ (OS_BASE+0x02CA000) |
stack_data_start equ (OS_BASE+0x02F0000) |
eth_data_start equ (OS_BASE+0x02F0000) |
stack_data equ (OS_BASE+0x02F4000) |
stack_data_end equ (OS_BASE+0x030ffff) |
resendQ equ (OS_BASE+0x0310000) |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SWITCH TO 32 BIT PROTECTED MODE ;; |
434,15 → 405,17 |
dec eax |
mov [Screen_Max_Y], eax |
mov [screen_workarea.bottom], eax |
mov ax, word [BOOT_VAR+BOOT_VESA_MODE] ; screen mode |
mov [SCR_MODE], ax |
mov [BytesPerScanLine], 640*4 ; Bytes PerScanLine |
cmp [SCR_MODE], 0x13 ; 320x200 |
movzx eax, word [BOOT_VAR+BOOT_VESA_MODE]; screen mode |
mov [SCR_MODE], eax |
; mov eax, [BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add |
; mov [BANK_SWITCH], eax |
mov [BytesPerScanLine], word 640*4 ; Bytes PerScanLine |
cmp [SCR_MODE], word 0x13 ; 320x200 |
je @f |
cmp [SCR_MODE], 0x12 ; VGA 640x480 |
cmp [SCR_MODE], word 0x12 ; VGA 640x480 |
je @f |
movzx eax, word[BOOT_VAR+BOOT_PITCH] ; for other modes |
mov [BytesPerScanLine], eax |
mov [BytesPerScanLine], ax |
mov [_display.pitch], eax |
@@: |
mov eax, [_display.width] |
1268,6 → 1241,7 |
xor eax, eax |
mov [BTN_ADDR], dword BUTTON_INFO ; address of button list |
mov byte [MOUSE_BUFF_COUNT], al ; mouse buffer |
mov byte [KEY_COUNT], al ; keyboard buffer |
mov byte [BTN_COUNT], al ; button buffer |
; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y |
4995,7 → 4969,7 |
.1: ; resolution |
mov eax, [Screen_Max_X] |
shl eax, 16 |
mov ax, word [Screen_Max_Y] |
mov ax, [Screen_Max_Y] |
add eax, 0x00010001 |
mov [esp+32], eax |
ret |
5094,9 → 5068,9 |
align 4 |
syscall_getscreensize: ; GetScreenSize |
mov eax, [Screen_Max_X] |
mov ax, [Screen_Max_X] |
shl eax, 16 |
mov ax, word [Screen_Max_Y] |
mov ax, [Screen_Max_Y] |
mov [esp + 32], eax |
ret |
/kernel/branches/Kolibri-acpi/network/eth_drv/pci.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/ethernet.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/arp.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/sis900.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8169.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/r6040.inc |
---|
File deleted |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/3c59x.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/pcnet32.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/forcedeth.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8029.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/i8255x.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8139.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers |
---|
Property changes: |
Deleted: svn:ignore |
-*.mnt |
-lang.inc |
-*.bat |
-out.txt |
-scin* |
-*.obj |
/kernel/branches/Kolibri-acpi/network/eth_drv |
---|
Property changes: |
Deleted: svn:ignore |
-*.mnt |
-lang.inc |
-*.bat |
-out.txt |
-scin* |
-*.obj |
/kernel/branches/Kolibri-acpi/network/ip.inc |
---|
File deleted |
Property changes: |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/branches/Kolibri-acpi/network/ARP.inc |
---|
177,7 → 177,7 |
inc [ARP_PACKETS_RX + 4*edi] ; update stats |
DEBUGF 1,"ARP_input: got packet from %u.%u.%u.%u through device %u\n",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: got packet from %u.%u.%u.%u through device %u\n",\ |
[edx + ARP_header.SenderIP]:1, [edx + ARP_header.SenderIP + 1]:1,\ |
[edx + ARP_header.SenderIP + 2]:1, [edx + ARP_header.SenderIP + 3]:1, edi |
194,7 → 194,7 |
cmp [edx + ARP_header.Opcode], ARP_REP_OPCODE |
jne .maybe_request |
DEBUGF 1,"ARP_input: It's a reply\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: It's a reply\n" |
mov ecx, [NumARP] |
test ecx, ecx |
208,16 → 208,16 |
dec ecx |
jnz .loop |
DEBUGF 1,"ARP_input: no matching entry found\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: no matching entry found\n" |
jmp .exit |
.gotit: |
DEBUGF 1,"ARP_input: found matching entry\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: found matching entry\n" |
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY ; if it is a static entry, dont touch it |
je .exit |
DEBUGF 1,"ARP_input: updating entry\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: updating entry\n" |
mov [esi + ARP_entry.Status], ARP_VALID_MAPPING |
mov [esi + ARP_entry.TTL], ARP_ENTRY_TTL |
236,7 → 236,7 |
cmp [edx + ARP_header.Opcode], ARP_REQ_OPCODE |
jne .exit |
DEBUGF 1,"ARP_input: its a request\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: its a request\n" |
mov eax, [IP_LIST + 4*edi] |
cmp eax, [edx + ARP_header.TargetIP] ; Is it looking for my IP address? |
277,7 → 277,7 |
; mov ax , ETHER_ARP ; It's already there, I'm sure of it! |
; stosw |
DEBUGF 1,"ARP_input: Sending reply\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: Sending reply\n" |
call [ebx + NET_DEVICE.transmit] |
ret |
284,13 → 284,13 |
.collision: |
inc [ARP_CONFLICTS + 4*edi] |
DEBUGF 1,"ARP_input: IP address conflict detected!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: IP address conflict detected!\n" |
.exit: |
call kernel_free |
add esp, 4 ; pop (balance stack) |
DEBUGF 1,"ARP_input: exiting\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: exiting\n" |
ret |
310,7 → 310,7 |
pushd [IP_LIST + edi] ; SenderIP |
inc [ARP_PACKETS_TX + edi] ; assume we will succeed |
DEBUGF 1,"ARP_output_request: ip=%u.%u.%u.%u\n",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: ip=%u.%u.%u.%u\n",\ |
[esp + 4]:1, [esp + 5]:1, [esp + 6]:1, [esp + 7]:1 |
mov ebx, [NET_DRV_LIST + edi] ; device ptr |
344,7 → 344,7 |
pop eax ; DestIP |
stosd ; |
DEBUGF 1,"ARP_output_request: device=%x\n", ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: device=%x\n", ebx |
push edx ecx |
call [ebx + NET_DEVICE.transmit] |
352,7 → 352,7 |
.exit: |
add esp, 4 + 4 |
DEBUGF 1,"ARP_output_request: failed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: failed\n" |
sub eax, eax |
ret |
369,7 → 369,7 |
align 4 |
ARP_add_entry: |
DEBUGF 1,"ARP_add_entry: " |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_add_entry: " |
mov ecx, [NumARP] |
cmp ecx, ARP_TABLE_SIZE ; list full ? |
400,12 → 400,12 |
rep movsw |
inc [NumARP] |
sub edi, sizeof.ARP_entry |
DEBUGF 1,"entry=%u\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "entry=%u\n", eax |
ret |
.error: |
DEBUGF 1,"failed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "failed\n" |
mov eax, -1 |
ret |
421,8 → 421,8 |
align 4 |
ARP_del_entry: |
DEBUGF 1,"ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP] |
DEBUGF 1,"ARP_del_entry: IP=%u.%u.%u.%u\n", \ |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP] |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: IP=%u.%u.%u.%u\n", \ |
[esi + ARP_entry.IP]:1, [esi + ARP_entry.IP + 1]:1, [esi + ARP_entry.IP + 2]:1, [esi + ARP_entry.IP + 3]:1 |
mov ecx, ARP_table + (ARP_TABLE_SIZE - 1) * sizeof.ARP_entry |
438,7 → 438,7 |
rep stosw |
dec [NumARP] |
DEBUGF 1,"ARP_del_entry: success\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: success\n" |
ret |
463,9 → 463,9 |
align 4 |
ARP_IP_to_MAC: |
DEBUGF 1,"ARP_IP_to_MAC: %u.%u", al, ah |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: %u.%u", al, ah |
rol eax, 16 |
DEBUGF 1,".%u.%u\n", al, ah |
DEBUGF DEBUG_NETWORK_VERBOSE, ".%u.%u\n", al, ah |
rol eax, 16 |
cmp eax, 0xffffffff |
485,7 → 485,7 |
loop .scan_loop |
.not_in_list: |
DEBUGF 1,"ARP_IP_to_MAC: preparing for ARP request\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: preparing for ARP request\n" |
;-------------------- |
; Send an ARP request |
535,16 → 535,16 |
end if |
.valid: |
DEBUGF 1,"ARP_IP_to_MAC: found MAC\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: found MAC\n" |
movzx eax, word[esi + ARP_entry.MAC] |
mov ebx, dword[esi + ARP_entry.MAC + 2] |
ret |
.full: |
DEBUGF 1,"ARP_IP_to_MAC: table is full!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: table is full!\n" |
add esp, 8 |
.give_up: |
DEBUGF 1,"ARP_IP_to_MAC: entry has no valid mapping!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: entry has no valid mapping!\n" |
mov eax, -1 |
ret |
/kernel/branches/Kolibri-acpi/network/IPv4.inc |
---|
112,7 → 112,7 |
jmp .done |
.died: |
DEBUGF 2,"IPv4 Fragment slot timed-out!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4 Fragment slot timed-out!\n" |
;;; TODO: clear all entry's of timed-out slot |
jmp .next |
205,10 → 205,10 |
align 4 |
IPv4_input: ; TODO: add IPv4 raw sockets support |
DEBUGF 2,"IPv4_input, packet from: %u.%u.%u.%u ",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input, packet from: %u.%u.%u.%u ",\ |
[edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\ |
[edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1 |
DEBUGF 2,"to: %u.%u.%u.%u\n",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "to: %u.%u.%u.%u\n",\ |
[edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\ |
[edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1 |
218,7 → 218,7 |
IPv4_checksum edx |
jnz .dump ; if checksum isn't valid then dump packet |
DEBUGF 1,"IPv4_input: Checksum ok\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n" |
;----------------------------------- |
; Check if destination IP is correct |
256,7 → 256,7 |
; or it's just not meant for us.. :( |
DEBUGF 2,"IPv4_input: Destination address does not match!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n" |
jmp .dump |
;------------------------ |
300,10 → 300,10 |
cmp al, IP_PROTO_ICMP |
je ICMP_input |
DEBUGF 2,"IPv4_input: unknown protocol %u\n", al |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al |
.dump: |
DEBUGF 1,"IPv4_input: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n" |
inc [IP_packets_dumped] ; FIXME: use correct interface |
call kernel_free |
add esp, 4 ; pop (balance stack) |
319,7 → 319,7 |
xchg al, ah |
shl ax, 3 |
DEBUGF 1,"IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4 |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4 |
test ax, ax ; Is this the first packet of the fragment? |
jz .is_first_fragment |
328,7 → 328,7 |
;------------------------------------------------------- |
; We have a fragmented IP packet, but it's not the first |
DEBUGF 1,"IPv4_input: Middle fragment packet received!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n" |
call IPv4_find_fragment_slot |
cmp esi, -1 |
361,7 → 361,7 |
; We have received the first fragment |
.is_first_fragment: |
DEBUGF 1,"IPv4_input: First fragment packet received!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n" |
; try to locate a free slot.. |
mov ecx, MAX_FRAGMENTS |
mov esi, FRAGMENT_LIST |
395,7 → 395,7 |
; We have received the last fragment |
.is_last_fragment: |
DEBUGF 1,"IPv4_input: Last fragment packet received!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n" |
call IPv4_find_fragment_slot |
cmp esi, -1 |
411,12 → 411,12 |
jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!) |
mov cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Add total length |
xchg cl, ch |
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx |
add ax, cx |
movzx cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Sub Header length |
and cx, 0x000F |
shl cx, 2 |
DEBUGF 1,"IPv4_input: Header size=%u\n", cx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx |
sub ax, cx |
mov edi, esi |
mov esi, [esi + FRAGMENT_entry.NextPtr] |
431,9 → 431,9 |
mov cx, [edx + IPv4_header.TotalLength] ; Note: This time we dont substract Header length |
xchg cl, ch |
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx |
add ax, cx |
DEBUGF 1,"IPv4_input: Total Received data size=%u\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax |
push eax |
mov ax, [edx + IPv4_header.FlagsAndFragmentOffset] |
441,7 → 441,7 |
shl ax, 3 |
add cx, ax |
pop eax |
DEBUGF 1,"IPv4_input: Total Fragment size=%u\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx |
cmp ax, cx |
jne .destroy_slot_pop |
457,7 → 457,7 |
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset |
xchg cl, ch ; intel byte order |
shl cx, 3 ; multiply by 8 and clear first 3 bits |
DEBUGF 1,"IPv4_input: Fragment offset=%u\n", cx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx |
lea edi, [eax + ecx] ; Notice that edi will be equal to eax for first fragment |
movzx ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Find header size (in ebx) of fragment |
504,7 → 504,7 |
.destroy_slot_pop: |
add esp, 4 |
.destroy_slot: |
DEBUGF 1,"IPv4_input: Destroy fragment slot!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n" |
; TODO! |
jmp .dump |
568,7 → 568,7 |
align 4 |
IPv4_output: |
DEBUGF 1,"IPv4_output: size=%u\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u\n", ecx |
cmp ecx, 65500 ; Max IPv4 packet size |
ja .too_large |
614,23 → 614,23 |
IPv4_checksum edi |
add edi, sizeof.IPv4_header |
DEBUGF 2,"IPv4_output: success!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n" |
ret |
.eth_error: |
DEBUGF 2,"IPv4_output: ethernet error\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: ethernet error\n" |
add esp, 3*4+2+6 |
xor edi, edi |
ret |
.arp_error: |
DEBUGF 2,"IPv4_output: ARP error=%x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: ARP error=%x\n", eax |
add esp, 3*4+2 |
xor edi, edi |
ret |
.too_large: |
DEBUGF 2,"IPv4_output: Packet too large!\n" |
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n" |
xor edi, edi |
ret |
713,7 → 713,7 |
IPv4_checksum edi ;;;; todo: checksum for IP packet with options! |
add edi, sizeof.IPv4_header |
DEBUGF 2,"IPv4_output_raw: device=%x\n", ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx |
call [ebx + NET_DEVICE.transmit] |
ret |
722,7 → 722,7 |
.arp_error: |
add esp, 8+4+4 |
.too_large: |
DEBUGF 2,"IPv4_output_raw: Failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n" |
sub edi, edi |
ret |
742,7 → 742,7 |
align 4 |
IPv4_fragment: |
DEBUGF 1,"IPv4_fragment\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n" |
and ecx, not 111b ; align 4 |
770,7 → 770,7 |
push dword 0 ; offset |
.new_fragment: |
DEBUGF 1,"Ipv4_fragment: new fragment" |
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment" |
mov eax, [esp + 3*4] |
792,7 → 792,7 |
add esi, [esp] ; offset |
mov ecx, [esp + 1*4] |
DEBUGF 1,"IPv4_fragment: copying %u bytes\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx |
rep movsb |
; now, correct header |
829,7 → 829,7 |
sub ecx, [esp+2*4] ; ptr to ip header |
add ecx, [esp] ; offset |
DEBUGF 1,"Ipv4_fragment: %u bytes remaining\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx |
cmp ecx, [esp+1*4] |
jae .new_fragment |
838,11 → 838,11 |
jmp .new_fragment |
.err: |
DEBUGF 1,"Ipv4_fragment: failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n" |
.done: |
add esp, 12 + 4 + 6 |
.err2: |
DEBUGF 1,"Ipv4_fragment: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n" |
call kernel_free |
add esp, 4 |
886,7 → 886,7 |
mov eax, [GATEWAY_LIST] |
.found_it: |
DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi |
ret |
.broadcast: |
/kernel/branches/Kolibri-acpi/network/IPv6.inc |
---|
83,7 → 83,7 |
align 4 |
IPv6_input: |
DEBUGF 2,"IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\ |
[edx + IPv6_header.SourceAddress + 0]:2,[edx + IPv6_header.SourceAddress + 1]:2,\ |
[edx + IPv6_header.SourceAddress + 2]:2,[edx + IPv6_header.SourceAddress + 3]:2,\ |
[edx + IPv6_header.SourceAddress + 4]:2,[edx + IPv6_header.SourceAddress + 5]:2,\ |
93,7 → 93,7 |
[edx + IPv6_header.SourceAddress + 12]:2,[edx + IPv6_header.SourceAddress + 13]:2,\ |
[edx + IPv6_header.SourceAddress + 14]:2,[edx + IPv6_header.SourceAddress + 15]:2 |
DEBUGF 1,"IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\ |
[edx + IPv6_header.DestinationAddress + 0]:2,[edx + IPv6_header.DestinationAddress + 1]:2,\ |
[edx + IPv6_header.DestinationAddress + 2]:2,[edx + IPv6_header.DestinationAddress + 3]:2,\ |
[edx + IPv6_header.DestinationAddress + 4]:2,[edx + IPv6_header.DestinationAddress + 5]:2,\ |
143,10 → 143,10 |
; cmp al, 58 |
; je ICMP6_input |
DEBUGF 2,"IPv6_input - unknown protocol: %u\n", al |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - unknown protocol: %u\n", al |
.dump: |
DEBUGF 1,"IPv6_input - dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - dumping\n" |
call kernel_free |
add esp, 4 |
166,7 → 166,7 |
; Hop-by-Hop |
.hop_by_hop: |
DEBUGF 1,"IPv6_input - hop by hop\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - hop by hop\n" |
pushw [esi] ; 8 bit identifier for option type |
movzx eax, byte[esi + 1] ; Hdr Ext Len |
inc eax ; first 8 octets not counted |
195,7 → 195,7 |
.pad_n: |
movzx eax, byte[esi + 1] |
DEBUGF 1,"IPv6_input - pad %u\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - pad %u\n", eax |
inc esi |
inc esi |
add esi, eax |
203,7 → 203,7 |
jmp .hop_by_hop |
.pad_1: |
DEBUGF 1,"IPv6_input - pad 1\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - pad 1\n" |
inc esi |
dec ecx |
jmp .hop_by_hop |
211,11 → 211,11 |
.dest_opts: |
DEBUGF 1,"IPv6_input - dest opts\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - dest opts\n" |
jmp .nextheader |
.routing: |
DEBUGF 1,"IPv6_input - routing\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - routing\n" |
pushw [esi] ; 8 bit identifier for option type |
movzx eax, byte[esi + 1] ; Hdr Ext Len |
inc eax ; first 8 octets not counted |
238,7 → 238,7 |
jmp .nextheader |
.fragment: |
DEBUGF 1,"IPv6_input - fragment\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - fragment\n" |
jmp .nextheader |
/kernel/branches/Kolibri-acpi/network/PPPoE.inc |
---|
59,7 → 59,7 |
align 4 |
PPPoE_discovery_input: |
DEBUGF 2,"PPPoE_discovery_input\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_input\n" |
; First, find open PPPoE socket |
84,7 → 84,7 |
jmp SOCKET_input |
.dump: |
DEBUGF 1,'PPPoE_discovery_input: dumping\n' |
DEBUGF DEBUG_NETWORK_VERBOSE, 'PPPoE_discovery_input: dumping\n' |
call kernel_free |
add esp, 4 |
ret |
103,7 → 103,7 |
align 4 |
PPPoE_discovery_output: |
DEBUGF 2,"PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx |
; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT |
; exceed 1484 octets. |
123,7 → 123,7 |
cmp [ebx + NET_DEVICE.type], NET_TYPE_ETH |
jne .bad |
DEBUGF 2,"PPPoE_discovery_output: device=%x\n", ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: device=%x\n", ebx |
; Create packet. |
push ecx esi |
193,7 → 193,7 |
xchg cl, ch |
mov ax, [edx + PPPoE_frame.SessionID] |
DEBUGF 2,"PPPoE_input: session ID=%x, length=%u\n", ax, cx |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: session ID=%x, length=%u\n", ax, cx |
cmp ax, [PPPoE_SID] |
jne .dump |
207,10 → 207,10 |
; je IPv6_input |
jmp PPPoE_discovery_input ; Send LCP,CHAP,CBCP,... packets to the PPP dialer |
DEBUGF 2,"PPPoE_input: Unknown protocol=%x\n", ax |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: Unknown protocol=%x\n", ax |
.dump: |
DEBUGF 2,"PPPoE_input: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: dumping\n" |
call kernel_free |
add esp, 4 |
ret |
238,7 → 238,7 |
align 4 |
PPPoE_output: |
DEBUGF 1,"PPPoE_output: size=%u device=%x\n", ecx, ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: size=%u device=%x\n", ecx, ebx |
pushw di |
pushw [PPPoE_SID] |
263,7 → 263,7 |
sub ecx, 2 |
add edi, PPPoE_frame.Payload + 2 |
DEBUGF 1,"PPPoE_output: success!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: success!\n" |
ret |
276,7 → 276,7 |
PPPoE_start_connection: |
DEBUGF 2,"PPPoE_start_connection: %x\n", cx |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_start_connection: %x\n", cx |
cmp [PPPoE_SID], 0 |
jne .fail |
296,7 → 296,7 |
align 4 |
PPPoE_stop_connection: |
DEBUGF 2,"PPPoE_stop_connection\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_stop_connection\n" |
xor eax, eax |
mov [PPPoE_SID], ax |
/kernel/branches/Kolibri-acpi/network/ethernet.inc |
---|
56,7 → 56,7 |
mov eax, [esp] |
mov ecx, [esp+4] |
DEBUGF 1,"ETH_input: size=%u\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE,"ETH_input: size=%u\n", ecx |
cmp ecx, ETH_FRAME_MINIMUM |
jb .dump |
sub ecx, sizeof.ETH_header |
79,10 → 79,10 |
cmp ax, ETHER_PPP_SESSION |
je PPPoE_session_input |
DEBUGF 2,"ETH_input: Unknown packet type=%x\n", ax |
DEBUGF DEBUG_NETWORK_ERROR, "ETH_input: Unknown packet type=%x\n", ax |
.dump: |
DEBUGF 2,"ETH_input: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE,"ETH_input: dumping\n" |
call kernel_free |
add esp, 4 |
ret |
107,7 → 107,7 |
align 4 |
ETH_output: |
DEBUGF 1,"ETH_output: size=%u device=%x\n", ecx, ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx |
cmp ecx, [ebx + NET_DEVICE.mtu] |
ja .exit |
137,7 → 137,7 |
cmp edx, ETH_FRAME_MINIMUM |
jbe .adjust_size |
.done: |
DEBUGF 1,"ETH_output: ptr=%x size=%u\n", eax, edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: ptr=%x size=%u\n", eax, edx |
ret |
.adjust_size: |
146,13 → 146,13 |
jmp .done |
.out_of_ram: |
DEBUGF 2,"ETH_output: Out of ram!\n" |
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Out of ram!\n" |
add esp, 4+4+2+4 |
sub edi, edi |
ret |
.exit: |
DEBUGF 2,"ETH_output: Packet too large!\n" |
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Packet too large!\n" |
sub edi, edi |
ret |
/kernel/branches/Kolibri-acpi/network/icmp.inc |
---|
142,7 → 142,7 |
align 4 |
ICMP_input: |
DEBUGF 1,"ICMP_input:\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input:\n" |
; First, check the checksum (altough some implementations ignore it) |
163,7 → 163,7 |
; We well re-use the packet so we can create the response as fast as possible |
; Notice: this only works on pure ethernet |
DEBUGF 1,"got echo request\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "got echo request\n" |
mov [edx + ICMP_header.Type], ICMP_ECHOREPLY ; Change Packet type to reply |
mov esi, [esp] ; Start of buffer |
258,7 → 258,7 |
; je .dump |
; inc [ICMP_PACKETS_RX+edi] |
DEBUGF 1,"socket=%x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax |
pusha |
lea ecx, [eax + SOCKET.mutex] |
270,10 → 270,10 |
.checksum_mismatch: |
DEBUGF 1,"checksum mismatch\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "checksum mismatch\n" |
.dump: |
DEBUGF 1,"ICMP_input: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n" |
call kernel_free |
add esp, 4 ; pop (balance stack) |
297,7 → 297,7 |
align 4 |
ICMP_output: |
DEBUGF 1,"Creating ICMP Packet\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n" |
push esi edi dx |
308,7 → 308,7 |
call IPv4_output |
jz .exit |
DEBUGF 1,"full icmp packet size: %u\n", edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx |
pop word [edi + ICMP_header.Type] ; Write both type and code bytes at once |
pop dword [edi + ICMP_header.Identifier] ; identifier and sequence number |
333,11 → 333,11 |
sub edi, edx ;;; TODO: find a better way to remember start of packet |
push edx edi |
DEBUGF 1,"Sending ICMP Packet\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n" |
call [ebx + NET_DEVICE.transmit] |
ret |
.exit: |
DEBUGF 1,"Creating ICMP Packet failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n" |
add esp, 2*4 + 2 |
ret |
356,7 → 356,7 |
align 4 |
ICMP_output_raw: |
DEBUGF 1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx |
push edx |
371,7 → 371,7 |
push eax |
push edi ecx |
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi |
rep movsb |
pop ecx edi |
383,11 → 383,11 |
call checksum_2 |
mov [edi + ICMP_header.Checksum], dx |
DEBUGF 1,"Sending ICMP Packet\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n" |
call [ebx + NET_DEVICE.transmit] |
ret |
.exit: |
DEBUGF 1,"Creating ICMP Packet failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n" |
add esp, 4 |
ret |
/kernel/branches/Kolibri-acpi/network/loopback.inc |
---|
59,7 → 59,7 |
push ecx |
push eax |
DEBUGF 1,"LOOP_input: size=%u\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: size=%u\n", ecx |
lea edx, [eax + 2] |
mov ax, word[eax] |
mov ebx, LOOPBACK_DEVICE |
67,10 → 67,10 |
cmp ax, ETHER_IPv4 |
je IPv4_input |
DEBUGF 2,"LOOP_input: Unknown packet type=%x\n", ax |
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: Unknown packet type=%x\n", ax |
.dump: |
DEBUGF 2,"LOOP_input: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: dumping\n" |
call kernel_free |
add esp, 4 |
ret |
93,7 → 93,7 |
align 4 |
LOOP_output: |
DEBUGF 1,"LOOP_output\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output\n" |
push ecx |
push di |
114,11 → 114,11 |
mov ebx, LOOPBACK_DEVICE |
.done: |
DEBUGF 2,"LOOP_output: ptr=%x size=%u\n", eax, edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output: ptr=%x size=%u\n", eax, edx |
ret |
.out_of_ram: |
DEBUGF 2,"LOOP_output: failed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output: failed\n" |
add esp, 2+4 |
sub edi, edi |
ret |
/kernel/branches/Kolibri-acpi/network/socket.inc |
---|
263,7 → 263,7 |
.number = ($ - .table) / 4 - 1 |
s_error: |
DEBUGF 2,"SOCKET: error\n" |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET: error\n" |
mov dword [esp+32], -1 |
ret |
281,7 → 281,7 |
align 4 |
SOCKET_open: |
DEBUGF 2,"SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi |
push ecx edx esi |
call SOCKET_alloc |
289,7 → 289,7 |
jz s_error |
mov [esp+32], edi ; return socketnumber |
DEBUGF 2,"socknum=%u\n", edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi |
; push edx |
; and edx, SO_NONBLOCK |
321,7 → 321,7 |
je .pppoe |
.no_ppp: |
DEBUGF 2,"Unknown socket family/protocol\n" |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_open: Unknown socket family/protocol\n" |
ret |
align 4 |
394,7 → 394,7 |
align 4 |
SOCKET_bind: |
DEBUGF 2,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
call SOCKET_num_to_ptr |
jz s_error |
444,7 → 444,7 |
call SOCKET_check_port |
jz s_error ; ZF is set by socket_check_port, on error |
DEBUGF 1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\ |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\ |
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\ |
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1 |
467,7 → 467,7 |
align 4 |
SOCKET_connect: |
DEBUGF 2,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
call SOCKET_num_to_ptr |
jz s_error |
616,7 → 616,7 |
align 4 |
SOCKET_listen: |
DEBUGF 2,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx |
call SOCKET_num_to_ptr |
jz s_error |
668,7 → 668,7 |
align 4 |
SOCKET_accept: |
DEBUGF 2,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
call SOCKET_num_to_ptr |
jz s_error |
718,7 → 718,7 |
align 4 |
SOCKET_close: |
DEBUGF 2,"SOCKET_close: socknum=%u\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx |
call SOCKET_num_to_ptr |
jz s_error |
767,18 → 767,21 |
align 4 |
SOCKET_receive: |
DEBUGF 2,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi |
call SOCKET_num_to_ptr |
jz s_error |
jmp [eax + SOCKET.rcv_proc] |
call [eax + SOCKET.rcv_proc] |
mov [esp+32], eax |
ret |
align 4 |
SOCKET_receive_dgram: |
DEBUGF 1,"SOCKET_receive: DGRAM\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n" |
mov ebx, esi |
mov edi, edx ; addr to buffer |
787,15 → 790,15 |
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block ; destroys esi and ecx |
mov ecx, [esi + socket_queue_entry.data_size] |
DEBUGF 1,"SOCKET_receive: %u bytes data\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx |
cmp ecx, ebx |
ja .too_small |
push ecx |
push [esi + socket_queue_entry.buf_ptr] ; save the buffer addr so we can clear it later |
mov esi, [esi + socket_queue_entry.data_ptr] |
DEBUGF 1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi |
mov [esp+32+4], ecx ; return number of bytes copied |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi |
; copy the data |
shr ecx, 1 |
812,16 → 815,20 |
.nd: |
call kernel_free ; remove the packet |
pop eax |
ret |
.too_small: |
DEBUGF 2,"SOCKET_receive: Buffer too small\n" |
jmp s_error |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Buffer too small\n" |
.fail: |
mov eax, -1 |
ret |
.block: |
test [eax + SOCKET.options], SO_NONBLOCK |
jnz s_error |
jnz .fail |
call SOCKET_block |
jmp .loop |
846,7 → 853,7 |
align 4 |
SOCKET_receive_stream: |
DEBUGF 1,"SOCKET_receive: STREAM\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n" |
mov ebx, edi |
mov ecx, esi |
866,12 → 873,11 |
call SOCKET_ring_read |
call SOCKET_ring_free |
mov [esp+32], ecx ; return number of bytes copied |
mov eax, ecx ; return number of bytes copied |
ret |
.peek: |
mov ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size] |
mov [esp+32], ecx ; return number of bytes available |
mov eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size] |
ret |
.block: |
882,11 → 888,18 |
jmp .loop |
.return0: |
xor ecx, ecx |
mov [esp+32], ecx |
test [eax + SOCKET.options], SS_CANTRCVMORE |
jz .ok |
xor eax, eax |
dec eax |
ret |
.ok: |
xor eax, eax |
ret |
;----------------------------------------------------------------- |
; |
; SOCKET_send |
902,7 → 915,7 |
align 4 |
SOCKET_send: |
DEBUGF 2,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi |
call SOCKET_num_to_ptr |
jz s_error |
916,7 → 929,7 |
align 4 |
SOCKET_send_udp: |
DEBUGF 1,"SOCKET_send: UDP\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n" |
mov [esp+32], ecx |
call UDP_output |
928,7 → 941,7 |
align 4 |
SOCKET_send_tcp: |
DEBUGF 1,"SOCKET_send: TCP\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n" |
push eax |
add eax, STREAM_SOCKET.snd |
944,7 → 957,7 |
align 4 |
SOCKET_send_ip: |
DEBUGF 1,"SOCKET_send: IPv4\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n" |
mov [esp+32], ecx |
call IPv4_output_raw |
956,7 → 969,7 |
align 4 |
SOCKET_send_icmp: |
DEBUGF 1,"SOCKET_send: ICMP\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n" |
mov [esp+32], ecx |
call ICMP_output_raw |
968,7 → 981,7 |
align 4 |
SOCKET_send_pppoe: |
DEBUGF 1,"SOCKET_send: PPPoE\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n" |
mov [esp+32], ecx |
mov ebx, [eax + SOCKET.device] |
998,7 → 1011,7 |
align 4 |
SOCKET_send_local_: |
DEBUGF 1,"SOCKET_send: LOCAL\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n" |
; get the other side's socket and check if it still exists |
mov eax, [eax + SOCKET.device] |
1037,7 → 1050,7 |
align 4 |
SOCKET_get_opt: |
DEBUGF 2,"SOCKET_get_opt\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n" |
call SOCKET_num_to_ptr |
jz s_error |
1087,7 → 1100,7 |
align 4 |
SOCKET_set_opt: |
DEBUGF 2,"SOCKET_set_opt\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n" |
call SOCKET_num_to_ptr |
jz s_error |
1116,7 → 1129,7 |
jz s_error |
mov [eax + SOCKET.device], edx |
DEBUGF 1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx |
mov dword [esp+32], 0 ; success! |
ret |
1158,7 → 1171,7 |
align 4 |
SOCKET_pair: |
DEBUGF 2,"SOCKET_pair\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n" |
call SOCKET_alloc |
jz s_error |
1217,7 → 1230,7 |
align 4 |
SOCKET_debug: |
DEBUGF 1,"SOCKET_debug\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n" |
mov edi, edx |
1266,7 → 1279,7 |
align 4 |
SOCKET_find_port: |
DEBUGF 2,"SOCKET_find_port\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n" |
push ebx esi ecx |
1327,7 → 1340,7 |
align 4 |
SOCKET_check_port: |
DEBUGF 2,"SOCKET_check_port: " |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: " |
mov ecx, [eax + SOCKET.Protocol] |
mov edx, [eax + IP_SOCKET.LocalIP] |
1347,11 → 1360,11 |
cmp [esi + UDP_SOCKET.LocalPort], bx |
jne .next_socket |
DEBUGF 2,"local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf |
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf |
ret |
.port_ok: |
DEBUGF 2,"local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf |
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf |
mov [eax + UDP_SOCKET.LocalPort], bx |
or bx, bx ; clear the zero-flag |
ret |
1378,7 → 1391,7 |
align 4 |
SOCKET_input: |
DEBUGF 2,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx |
mov [esp+4], ecx |
push esi |
1386,7 → 1399,7 |
add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full |
DEBUGF 1,"SOCKET_input: success\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n" |
add esp, sizeof.socket_queue_entry |
pusha |
1397,7 → 1410,7 |
jmp SOCKET_notify |
.full: |
DEBUGF 2,"SOCKET_input: socket %x is full!\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax |
pusha |
lea ecx, [eax + SOCKET.mutex] |
1424,7 → 1437,7 |
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW |
pop edx |
DEBUGF 1,"SOCKET_ring_created: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax |
pusha |
lea ecx, [esi + RING_BUFFER.mutex] |
1458,7 → 1471,7 |
align 4 |
SOCKET_ring_write: |
DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx |
; lock mutex |
pusha |
1474,7 → 1487,7 |
mov ecx, edi |
.copy: |
mov edi, [eax + RING_BUFFER.write_ptr] |
DEBUGF 2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi |
; update write ptr |
push edi |
1532,7 → 1545,7 |
align 4 |
SOCKET_ring_read: |
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx |
pusha |
lea ecx, [eax + RING_BUFFER.mutex] |
1555,7 → 1568,7 |
ja .less_data |
.copy: |
DEBUGF 2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi |
push ecx |
shr ecx, 1 |
jnc .nb |
1578,7 → 1591,7 |
call mutex_unlock ; TODO: check what registers this function actually destroys |
popa |
DEBUGF 1,"SOCKET_ring_read: no data at all!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n" |
xor ecx, ecx |
ret |
1602,7 → 1615,7 |
align 4 |
SOCKET_ring_free: |
DEBUGF 1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax |
push eax ecx |
lea ecx, [eax + RING_BUFFER.mutex] |
1627,7 → 1640,7 |
ret |
.error: ; we could free all available bytes, but that would be stupid, i guess.. |
DEBUGF 1,"SOCKET_ring_free: buffer=%x error!\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax |
add [eax + RING_BUFFER.size], ecx |
push eax |
1652,7 → 1665,7 |
align 4 |
SOCKET_block: |
DEBUGF 1,"SOCKET_block: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax |
pushf |
cli |
1667,7 → 1680,7 |
; Remember the thread ID so we can wake it up again |
mov edx, [edx + TASKDATA.pid] |
DEBUGF 1,"SOCKET_block: suspending thread: %u\n", edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx |
mov [eax + SOCKET.TID], edx |
pop edx |
1674,7 → 1687,7 |
call change_task |
popf |
DEBUGF 1,"SOCKET_block: continueing\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n" |
ret |
1692,7 → 1705,7 |
align 4 |
SOCKET_notify: |
DEBUGF 1,"SOCKET_notify: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax |
call SOCKET_check |
jz .error |
1728,7 → 1741,7 |
shl ecx, 8 |
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK |
DEBUGF 1,"SOCKET_notify: Raised a network event!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Raised a network event!\n" |
jmp .done |
1756,7 → 1769,7 |
; Run the thread |
mov [esi + TASKDATA.state], 0 ; Running |
DEBUGF 1,"SOCKET_notify: Unblocked socket!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n" |
.done: |
pop esi ecx eax |
1785,7 → 1798,7 |
push ebx |
stdcall kernel_alloc, SOCKETBUFFSIZE |
DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax |
or eax, eax |
jz .exit |
1821,7 → 1834,7 |
.last_socket: |
mov [last_socket_num], edi |
mov [eax + SOCKET.Number], edi |
DEBUGF 1, "SOCKET_alloc: number=%u\n", edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi |
; Fill in PID |
mov ebx, [TASK_BASE] |
1878,7 → 1891,7 |
align 4 |
SOCKET_free: |
DEBUGF 1, "SOCKET_free: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax |
call SOCKET_check |
jz .error |
1906,7 → 1919,7 |
mov ebx, [eax + SOCKET.NextPtr] |
mov eax, [eax + SOCKET.PrevPtr] |
DEBUGF 1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx |
test eax, eax |
jz @f |
1921,7 → 1934,7 |
call kernel_free |
pop ebx |
DEBUGF 1, "SOCKET_free: success!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n" |
.error: |
ret |
1939,7 → 1952,7 |
align 4 |
SOCKET_fork: |
DEBUGF 1,"SOCKET_fork: %x\n", ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx |
; Exit if backlog queue is full |
mov eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size] |
1971,7 → 1984,7 |
.fail2: |
add esp, 4+4+4 |
.fail: |
DEBUGF 1,"SOCKET_fork: failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n" |
xor eax, eax |
ret |
1990,7 → 2003,7 |
align 4 |
SOCKET_num_to_ptr: |
DEBUGF 1,"SOCKET_num_to_ptr: num=%u ", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx |
mov eax, net_sockets |
2003,11 → 2016,11 |
test eax, eax |
DEBUGF 1,"ptr=%x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax |
ret |
.error: |
DEBUGF 1,"not found\n", eax |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_nuto_ptr: not found\n", eax |
ret |
2025,7 → 2038,7 |
align 4 |
SOCKET_ptr_to_num: |
DEBUGF 1,"SOCKET_ptr_to_num: ptr=%x ", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax |
call SOCKET_check |
jz .error |
2032,11 → 2045,11 |
mov eax, [eax + SOCKET.Number] |
DEBUGF 1,"num=%u\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "num=%u\n", eax |
ret |
.error: |
DEBUGF 1,"not found\n", eax |
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax |
ret |
2054,7 → 2067,7 |
align 4 |
SOCKET_check: |
DEBUGF 1,"SOCKET_check: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax |
push ebx |
mov ebx, net_sockets |
2088,7 → 2101,7 |
align 4 |
SOCKET_check_owner: |
DEBUGF 1,"SOCKET_check_owner: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax |
push ebx |
mov ebx, [TASK_BASE] |
2116,7 → 2129,7 |
align 4 |
SOCKET_process_end: |
DEBUGF 1, "SOCKET_process_end: %x\n", edx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx |
push ebx |
mov ebx, net_sockets |
2130,7 → 2143,7 |
cmp [ebx + SOCKET.PID], edx |
jne .next_socket |
DEBUGF 1, "SOCKET_process_end: killing socket %x\n", ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx |
mov [ebx + SOCKET.PID], 0 |
mov eax, ebx |
2160,7 → 2173,7 |
align 4 |
SOCKET_is_connecting: |
DEBUGF 1,"SOCKET_is_connecting: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax |
and [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING) |
or [eax + SOCKET.options], SS_ISCONNECTING |
2181,7 → 2194,7 |
align 4 |
SOCKET_is_connected: |
DEBUGF 1,"SOCKET_is_connected: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax |
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING) |
or [eax + SOCKET.options], SS_ISCONNECTED |
2203,7 → 2216,7 |
align 4 |
SOCKET_is_disconnecting: |
DEBUGF 1,"SOCKET_is_disconnecting: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax |
and [eax + SOCKET.options], not (SS_ISCONNECTING) |
or [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE |
2224,7 → 2237,7 |
align 4 |
SOCKET_is_disconnected: |
DEBUGF 1,"SOCKET_is_disconnected: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax |
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING) |
or [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE |
2257,10 → 2270,12 |
align 4 |
SOCKET_cant_recv_more: |
DEBUGF 1,"SOCKET_cant_recv_more: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax |
or [eax + SOCKET.options], SS_CANTRCVMORE |
call SOCKET_notify |
ret |
2277,8 → 2292,11 |
align 4 |
SOCKET_cant_send_more: |
DEBUGF 1,"SOCKET_cant_send_more: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax |
or [eax + SOCKET.options], SS_CANTSENDMORE |
mov [eax + SOCKET.snd_proc], s_error |
call SOCKET_notify |
ret |
/kernel/branches/Kolibri-acpi/network/stack.inc |
---|
28,6 → 28,9 |
net_tmr_count dw ? |
endg |
DEBUG_NETWORK_ERROR = 1 |
DEBUG_NETWORK_VERBOSE = 0 |
MAX_NET_DEVICES = 16 |
ARP_BLOCK = 1 ; true or false |
305,12 → 308,12 |
align 4 |
NET_link_changed: |
DEBUGF 1,"NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state] |
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state] |
align 4 |
NET_send_event: |
DEBUGF 1,"NET_send_event\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_send_event\n" |
; Send event to all applications |
push edi ecx |
340,7 → 343,7 |
align 4 |
NET_add_device: |
DEBUGF 1,"NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list |
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list |
cmp [NET_RUNNING], MAX_NET_DEVICES |
jae .error |
384,12 → 387,12 |
call NET_send_event |
DEBUGF 1,"Device number: %u\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "Device number: %u\n", eax |
ret |
.error: |
or eax, -1 |
DEBUGF 2,"Adding network device failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "Adding network device failed\n" |
ret |
407,7 → 410,7 |
align 4 |
NET_set_default: |
DEBUGF 1,"NET_set_default: device=%x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_set_default: device=%x\n", eax |
cmp eax, MAX_NET_DEVICES |
jae .error |
417,12 → 420,12 |
mov [NET_DEFAULT], eax |
DEBUGF 1,"NET_set_default: succes\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_set_default: succes\n" |
ret |
.error: |
or eax, -1 |
DEBUGF 1,"NET_set_default: failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "NET_set_default: failed\n" |
ret |
634,7 → 637,7 |
.not_zero: |
xchg dl, dh |
DEBUGF 1,"Checksum: %x\n", dx |
DEBUGF DEBUG_NETWORK_VERBOSE, "Checksum: %x\n", dx |
ret |
/kernel/branches/Kolibri-acpi/network/tcp_input.inc |
---|
60,7 → 60,7 |
.fail: |
popf |
DEBUGF 2, "TCP incoming queue is full, discarding packet!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n" |
inc [TCP_segments_missed] ; FIXME: use correct interface |
97,7 → 97,7 |
mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address |
mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last |
DEBUGF 1,"TCP_input: size=%u time=%d\n", ecx, [timer_ticks] |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks] |
mov edx, esi |
127,7 → 127,7 |
movzx eax, [edx + TCP_header.DataOffset] |
sub ecx, eax ; substract TCP header size from total segment size |
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet |
DEBUGF 1,"TCP_input: %u bytes of data\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx |
;------------------------------------------- |
; Convert Big-endian values to little endian |
176,7 → 176,7 |
test ax, ax |
jnz .socket_loop |
.found_socket: ; ebx now contains the socketpointer |
DEBUGF 1,"TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2 |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2 |
;------------- |
; update stats |
197,7 → 197,7 |
call mutex_lock |
popa |
DEBUGF 1,"TCP_input: socket locked\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n" |
;--------------------------- |
; disable all temporary bits |
220,7 → 220,7 |
test [ebx + SOCKET.options], SO_ACCEPTCON |
jz .no_accept |
DEBUGF 1,"TCP_input: Accepting new connection\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n" |
pusha |
lea ecx, [ebx + SOCKET.mutex] |
263,7 → 263,7 |
cmp ecx, sizeof.TCP_header ; Does header contain any options? |
je .no_options |
DEBUGF 1,"TCP_input: Segment has options\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n" |
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS |
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state |
290,7 → 290,7 |
; je .opt_sack |
cmp al, TCP_OPT_TIMESTAMP |
je .opt_timestamp |
DEBUGF 1,"TCP_input: unknown option:%u\n", al |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al |
jmp .no_options ; If we reach here, some unknown options were received, skip them all! |
.opt_maxseg: |
303,7 → 303,7 |
lodsw |
rol ax, 8 |
DEBUGF 1,"TCP_input: Maxseg=%u\n", ax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", ax |
call TCP_mss |
@@: |
jmp .opt_loop |
317,7 → 317,7 |
test [edx + TCP_header.Flags], TH_SYN |
jz @f |
DEBUGF 1,"TCP_input: Got window scale option\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n" |
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE |
lodsb |
336,7 → 336,7 |
test [edx + TCP_header.Flags], TH_SYN |
jz @f |
DEBUGF 1,"TCP_input: Selective Acknowledgement permitted\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n" |
or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT |
@@: |
348,7 → 348,7 |
cmp al, 10 ; length must be 10 |
jne .no_options |
DEBUGF 1,"TCP_input: Got timestamp option\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n" |
test [edx + TCP_header.Flags], TH_SYN |
jz @f |
372,7 → 372,7 |
cmp eax, [ebx + TCP_SOCKET.ts_val] |
jge .no_paws |
DEBUGF 1,"TCP_input: PAWS: detected an old segment\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n" |
mov eax, [esp+4+4] ; tcp_now |
sub eax, [ebx + TCP_SOCKET.ts_recent_age] |
450,7 → 450,7 |
sub eax, [ebx + TCP_SOCKET.SND_UNA] |
jbe .not_uni_xfer |
DEBUGF 1,"TCP_input: Header prediction: we are sender\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n" |
;--------------------------------- |
; Packet is a pure ACK, process it |
524,7 → 524,7 |
; Complete processing of received data |
DEBUGF 1,"TCP_input: Header prediction: we are receiving %u bytes\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx |
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
545,7 → 545,7 |
.not_uni_xfer: |
DEBUGF 1,"TCP_input: Header prediction failed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n" |
; Calculate receive window size |
558,7 → 558,7 |
jg @f |
mov eax, edx |
@@: |
DEBUGF 1,"Receive window size=%d\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax |
mov [ebx + TCP_SOCKET.RCV_WND], eax |
pop edx |
579,12 → 579,12 |
sub eax, [edx + TCP_header.SequenceNumber] |
jle .no_duplicate |
DEBUGF 1,"TCP_input: %u bytes duplicate data!\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax |
test [edx + TCP_header.Flags], TH_SYN |
jz .no_dup_syn |
DEBUGF 1,"TCP_input: got duplicate syn\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n" |
and [edx + TCP_header.Flags], not (TH_SYN) |
inc [edx + TCP_header.SequenceNumber] |
613,7 → 613,7 |
; send an ACK and resynchronize and drop any data. |
; But keep on processing for RST or ACK |
DEBUGF 1, "616\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "616\n" |
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
mov eax, ecx |
;TODO: update stats |
658,7 → 658,7 |
sub eax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop |
jle .no_excess_data |
DEBUGF 1,"%d bytes beyond right edge of window\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax |
;;; TODO: update stats |
cmp eax, ecx |
687,7 → 687,7 |
cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
jne .drop_after_ack |
DEBUGF 1, "690\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "690\n" |
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
;;; TODO: update stats |
jmp .no_excess_data |
715,7 → 715,7 |
sub eax, ecx |
jae .no_timestamp |
DEBUGF 1,"Recording timestamp\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "Recording timestamp\n" |
mov eax, [esp + 4] ; tcp_now |
mov [ebx + TCP_SOCKET.ts_recent_age], eax |
729,7 → 729,7 |
test [edx + TCP_header.Flags], TH_RST |
jz .no_rst |
DEBUGF 1,"TCP_input: Got an RST flag\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n" |
mov eax, [ebx + TCP_SOCKET.t_state] |
shl eax, 2 |
749,18 → 749,18 |
dd .rst_close ; TCPS_TIMED_WAIT |
.econnrefused: |
DEBUGF 1,"TCP_input: Connection refused\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n" |
mov [ebx + SOCKET.errorcode], ECONNREFUSED |
jmp .close |
.econnreset: |
DEBUGF 1,"TCP_input: Connection reset\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n" |
mov [ebx + SOCKET.errorcode], ECONNRESET |
.close: |
DEBUGF 1,"TCP_input: Closing connection\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n" |
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED |
;;; TODO: update stats (tcp drops) |
769,7 → 769,7 |
jmp .drop_no_socket |
.rst_close: |
DEBUGF 1,"TCP_input: Closing with reset\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n" |
mov eax, ebx |
call TCP_close |
799,7 → 799,7 |
jb .ack_processed ; states: closed, listen, syn_sent |
ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait |
DEBUGF 1,"TCP_input: state=syn_received\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n" |
mov eax, [edx + TCP_header.AckNumber] |
cmp [ebx + TCP_SOCKET.SND_UNA], eax |
846,7 → 846,7 |
cmp eax, [ebx + TCP_SOCKET.SND_WND] |
jne .reset_dupacks |
DEBUGF 1,"TCP_input: Processing duplicate ACK\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n" |
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK |
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them, |
927,7 → 927,7 |
.no_re_xmit: |
jbe .not_dup_ack |
DEBUGF 1,"TCP_input: Increasing congestion window\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n" |
mov eax, [ebx + TCP_SOCKET.t_maxseg] |
add [ebx + TCP_SOCKET.SND_CWND], eax |
980,7 → 980,7 |
;;; TODO: update stats |
DEBUGF 1,"TCP_input: acceptable ACK for %u bytes\n", edi |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi |
;------------------------------------------ |
; RTT measurements and retransmission timer (912-926) |
1073,7 → 1073,7 |
call SOCKET_ring_free |
pop ebx edx ecx |
DEBUGF 1,"TCP_input: our FIN is acked\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n" |
stc |
jmp .wakeup |
1088,7 → 1088,7 |
sub [ebx + TCP_SOCKET.SND_WND], ecx |
pop edx ecx |
DEBUGF 1,"TCP_input: our FIN is not acked\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n" |
clc |
;---------------------------------------- |
1176,7 → 1176,7 |
align 4 |
.LISTEN: |
DEBUGF 1,"TCP_input: state=listen\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n" |
test [edx + TCP_header.Flags], TH_RST |
jnz .drop |
1228,7 → 1228,7 |
align 4 |
.SYN_SENT: |
DEBUGF 1,"TCP_input: state=syn_sent\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n" |
test [edx + TCP_header.Flags], TH_ACK |
jz @f |
1288,7 → 1288,7 |
test [edx + TCP_header.Flags], TH_ACK |
jz .simultaneous_open |
DEBUGF 1,"TCP_input: active open\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n" |
;;; TODO: update stats |
1316,7 → 1316,7 |
.simultaneous_open: |
DEBUGF 1,"TCP_input: simultaneous open\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n" |
; We have received a syn but no ACK, so we are having a simultaneous open.. |
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
1339,7 → 1339,7 |
.ack_processed: |
DEBUGF 1,"TCP_input: ACK processed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n" |
;---------------------------------------------- |
; check if we need to update window information |
1373,7 → 1373,7 |
@@: |
mov [ebx + TCP_SOCKET.SND_WND], eax |
DEBUGF 1,"TCP_input: Updating window to %u\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax |
push [edx + TCP_header.SequenceNumber] |
pop [ebx + TCP_SOCKET.SND_WL1] |
1467,7 → 1467,7 |
call TCP_reassemble |
DEBUGF 1, "1470\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "1470\n" |
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
.data_done: |
1478,12 → 1478,12 |
test [edx + TCP_header.Flags], TH_FIN |
jz .final_processing |
DEBUGF 1,"TCP_input: Processing FIN\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n" |
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
jae .not_first_fin |
DEBUGF 1,"TCP_input: First FIN for this connection\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n" |
mov eax, ebx |
call SOCKET_cant_recv_more |
1534,7 → 1534,7 |
.drop_after_ack: |
DEBUGF 1,"TCP_input: Drop after ACK\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n" |
push edx ebx |
lea ecx, [ebx + SOCKET.mutex] |
1548,7 → 1548,7 |
jmp .need_output |
.drop_with_reset: |
DEBUGF 1,"TCP_input: Drop with reset\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n" |
push ebx edx |
lea ecx, [ebx + SOCKET.mutex] |
1571,7 → 1571,7 |
; Final processing |
.final_processing: |
DEBUGF 1,"TCP_input: Final processing\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n" |
push ebx |
lea ecx, [ebx + SOCKET.mutex] |
1583,14 → 1583,14 |
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
jz .dumpit |
DEBUGF 1,"TCP_input: ACK now!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n" |
.need_output: |
DEBUGF 1,"TCP_input: need output\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n" |
call TCP_output |
.dumpit: |
DEBUGF 1,"TCP_input: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n" |
call kernel_free |
add esp, 4 |
1641,7 → 1641,7 |
; Drop |
.drop: |
DEBUGF 1,"TCP_input: Dropping segment\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n" |
pusha |
lea ecx, [ebx + SOCKET.mutex] |
1656,7 → 1656,7 |
call SOCKET_free |
.drop_no_socket: |
DEBUGF 1,"TCP_input: Drop (no socket)\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n" |
call kernel_free |
add esp, 4 |
/kernel/branches/Kolibri-acpi/network/tcp_output.inc |
---|
28,7 → 28,7 |
align 4 |
TCP_output: |
DEBUGF 1,"TCP_output: socket=%x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket=%x\n", eax |
push eax |
lea ecx, [eax + SOCKET.mutex] |
78,7 → 78,7 |
cmp [eax + TCP_SOCKET.t_force], 0 |
je .no_force |
DEBUGF 1,"TCP_output: forcing data out\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: forcing data out\n" |
test ecx, ecx |
jnz .no_zero_window |
202,7 → 202,7 |
;---------------------------------------- |
; Check if a window update should be sent (154) |
DEBUGF 1,"TCP_output: window=%d\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: window=%d\n", ecx |
; Compare available window to amount of window known to peer (as advertised window less next expected input) |
; If the difference is at least two max size segments, or at least 50% of the maximum possible window, |
237,7 → 237,7 |
;-------------------------- |
; Should a segment be sent? (174) |
DEBUGF 1,"TCP_output: 174\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: 174\n" |
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK |
jnz TCP_send |
273,7 → 273,7 |
cmp [eax + TCP_SOCKET.timer_persist], 0 ; Persist timer already expired? |
jne @f |
DEBUGF 1,"TCP_output: Entering persist state\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: Entering persist state\n" |
mov [eax + TCP_SOCKET.t_rxtshift], 0 |
call TCP_set_persist |
282,7 → 282,7 |
;---------------------------- |
; No reason to send a segment (219) |
DEBUGF 1,"TCP_output: No reason to send a segment\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: No reason to send a segment\n" |
pusha |
lea ecx, [eax + SOCKET.mutex] |
313,7 → 313,7 |
align 4 |
TCP_send: |
DEBUGF 1,"TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl |
push eax ; save socket ptr |
push esi ; and data length too |
337,7 → 337,7 |
push ecx |
add di, 4 |
DEBUGF 1,"TCP_send: added maxseg option\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added maxseg option\n" |
test [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE |
jz .no_scale |
355,7 → 355,7 |
pushw TCP_OPT_WINDOW + 3 shl 8 |
add di, 4 |
DEBUGF 1,"TCP_send: added scale option\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added scale option\n" |
.no_scale: |
.no_syn: |
381,7 → 381,7 |
pushd TCP_OPT_NOP + TCP_OPT_NOP shl 8 + TCP_OPT_TIMESTAMP shl 16 + 10 shl 24 |
add di, 12 |
DEBUGF 1,"TCP_send: added timestamp\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added timestamp\n" |
.no_timestamp: |
538,7 → 538,7 |
;---------------- |
; Send the packet |
DEBUGF 1,"TCP_send: Sending with device %x\n", ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: Sending with device %x\n", ebx |
call [ebx + NET_DEVICE.transmit] |
jnz .send_error |
580,7 → 580,7 |
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT |
jnz TCP_output.again |
DEBUGF 1,"TCP_send: success!\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: success!\n" |
xor eax, eax |
ret |
597,7 → 597,7 |
lea ecx, [eax + SOCKET.mutex] |
call mutex_unlock |
DEBUGF 1,"TCP_send: IP error\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: IP error\n" |
or eax, -1 |
ret |
609,7 → 609,7 |
lea ecx, [eax + SOCKET.mutex] |
call mutex_unlock |
DEBUGF 1,"TCP_send: sending failed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: sending failed\n" |
or eax, -2 |
ret |
/kernel/branches/Kolibri-acpi/network/tcp_subr.inc |
---|
119,7 → 119,7 |
align 4 |
TCP_pull_out_of_band: |
DEBUGF 1,"TCP_pull_out_of_band\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_pull_out_of_band\n" |
;;;; 1282-1305 |
145,7 → 145,7 |
align 4 |
TCP_drop: |
DEBUGF 1,"TCP_drop: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_drop: %x\n", eax |
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
jb .no_syn_received |
184,7 → 184,7 |
align 4 |
TCP_close: |
DEBUGF 1,"TCP_close: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax |
;;; TODO: update RTT and mean deviation |
;;; TODO: update slow start threshold |
212,7 → 212,7 |
mov edx, [eax + TCP_SOCKET.t_state] |
movzx edx, byte [edx + .flaglist] |
DEBUGF 1,"TCP_outflags: socket=%x flags=%x\n", eax, dl |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl |
ret |
248,7 → 248,7 |
align 4 |
TCP_respond: |
DEBUGF 1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl |
;--------------------- |
; Create the IP packet |
305,7 → 305,7 |
ret |
.error: |
DEBUGF 1,"TCP_respond_socket: failed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n" |
add esp, 2 + 4 |
ret |
327,7 → 327,7 |
align 4 |
TCP_respond_segment: |
DEBUGF 1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl |
DEBUGF DEBUG_NETWORK_VERBOSE,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl |
;--------------------- |
; Create the IP packet |
381,7 → 381,7 |
ret |
.error: |
DEBUGF 1,"TCP_respond_segment: failed\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n" |
add esp, 2+4 |
ret |
416,7 → 416,7 |
align 4 |
TCP_set_persist: |
DEBUGF 1,"TCP_set_persist\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n" |
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive |
454,7 → 454,7 |
align 4 |
TCP_xmit_timer: |
DEBUGF 1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax |
;TODO: update stats |
/kernel/branches/Kolibri-acpi/network/tcp_timer.inc |
---|
87,7 → 87,7 |
dec [eax + TCP_SOCKET.timer_retransmission] |
jnz .check_more2 |
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Retransmission timer expired\n", eax |
push eax |
call TCP_output |
97,7 → 97,7 |
dec [eax + TCP_SOCKET.timer_keepalive] |
jnz .check_more3 |
DEBUGF 1,"socket %x: Keepalive expired\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax |
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED |
ja .dont_kill |
126,13 → 126,13 |
dec [eax + TCP_SOCKET.timer_timed_wait] |
jnz .check_more5 |
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: 2MSL timer expired\n", eax |
.check_more5: |
dec [eax + TCP_SOCKET.timer_persist] |
jnz .loop |
DEBUGF 1,"socket %x: persist timer expired\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: persist timer expired\n", eax |
call TCP_set_persist |
mov [eax + TCP_SOCKET.t_force], 1 |
/kernel/branches/Kolibri-acpi/network/tcp_usreq.inc |
---|
27,7 → 27,7 |
align 4 |
TCP_usrclosed: |
DEBUGF 1,"TCP_usrclosed: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_usrclosed: %x\n", eax |
push ebx |
mov ebx, [eax + TCP_SOCKET.t_state] |
87,7 → 87,7 |
align 4 |
TCP_disconnect: |
DEBUGF 1,"TCP_disconnect: %x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax |
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
jb TCP_close |
/kernel/branches/Kolibri-acpi/network/udp.inc |
---|
116,7 → 116,7 |
align 4 |
UDP_input: |
DEBUGF 1,"UDP_input: size=%u\n", ecx |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx |
; First validate, checksum |
129,7 → 129,7 |
jnz .checksum_mismatch |
.no_checksum: |
DEBUGF 1,"UDP_input: checksum ok\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n" |
; Convert length to little endian |
158,7 → 158,7 |
cmp [eax + UDP_SOCKET.LocalPort], dx |
jne .next_socket |
DEBUGF 1,"UDP_input: socket=%x\n", eax |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax |
;;; TODO: when packet is processed, check more sockets! |
196,7 → 196,7 |
call mutex_lock |
popa |
DEBUGF 1,"UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf |
mov [eax + UDP_SOCKET.RemotePort], cx |
inc [eax + UDP_SOCKET.firstpacket] |
204,12 → 204,12 |
.checksum_mismatch: |
DEBUGF 2,"UDP_input: checksum mismatch\n" |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n" |
.dump: |
call kernel_free |
add esp, 4 ; pop (balance stack) |
DEBUGF 2,"UDP_input: dumping\n" |
DEBUGF DEBUG_NETWORK_VERBOSE,"UDP_input: dumping\n" |
ret |
229,13 → 229,13 |
align 4 |
UDP_output: |
DEBUGF 1,"UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi |
mov dx, [eax + UDP_SOCKET.RemotePort] |
DEBUGF 1,"UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf |
rol edx, 16 |
mov dx, [eax + UDP_SOCKET.LocalPort] |
DEBUGF 1,"local port=%x\n", dx |
DEBUGF DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx |
sub esp, 8 ; Data ptr and data size will be placed here |
push edx esi |
270,7 → 270,7 |
mov [edi + UDP_header.Checksum], 0 |
UDP_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options.. |
DEBUGF 1,"UDP_output: sending with device %x\n", ebx |
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx |
call [ebx + NET_DEVICE.transmit] |
test eax, eax |
jnz @f |
280,7 → 280,7 |
ret |
.fail: |
DEBUGF 1,"UDP_output: failed\n" |
DEBUGF DEBUG_NETWORK_ERROR, "UDP_output: failed\n" |
add esp, 4+4+8 |
or eax, -1 |
ret |