Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef1eceaa6c | ||
|
|
3f3770fc57 | ||
|
|
9fe9b676c1 | ||
|
|
3110deedd5 | ||
|
|
0486f294ce |
No files matched your search
+1
-2
@@ -421,7 +421,6 @@ tup.append_table(img_files, {
|
||||
{"CALENDAR", VAR_PROGS .. "/system/calendar/calendar"},
|
||||
{"COLRDIAL", VAR_PROGS .. "/system/colrdial/color_dialog"},
|
||||
{"CROPFLAT", VAR_PROGS .. "/system/cropflat/cropflat"},
|
||||
{"CPU", VAR_PROGS .. "/system/cpu/cpu"},
|
||||
{"CPUID", VAR_PROGS .. "/testing/cpuid/CPUID"},
|
||||
{"DOCPACK", VAR_PROGS .. "/system/docpack/docpack"},
|
||||
{"DEFAULT.SKN", VAR_SKINS .. "/../skins/Leency/Shkvorka/Shkvorka.skn"},
|
||||
@@ -446,6 +445,7 @@ tup.append_table(img_files, {
|
||||
{"SCRSHOOT", VAR_PROGS .. "/media/scrshoot/scrshoot"},
|
||||
{"SETUP", VAR_PROGS .. "/system/setup/setup"},
|
||||
{"SKINCFG", VAR_PROGS .. "/system/skincfg/skincfg"},
|
||||
{"TASKMAN", VAR_PROGS .. "/system/taskman/taskman"},
|
||||
{"TERMINAL", VAR_PROGS .. "/system/terminal/terminal"},
|
||||
{"TEST", VAR_PROGS .. "/testing/protection/test"},
|
||||
{"TINYPAD", VAR_PROGS .. "/develop/tinypad/tinypad"},
|
||||
@@ -694,7 +694,6 @@ tup.append_table(img_files, {
|
||||
{"BBENCH", VAR_PROGS .. "/cmm/bbench/bbench.com"},
|
||||
{"SEARCH", VAR_PROGS .. "/cmm/misc/search.com"},
|
||||
{"SYSPANEL", VAR_PROGS .. "/cmm/misc/software_widget.com"},
|
||||
{"SYSMON", VAR_PROGS .. "/cmm/sysmon/sysmon.com"},
|
||||
{"TMPDISK", VAR_PROGS .. "/cmm/tmpdisk/tmpdisk.com"},
|
||||
{"DEVELOP/CLIPVIEW", VAR_PROGS .. "/cmm/clipview/clipview.com"},
|
||||
{"DEVELOP/MENU", VAR_PROGS .. "/cmm/menu/menu.com"},
|
||||
|
||||
@@ -1 +1 @@
|
||||
[@]
location=3
fsize=0
ashow=1
[AppPlus]
path=/sys/app_plus
param=
icon=27
$=1
[KFAR]
path=/sys/file managers/kfar
param=
icon=16
[Pixie2]
path=/sys/media/pixie
param=
icon=65
[IconEdit]
path=/sys/media/iconedit
param=
icon=98
[Calc]
path=/sys/calc
param=
icon=4
[Notes]
path=/kolibrios/utils/notes
param=
icon=117
[Dictionary]
path=/kolibrios/utils/dicty.kex
param=
icon=79
[FB2Read]
path=/sys/fb2read
param=
icon=44
[Animage]
path=/sys/media/animage
param=
icon=15
[RDSave]
path=/sys/rdsave
param=
icon=17
$=1
[Volume]
path=/sys/@volume
param=
icon=64
[NetStatus]
path=/sys/network/netstat
param=
icon=33
[SysMon]
path=/sys/sysmon
param=
icon=57
[SysPanel]
path=/sys/syspanel
param=
icon=6
|
||||
[@]
location=3
fsize=0
ashow=1
[AppPlus]
path=/sys/app_plus
param=
icon=27
$=1
[KFAR]
path=/sys/file managers/kfar
param=
icon=16
[Pixie2]
path=/sys/media/pixie
param=
icon=65
[IconEdit]
path=/sys/media/iconedit
param=
icon=98
[Calc]
path=/sys/calc
param=
icon=4
[Notes]
path=/kolibrios/utils/notes
param=
icon=117
[Dictionary]
path=/kolibrios/utils/dicty.kex
param=
icon=79
[FB2Read]
path=/sys/fb2read
param=
icon=44
[Animage]
path=/sys/media/animage
param=
icon=15
[RDSave]
path=/sys/rdsave
param=
icon=17
$=1
[Volume]
path=/sys/@volume
param=
icon=64
[NetStatus]
path=/sys/network/netstat
param=
icon=33
[TaskMan]
path=/sys/taskman
param=
icon=57
[SysPanel]
path=/sys/syspanel
param=
icon=6
|
||||
@@ -1 +1 @@
|
||||
[rbmenu]
Диспетчер процессов=/sys/cpu
Настройка внешнего вида=/kolibrios/utils/appearance
;Настройка цветов=/sys/skincfg
;Сплошной фон=/sys/media/palitra
[01]
name=FILES
path=/sys/File Managers/EOLITE
param=
ico=7
x=4
y=21
[02]
name=FPLAY
path=/kolibrios/media/fplay
param=
ico=96
x=65
y=21
[03]
name=GAMES
path=/sys/allgames
param=
ico=35
x=125
y=21
[04]
name=TINYPAD
path=/sys/tinypad
param=
ico=9
x=4
y=96
[05]
name=zSEA
path=/kolibrios/media/zsea/zsea
param=
ico=46
x=65
y=96
[06]
name=WEBVIEW
path=/sys/network/webview
param=
ico=31
x=125
y=96
; =========
; RIGHT TOP
; =========
[10]
name=DEBUG
path=/SYS/DEVELOP/MTDBG
param=
ico=39
x=-204
y=21
[11]
name=BOARD
path=/SYS/DEVELOP/BOARD
param=
ico=19
x=-140
y=21
[12]
name=KPACK
path=/SYS/KPACK
param=
ico=99
x=-77
y=21
[13]
name=DIFF
path=/sys/develop/diff
param=
ico=84
x=-203
y=96
[14]
name=FASM
path=/SYS/DEVELOP/FASM
param=
ico=10
x=-141
y=96
[15]
name=DOCPACK
path=/sys/network/webview
param=/kolibrios/res/guide/guide.htm
ico=8
x=-76
y=96
[16]
name=SHELL
path=/SYS/SHELL
param=
ico=1
x=-203
y=166
[17]
name=HEXEDIT
path=/SYS/DEVELOP/HEED
param=
ico=22
x=-141
y=166
[18]
name=CEDIT
path=/sys/develop/cedit
param=
ico=58
x=-74
y=166
|
||||
[rbmenu]
Диспетчер задач=/sys/taskman
Настройка внешнего вида=/kolibrios/utils/appearance
;Настройка цветов=/sys/skincfg
;Сплошной фон=/sys/media/palitra
[01]
name=FILES
path=/sys/File Managers/EOLITE
param=
ico=7
x=4
y=21
[02]
name=FPLAY
path=/kolibrios/media/fplay
param=
ico=96
x=65
y=21
[03]
name=GAMES
path=/sys/allgames
param=
ico=35
x=125
y=21
[04]
name=TINYPAD
path=/sys/tinypad
param=
ico=9
x=4
y=96
[05]
name=zSEA
path=/kolibrios/media/zsea/zsea
param=
ico=46
x=65
y=96
[06]
name=WEBVIEW
path=/sys/network/webview
param=
ico=31
x=125
y=96
; =========
; RIGHT TOP
; =========
[10]
name=DEBUG
path=/SYS/DEVELOP/MTDBG
param=
ico=39
x=-204
y=21
[11]
name=BOARD
path=/SYS/DEVELOP/BOARD
param=
ico=19
x=-140
y=21
[12]
name=KPACK
path=/SYS/KPACK
param=
ico=99
x=-77
y=21
[13]
name=DIFF
path=/sys/develop/diff
param=
ico=84
x=-203
y=96
[14]
name=FASM
path=/SYS/DEVELOP/FASM
param=
ico=10
x=-141
y=96
[15]
name=DOCPACK
path=/sys/network/webview
param=/kolibrios/res/guide/guide.htm
ico=8
x=-76
y=96
[16]
name=SHELL
path=/SYS/SHELL
param=
ico=1
x=-203
y=166
[17]
name=HEXEDIT
path=/SYS/DEVELOP/HEED
param=
ico=22
x=-141
y=166
[18]
name=CEDIT
path=/sys/develop/cedit
param=
ico=58
x=-74
y=166
|
||||
@@ -23,8 +23,7 @@ Bus Disconnect=kbd,37
|
||||
System Settings=setup,5
|
||||
|
||||
[Monitoring]
|
||||
Processes=cpu,60
|
||||
System Monitor=sysmon,57
|
||||
Task Manager=taskman,57
|
||||
Ghost Monitor=gmon,107
|
||||
Network Status=network/netstat,33
|
||||
AMDtemp=/k/utils/AMDtemp,128
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[rbmenu]
|
||||
Processes=cpu
|
||||
Task manager=taskman
|
||||
Theme settings=skincfg
|
||||
Background=/sys/media/palitra
|
||||
System panel=syspanel
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
56 Clipboard viewer |develop/clipview
|
||||
62 Calendar |calendar
|
||||
33 Online update * |/kolibrios/utils/osupdate
|
||||
48 Process manager |cpu
|
||||
48 Task manager |taskman
|
||||
24 Terminal |terminal
|
||||
05 Save ramdisk |rdsave
|
||||
24 Shell |shell
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[rbmenu]
|
||||
Processes=cpu
|
||||
Task manager=taskman
|
||||
Theme settings=skincfg
|
||||
Background=/sys/media/palitra
|
||||
System panel=syspanel
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
16 Colores y Apariencia |skincfg
|
||||
16 Atajos de teclado |mykey
|
||||
#9 **** SENSORES
|
||||
16 Procesos |cpu
|
||||
16 Gestor de tareas |taskman
|
||||
16 Dispositivos PCI |pcidev
|
||||
16 CPUID |cpuid
|
||||
16 Ghost Monitor |gmon
|
||||
|
||||
@@ -23,8 +23,7 @@ Desconectar bus=kbd,37
|
||||
Ajustes del sistema=setup,5
|
||||
|
||||
[Monitorizacion]
|
||||
Procesos=cpu,60
|
||||
Monitor del sistema=sysmon,57
|
||||
Gestor de tareas=taskman,57
|
||||
Ghost Monitor=gmon,107
|
||||
Estado de red=network/netstat,33
|
||||
AMDtemp=/k/utils/AMDtemp,128
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[rbmenu]
|
||||
Диспетчер процессов=cpu
|
||||
Диспетчер задач=taskman
|
||||
Управление темой=skincfg
|
||||
Настройка фона=/sys/media/palitra
|
||||
Системная панель=syspanel
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
00 Файловые менеджеры > |@8
|
||||
00 Спец. возможности > |@9
|
||||
62 Календарь |calendar
|
||||
48 Диспетчер задач |taskman
|
||||
51 Виртуальные диски |tmpdisk
|
||||
24 Терминал |terminal
|
||||
24 Консоль SHELL |shell
|
||||
|
||||
@@ -23,8 +23,7 @@ Hot Angles=HACONFIG,105
|
||||
Системные настройки=setup,5
|
||||
|
||||
[Мониторинг]
|
||||
Процессы=cpu,60
|
||||
Системный монитор=sysmon,57
|
||||
Диспетчер задач=taskman,57
|
||||
Ghost Monitor=gmon,107
|
||||
Статус сети=network/netstat,33
|
||||
AMDtemp=/k/utils/AMDtemp,128
|
||||
|
||||
+74
-604
@@ -38,7 +38,10 @@ DEBUG = 1
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors/events only
|
||||
|
||||
; 1 = per-second RX/TX counters and a frame log on the debug board
|
||||
; 1 = print per-second RX/TX rate statistics to the debug board while
|
||||
; traffic flows (cb/fr = transfers/frames, B = bytes, tx = frames sent,
|
||||
; wnd = advertised TCP window). Costs a few counters per frame and one
|
||||
; line of board output per second; invaluable for throughput debugging.
|
||||
DEBUG_STATS = 0
|
||||
|
||||
include '../../struct.inc'
|
||||
@@ -81,9 +84,6 @@ OID_GEN_CURRENT_PACKET_FILTER = 0x0001010E
|
||||
|
||||
; NDIS packet filter: directed | multicast | all-multicast | broadcast
|
||||
RNDIS_PACKET_FILTER = 0x0000000F
|
||||
; With a host address of our own choosing (see random_mac) also
|
||||
; promiscuous, as Linux always sets: the device never learns that address.
|
||||
RNDIS_FILTER_PROMISC = 0x00000020
|
||||
|
||||
RNDIS_STATUS_MEDIA_CONNECT = 0x4001000B
|
||||
RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000C
|
||||
@@ -98,32 +98,13 @@ STATE_RUN = 4 ; registered, data path live
|
||||
ETH_FRAME_MIN = 60 ; minimal ethernet frame (without FCS)
|
||||
ETH_FRAME_MAX = 1514 ; maximal ethernet frame (without FCS)
|
||||
RNDIS_HDR_SIZE = 44 ; REMOTE_NDIS_PACKET_MSG header
|
||||
; Our MaxTransferSize and the RX buffer size: one frame, as in Linux.
|
||||
; With 8192 phones split messages across transfers and we lost them.
|
||||
RNDIS_RX_BUF = 2048
|
||||
; Bulk IN transfers kept in flight: up to 32 frames per 10 ms wakeup
|
||||
; of the USB thread (~38 Mbit/s). See the note in rndis_start.
|
||||
RNDIS_RX_BUFFERS = 32
|
||||
RNDIS_RX_BUF = 8192 ; our max transfer, advertised in INIT
|
||||
RNDIS_RX_BUFFERS = 2 ; ping-pong pair for the bulk IN pipe
|
||||
RNDIS_RX_MAX_ERRORS = 32 ; consecutive RX errors before receive
|
||||
; stops (anti retry-storm)
|
||||
; The same for the interrupt IN pipe (was an endless retry storm).
|
||||
RNDIS_NOTIFY_MAX_ERRORS = 16
|
||||
RNDIS_RSP_BUF = 1024 ; encapsulated response buffer
|
||||
RNDIS_QUERY_LEN = 28 + 48 ; QUERY_MSG with a 48-byte input buffer,
|
||||
; what Linux rndis_host sends; also the
|
||||
; size of CmdBuf, the longest command
|
||||
; Bulk OUT messages in flight, each in a slot of a preallocated pool
|
||||
; (Kmalloc's 128 KB heap ran out). TX completions wait up to 10 ms for
|
||||
; the USB thread, and 96 slots were still exhausted during uploads.
|
||||
; A 2 KB slot never crosses a page, so 192 TRBs fit the 256-entry ring.
|
||||
RNDIS_TX_MAX_PENDING = 192 ; slots, a multiple of 32 (free bitmap)
|
||||
RNDIS_TX_SLOT = 2048 ; [context ptr][message <= 1559 bytes]
|
||||
RNDIS_FLOWS = 8 ; TCP flows tracked by DEBUG_STATS (power of 2)
|
||||
RNDIS_LOG_BURST = 40 ; frame-log lines allowed per second (DEBUG_STATS)
|
||||
RNDIS_TX_MAX_PENDING = 32 ; max messages in flight on bulk OUT
|
||||
RNDIS_GET_RETRIES = 200 ; response polls per command (see below)
|
||||
; 1/100 s to wait for MEDIA_CONNECT before taking the link as up.
|
||||
; A phone just switched to tethering drops the first DHCP DISCOVER.
|
||||
RNDIS_LINK_WAIT = 100
|
||||
|
||||
; USB structures
|
||||
struct usb_descr
|
||||
@@ -196,8 +177,6 @@ struct rndis_dev ETH_DEVICE
|
||||
InitState dd ? ; STATE_* of the init chain
|
||||
DevMaxTx dd ? ; device's max transfer (from INIT_C)
|
||||
LinkDown dd ? ; a MEDIA_DISCONNECT was indicated
|
||||
LinkKnown dd ? ; the device has indicated its media state
|
||||
LinkTimer dd ? ; TimerHS handle of the link-up fallback
|
||||
|
||||
TxPending dd ? ; messages in flight on bulk OUT
|
||||
Dead dd ? ; set on disconnect/fatal error
|
||||
@@ -208,16 +187,9 @@ struct rndis_dev ETH_DEVICE
|
||||
KaPending dd ? ; a keepalive reply is in flight
|
||||
GetRetries dd ? ; polls left for the current command
|
||||
|
||||
RxArea dd ? ; one KernelAlloc holding all RX buffers
|
||||
RxBufs rd RNDIS_RX_BUFFERS ; bulk IN buffers, slices of RxArea
|
||||
RxBufs rd RNDIS_RX_BUFFERS ; bulk IN buffers (KernelAlloc)
|
||||
RxSize dd ? ; size of one buffer
|
||||
TxArea dd ? ; KernelAlloc'ed pool of TX slots
|
||||
TxFree rd RNDIS_TX_MAX_PENDING/32 ; bit set = slot free
|
||||
RxErrRun dd ? ; consecutive failed RX transfers
|
||||
NotifyErrRun dd ? ; consecutive failed notification polls
|
||||
RxArmed dd ? ; transfers outstanding on the bulk IN
|
||||
; pipe; zero means receive has died
|
||||
LenErrNoted dd ? ; refused-frame lengths already logged
|
||||
|
||||
; per-second statistics, only maintained when DEBUG_STATS = 1
|
||||
StatTicks dd ? ; last print time, timer ticks
|
||||
@@ -227,24 +199,11 @@ struct rndis_dev ETH_DEVICE
|
||||
StatTxPkts dd ? ; packets_tx snapshot at last print
|
||||
StatWnd dd ? ; TCP receive window we advertised
|
||||
; in the last outgoing TCP frame
|
||||
StatTxHigh dd ? ; deepest the bulk OUT queue has been
|
||||
StatTail dd ? ; received bytes no frame was made of
|
||||
StatRxUni dd ? ; frames received addressed to our MAC
|
||||
StatRxBc dd ? ; frames received as broadcast/multicast
|
||||
LogTicks dd ? ; start of the current frame-log second
|
||||
LogCount dd ? ; frame-log lines printed in it
|
||||
StatLogDrop dd ? ; frame-log lines suppressed by the limit
|
||||
StatGap dd ? ; TCP segments that arrived beyond a
|
||||
; hole in their flow (loss/reorder)
|
||||
StatRetx dd ? ; TCP segments with data already seen
|
||||
; (the peer retransmitting)
|
||||
FlowNext dd ? ; next slot of Flows to recycle
|
||||
Flows rd RNDIS_FLOWS*2 ; [key][next expected seq]
|
||||
|
||||
SetupCmd rb 8 ; setup packet: SEND_ENCAPSULATED_CMD
|
||||
SetupRsp rb 8 ; setup packet: GET_ENCAPSULATED_RSP
|
||||
SetupKa rb 8 ; setup packet: keepalive reply
|
||||
CmdBuf rb RNDIS_QUERY_LEN ; init chain command messages
|
||||
CmdBuf rb 64 ; init chain command messages
|
||||
KaBuf rb 16 ; keepalive reply message
|
||||
NotifBuf rb 16 ; interrupt notification buffer
|
||||
RspBuf rb RNDIS_RSP_BUF ; encapsulated responses
|
||||
@@ -280,18 +239,6 @@ proc START c, reason:dword, cmdline:dword
|
||||
jne .nothing
|
||||
|
||||
DEBUGF 2,"loading (RNDIS host network driver)\n"
|
||||
|
||||
; one random host address per boot (see random_mac)
|
||||
rdtsc
|
||||
xor eax, edx
|
||||
imul eax, eax, 0x9E3779B1
|
||||
mov dword [random_mac], eax
|
||||
imul eax, eax, 0x85EBCA6B
|
||||
rol eax, 13
|
||||
mov word [random_mac+4], ax
|
||||
and byte [random_mac], 0xFE ; unicast
|
||||
or byte [random_mac], 0x02 ; locally administered
|
||||
|
||||
invoke RegUSBDriver, my_service, service_proc, usb_functions
|
||||
|
||||
.nothing:
|
||||
@@ -746,16 +693,7 @@ proc rndis_notify_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword,
|
||||
cmp [.status], USB_STATUS_STALL
|
||||
je .ret ; don't hammer a stalled pipe
|
||||
cmp [.status], 0
|
||||
je .status_ok
|
||||
; transient error: retry, but not for ever
|
||||
inc [ebx+rndis_dev.NotifyErrRun]
|
||||
cmp [ebx+rndis_dev.NotifyErrRun], RNDIS_NOTIFY_MAX_ERRORS
|
||||
jb .rearm
|
||||
DEBUGF 2,"notification pipe stopped after %u errors (status %u)\n", \
|
||||
[ebx+rndis_dev.NotifyErrRun], [.status]
|
||||
ret
|
||||
.status_ok:
|
||||
mov [ebx+rndis_dev.NotifyErrRun], 0
|
||||
jne .rearm ; transient error: retry
|
||||
|
||||
cmp [.length], 8
|
||||
jb .rearm
|
||||
@@ -825,23 +763,17 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
mov [ebx+rndis_dev.DevMaxTx], eax
|
||||
DEBUGF 2,"initialized, device max transfer %u\n", eax
|
||||
|
||||
; query the permanent MAC address, with an unused input buffer as Linux
|
||||
; sends it: QEMU's usb-net stalls a query without one
|
||||
; query the permanent MAC address
|
||||
lea edi, [ebx+rndis_dev.CmdBuf]
|
||||
push edi
|
||||
xor eax, eax
|
||||
mov ecx, RNDIS_QUERY_LEN / 4
|
||||
rep stosd
|
||||
pop edi
|
||||
mov dword [edi], RNDIS_MSG_QUERY
|
||||
mov dword [edi+4], RNDIS_QUERY_LEN ; MessageLength
|
||||
mov dword [edi+4], 28 ; MessageLength
|
||||
mov dword [edi+8], 2 ; RequestID
|
||||
mov dword [edi+12], OID_802_3_PERMANENT_ADDRESS
|
||||
mov dword [edi+16], RNDIS_QUERY_LEN - 28 ; InformationBufferLength
|
||||
mov dword [edi+16], 0 ; InformationBufferLength
|
||||
mov dword [edi+20], 20 ; InformationBufferOffset
|
||||
mov dword [edi+24], 0 ; DeviceVcHandle
|
||||
mov [ebx+rndis_dev.InitState], STATE_MAC
|
||||
mov eax, RNDIS_QUERY_LEN
|
||||
mov eax, 28
|
||||
call rndis_send_command
|
||||
test eax, eax
|
||||
jz .fail
|
||||
@@ -872,24 +804,6 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
[ebx+rndis_dev.mac+0]:2,[ebx+rndis_dev.mac+1]:2,[ebx+rndis_dev.mac+2]:2,\
|
||||
[ebx+rndis_dev.mac+3]:2,[ebx+rndis_dev.mac+4]:2,[ebx+rndis_dev.mac+5]:2
|
||||
|
||||
; A locally administered address is the same on every plug-in, so each
|
||||
; boot repeated the previous boot's connections into stale phone NAT
|
||||
; state. Replace it with a random one per boot, as Linux does.
|
||||
mov edx, RNDIS_PACKET_FILTER
|
||||
test byte [ebx+rndis_dev.mac], 0x02
|
||||
jz .mac_done
|
||||
mov eax, dword [random_mac]
|
||||
mov dword [ebx+rndis_dev.mac], eax
|
||||
mov ax, word [random_mac+4]
|
||||
mov word [ebx+rndis_dev.mac+4], ax
|
||||
or edx, RNDIS_FILTER_PROMISC
|
||||
push edx
|
||||
DEBUGF 2,"using random MAC %x-%x-%x-%x-%x-%x\n",\
|
||||
[ebx+rndis_dev.mac+0]:2,[ebx+rndis_dev.mac+1]:2,[ebx+rndis_dev.mac+2]:2,\
|
||||
[ebx+rndis_dev.mac+3]:2,[ebx+rndis_dev.mac+4]:2,[ebx+rndis_dev.mac+5]:2
|
||||
pop edx
|
||||
.mac_done:
|
||||
|
||||
; enable reception: set the packet filter
|
||||
lea edi, [ebx+rndis_dev.CmdBuf]
|
||||
mov dword [edi], RNDIS_MSG_SET
|
||||
@@ -899,7 +813,7 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
mov dword [edi+16], 4 ; InformationBufferLength
|
||||
mov dword [edi+20], 20 ; InformationBufferOffset
|
||||
mov dword [edi+24], 0 ; DeviceVcHandle
|
||||
mov dword [edi+28], edx
|
||||
mov dword [edi+28], RNDIS_PACKET_FILTER
|
||||
mov [ebx+rndis_dev.InitState], STATE_FILTER
|
||||
mov eax, 32
|
||||
call rndis_send_command
|
||||
@@ -950,13 +864,11 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
je .media_up
|
||||
cmp eax, RNDIS_STATUS_MEDIA_DISCONNECT
|
||||
jne .done
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
mov [ebx+rndis_dev.LinkDown], 1
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
DEBUGF 2,"link down\n"
|
||||
jmp .media_changed
|
||||
.media_up:
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
mov [ebx+rndis_dev.LinkDown], 0
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
DEBUGF 2,"link up\n"
|
||||
@@ -1014,28 +926,6 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
|
||||
endp
|
||||
|
||||
; The link-up fallback (see RNDIS_LINK_WAIT): the device said nothing
|
||||
; about its media in time, take the link as up. Runs from the kernel's
|
||||
; timer list, the context is the one given to TimerHS.
|
||||
proc rndis_link_timer stdcall uses ebx, .ctx:dword
|
||||
|
||||
mov ebx, [.ctx]
|
||||
mov [ebx+rndis_dev.LinkTimer], 0
|
||||
cmp [ebx+rndis_dev.Dead], 0
|
||||
jne .ret
|
||||
cmp [ebx+rndis_dev.LinkKnown], 0
|
||||
jne .ret ; the device spoke meanwhile
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
DEBUGF 2,"no media indication, assuming link up\n"
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
push ebx
|
||||
invoke NetLinkChanged
|
||||
pop ebx
|
||||
.ret:
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Init chain complete: allocate the receive buffers, register in the
|
||||
; network stack, bring the link up and start receiving.
|
||||
; IN: ebx = device context
|
||||
@@ -1044,32 +934,15 @@ proc rndis_start
|
||||
mov [ebx+rndis_dev.InitState], STATE_RUN
|
||||
mov [ebx+rndis_dev.RxSize], RNDIS_RX_BUF
|
||||
|
||||
; All receive buffers come from one page-aligned block: a 2 KB slice of
|
||||
; it never crosses a page, so every transfer is a single TRB.
|
||||
invoke KernelAlloc, RNDIS_RX_BUF * RNDIS_RX_BUFFERS
|
||||
xor edi, edi
|
||||
.alloc_loop:
|
||||
invoke KernelAlloc, RNDIS_RX_BUF
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [ebx+rndis_dev.RxArea], eax
|
||||
xor edi, edi
|
||||
.slice_loop:
|
||||
mov [ebx+rndis_dev.RxBufs+edi*4], eax
|
||||
add eax, RNDIS_RX_BUF
|
||||
inc edi
|
||||
cmp edi, RNDIS_RX_BUFFERS
|
||||
jb .slice_loop
|
||||
|
||||
; The pool of transmit slots, all free. It must exist before NetRegDev:
|
||||
; the stack may transmit as soon as the device is registered.
|
||||
invoke KernelAlloc, RNDIS_TX_SLOT * RNDIS_TX_MAX_PENDING
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [ebx+rndis_dev.TxArea], eax
|
||||
xor edi, edi
|
||||
.free_loop:
|
||||
or [ebx+rndis_dev.TxFree+edi*4], -1
|
||||
inc edi
|
||||
cmp edi, RNDIS_TX_MAX_PENDING/32
|
||||
jb .free_loop
|
||||
jb .alloc_loop
|
||||
|
||||
push ebx
|
||||
invoke NetRegDev
|
||||
@@ -1079,9 +952,8 @@ proc rndis_start
|
||||
mov [ebx+rndis_dev.Registered], 1
|
||||
DEBUGF 2,"registered as network device %u\n", eax
|
||||
|
||||
; the link follows the media indication, or RNDIS_LINK_WAIT expires
|
||||
cmp [ebx+rndis_dev.LinkKnown], 0
|
||||
je .link_wait
|
||||
; An LTE router bridge is up unless the device indicated otherwise
|
||||
; before we finished initializing.
|
||||
cmp [ebx+rndis_dev.LinkDown], 0
|
||||
jne @f
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
@@ -1089,40 +961,18 @@ proc rndis_start
|
||||
push ebx
|
||||
invoke NetLinkChanged
|
||||
pop ebx
|
||||
jmp .link_done
|
||||
.link_wait:
|
||||
invoke TimerHS, RNDIS_LINK_WAIT, 0, rndis_link_timer, ebx
|
||||
mov [ebx+rndis_dev.LinkTimer], eax
|
||||
test eax, eax
|
||||
jnz .link_done
|
||||
DEBUGF 2,"no timer for the link, assuming it is up\n"
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
push ebx
|
||||
invoke NetLinkChanged
|
||||
pop ebx
|
||||
.link_done:
|
||||
|
||||
; Arm every receive buffer at once. Callbacks run in the USB thread,
|
||||
; woken up to 10 ms after the IRQ; with one transfer in flight a device
|
||||
; sending one frame per transfer is capped at ~1 Mbit/s. Each callback
|
||||
; re-arms its own buffer at the ring tail, so frame order is kept.
|
||||
; NB: on EHCI this used to hurt (see usbcdc.asm); if so, use 2 buffers.
|
||||
xor edi, edi
|
||||
.arm_loop:
|
||||
; Arm the first receive. From here on the RX callback ping-pongs between
|
||||
; the two buffers: it re-arms the pipe with the other buffer BEFORE
|
||||
; parsing the completed one, so the device streams the next frames while
|
||||
; the host walks the current buffer. Exactly one transfer is outstanding
|
||||
; at any time - queueing several short-packet-terminated bulk IN
|
||||
; transfers breaks the EHCI stack (see the note in usbcdc.asm).
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], \
|
||||
[ebx+rndis_dev.RxBufs+edi*4], [ebx+rndis_dev.RxSize], \
|
||||
[ebx+rndis_dev.RxBufs], [ebx+rndis_dev.RxSize], \
|
||||
rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jz .armed
|
||||
inc [ebx+rndis_dev.RxArmed]
|
||||
inc edi
|
||||
cmp edi, RNDIS_RX_BUFFERS
|
||||
jb .arm_loop
|
||||
.armed:
|
||||
cmp [ebx+rndis_dev.RxArmed], 0
|
||||
je .fail
|
||||
DEBUGF 2,"receive queue depth %u\n", [ebx+rndis_dev.RxArmed]
|
||||
jz .fail
|
||||
ret
|
||||
|
||||
.fail:
|
||||
@@ -1133,8 +983,10 @@ proc rndis_start
|
||||
endp
|
||||
|
||||
if DEBUG_STATS
|
||||
; Print RX/TX counters about once a second while traffic flows.
|
||||
; cb/fr = transfers/frames received, tx = frames sent.
|
||||
; Print transfer-rate statistics to the debug board about once a second
|
||||
; while traffic flows (called from the RX callback). Shows where the
|
||||
; bottleneck is: cb/fr = USB transfers and frames per interval (RX),
|
||||
; tx = frames sent per interval (the TCP ACK clock on downloads).
|
||||
; IN: ebx = device context
|
||||
proc rndis_stats
|
||||
|
||||
@@ -1149,16 +1001,10 @@ proc rndis_stats
|
||||
jb .done
|
||||
mov ecx, [ebx+rndis_dev.packets_tx]
|
||||
sub ecx, [ebx+rndis_dev.StatTxPkts]
|
||||
DEBUGF 2,"stat %ut: cb %u fr %u B %u tx %u wnd %u txovr %u txerr %u rxdrop %u rxovr %u gap %u retx %u txq %u tail %u rxu %u rxb %u logdrop %u\n", \
|
||||
DEBUGF 2,"stat %ut: cb %u fr %u B %u tx %u wnd %u txovr %u rxdrop %u\n", \
|
||||
edx, [ebx+rndis_dev.StatCb], [ebx+rndis_dev.StatFrames], \
|
||||
[ebx+rndis_dev.StatBytes], ecx, [ebx+rndis_dev.StatWnd], \
|
||||
[ebx+rndis_dev.packets_tx_ovr], [ebx+rndis_dev.packets_tx_err], \
|
||||
[ebx+rndis_dev.packets_rx_drop], [ebx+rndis_dev.packets_rx_ovr], \
|
||||
[ebx+rndis_dev.StatGap], [ebx+rndis_dev.StatRetx], \
|
||||
[ebx+rndis_dev.StatTxHigh], [ebx+rndis_dev.StatTail], \
|
||||
[ebx+rndis_dev.StatRxUni], [ebx+rndis_dev.StatRxBc], \
|
||||
[ebx+rndis_dev.StatLogDrop]
|
||||
mov [ebx+rndis_dev.StatTxHigh], 0
|
||||
[ebx+rndis_dev.packets_tx_ovr], [ebx+rndis_dev.packets_rx_drop]
|
||||
mov [ebx+rndis_dev.StatCb], 0
|
||||
mov [ebx+rndis_dev.StatFrames], 0
|
||||
mov [ebx+rndis_dev.StatBytes], 0
|
||||
@@ -1170,281 +1016,6 @@ proc rndis_stats
|
||||
pop edx ecx eax
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Log ARP, ICMP, DNS, DHCP and TCP SYN/FIN/RST in both directions, at
|
||||
; most RNDIS_LOG_BURST lines a second (the rest counted in logdrop).
|
||||
; Also counts arrivals to our MAC (rxu) and to a group (rxb).
|
||||
; IN: ebx = device context, esi -> ethernet frame, ecx = frame length,
|
||||
; edi = 0 received, 1 sent. Destroys everything, the caller saves it.
|
||||
align 4
|
||||
rndis_log_frame:
|
||||
|
||||
mov ebp, edi ; direction
|
||||
test ebp, ebp
|
||||
jnz .classified
|
||||
test byte [esi], 1 ; group bit of destination MAC
|
||||
jz .unicast
|
||||
inc [ebx+rndis_dev.StatRxBc]
|
||||
jmp .classified
|
||||
.unicast:
|
||||
mov eax, [esi]
|
||||
cmp eax, dword [ebx+rndis_dev.mac]
|
||||
jne .classified
|
||||
mov ax, [esi+4]
|
||||
cmp ax, word [ebx+rndis_dev.mac+4]
|
||||
jne .classified
|
||||
inc [ebx+rndis_dev.StatRxUni]
|
||||
.classified:
|
||||
|
||||
; Pick out the frames worth a line; edx -> transport header.
|
||||
cmp word [esi+12], 0x0608 ; EtherType ARP (BE 08 06)
|
||||
je .arp
|
||||
cmp word [esi+12], 0x0008 ; EtherType IPv4
|
||||
jne .done
|
||||
cmp ecx, 14+20
|
||||
jb .done
|
||||
movzx eax, byte [esi+14]
|
||||
and eax, 15
|
||||
shl eax, 2 ; IP header length
|
||||
cmp eax, 20
|
||||
jb .done
|
||||
test word [esi+20], 0xFF1F ; not the first fragment
|
||||
jnz .done
|
||||
lea edx, [esi+14+eax]
|
||||
add eax, 14+8 ; room for an ICMP/UDP header
|
||||
cmp ecx, eax
|
||||
jb .done
|
||||
cmp byte [esi+23], 1 ; ICMP
|
||||
je .limit
|
||||
cmp byte [esi+23], 17 ; UDP
|
||||
je .udp
|
||||
cmp byte [esi+23], 6 ; TCP
|
||||
jne .done
|
||||
add eax, 20-8
|
||||
cmp ecx, eax
|
||||
jb .done
|
||||
test byte [edx+13], 7 ; FIN, SYN or RST
|
||||
jz .done
|
||||
jmp .limit
|
||||
.udp:
|
||||
mov eax, [edx] ; both ports, big-endian
|
||||
mov ecx, 2
|
||||
.udp_port:
|
||||
cmp ax, 53 shl 8 ; DNS
|
||||
je .limit
|
||||
cmp ax, 67 shl 8 ; DHCP server
|
||||
je .limit
|
||||
cmp ax, 68 shl 8 ; DHCP client
|
||||
je .limit
|
||||
shr eax, 16
|
||||
dec ecx
|
||||
jnz .udp_port
|
||||
jmp .done
|
||||
.arp:
|
||||
cmp ecx, 42
|
||||
jb .done
|
||||
|
||||
; Rate limit: RNDIS_LOG_BURST lines per 100 ticks.
|
||||
.limit:
|
||||
push edx
|
||||
invoke GetTimerTicks
|
||||
pop edx
|
||||
mov ecx, eax
|
||||
sub ecx, [ebx+rndis_dev.LogTicks]
|
||||
cmp ecx, 100
|
||||
jb @f
|
||||
mov [ebx+rndis_dev.LogTicks], eax
|
||||
mov [ebx+rndis_dev.LogCount], 0
|
||||
@@:
|
||||
cmp [ebx+rndis_dev.LogCount], RNDIS_LOG_BURST
|
||||
jb @f
|
||||
inc [ebx+rndis_dev.StatLogDrop]
|
||||
ret
|
||||
@@:
|
||||
inc [ebx+rndis_dev.LogCount]
|
||||
|
||||
; eax = ticks, ebp = direction, esi -> frame, edx -> transport header
|
||||
cmp word [esi+12], 0x0608
|
||||
je .print_arp
|
||||
cmp byte [esi+23], 1
|
||||
je .print_icmp
|
||||
cmp byte [esi+23], 17
|
||||
je .print_udp
|
||||
|
||||
;--------------------------------- TCP
|
||||
push ebp ; direction, tested below
|
||||
movzx ecx, word [esi+16]
|
||||
xchg cl, ch ; IP total length
|
||||
movzx ebx, byte [esi+14]
|
||||
and ebx, 15
|
||||
shl ebx, 2
|
||||
sub ecx, ebx ; minus the IP header
|
||||
movzx ebx, byte [edx+12]
|
||||
shr ebx, 4
|
||||
shl ebx, 2
|
||||
sub ecx, ebx ; minus the TCP header
|
||||
jns @f
|
||||
xor ecx, ecx
|
||||
@@:
|
||||
mov ebp, ecx ; payload length
|
||||
movzx ecx, word [edx]
|
||||
xchg cl, ch ; source port
|
||||
mov di, [edx+2]
|
||||
rol di, 8
|
||||
movzx edi, di ; destination port
|
||||
movzx ebx, word [edx+14]
|
||||
xchg bl, bh ; window (unscaled)
|
||||
cmp dword [esp], 0
|
||||
jne .tcp_out
|
||||
DEBUGF 2,"t%u in TCP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u flags %x win %u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, \
|
||||
[edx+13]:2, ebx, ebp
|
||||
pop eax
|
||||
ret
|
||||
.tcp_out:
|
||||
DEBUGF 2,"t%u out TCP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u flags %x win %u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, \
|
||||
[edx+13]:2, ebx, ebp
|
||||
pop eax
|
||||
ret
|
||||
|
||||
;--------------------------------- UDP (DNS, DHCP)
|
||||
.print_udp:
|
||||
movzx ecx, word [edx]
|
||||
xchg cl, ch ; source port
|
||||
mov di, [edx+2]
|
||||
rol di, 8
|
||||
movzx edi, di ; destination port
|
||||
movzx ebx, word [edx+4]
|
||||
xchg bl, bh
|
||||
sub ebx, 8 ; payload length
|
||||
test ebp, ebp
|
||||
jnz .udp_out
|
||||
DEBUGF 2,"t%u in UDP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, ebx
|
||||
ret
|
||||
.udp_out:
|
||||
DEBUGF 2,"t%u out UDP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, ebx
|
||||
ret
|
||||
|
||||
;--------------------------------- ICMP
|
||||
.print_icmp:
|
||||
test ebp, ebp
|
||||
jnz .icmp_out
|
||||
DEBUGF 2,"t%u in ICMP %u.%u.%u.%u > %u.%u.%u.%u type %u code %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, \
|
||||
[edx]:1, [edx+1]:1
|
||||
ret
|
||||
.icmp_out:
|
||||
DEBUGF 2,"t%u out ICMP %u.%u.%u.%u > %u.%u.%u.%u type %u code %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, \
|
||||
[edx]:1, [edx+1]:1
|
||||
ret
|
||||
|
||||
;--------------------------------- ARP
|
||||
; a request names who asks; a reply names the MAC, which tells a stale
|
||||
; entry (the phone's address changed) from a missing one
|
||||
.print_arp:
|
||||
cmp byte [esi+21], 2 ; opcode: 1 request, 2 reply
|
||||
je .arp_reply
|
||||
test ebp, ebp
|
||||
jnz .arp_req_out
|
||||
DEBUGF 2,"t%u in ARP who-has %u.%u.%u.%u tell %u.%u.%u.%u\n", eax, \
|
||||
[esi+38]:1, [esi+39]:1, [esi+40]:1, [esi+41]:1, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1
|
||||
ret
|
||||
.arp_req_out:
|
||||
DEBUGF 2,"t%u out ARP who-has %u.%u.%u.%u tell %u.%u.%u.%u\n", eax, \
|
||||
[esi+38]:1, [esi+39]:1, [esi+40]:1, [esi+41]:1, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1
|
||||
ret
|
||||
.arp_reply:
|
||||
test ebp, ebp
|
||||
jnz .arp_rep_out
|
||||
DEBUGF 2,"t%u in ARP %u.%u.%u.%u is-at %x-%x-%x-%x-%x-%x\n", eax, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1, \
|
||||
[esi+22]:2, [esi+23]:2, [esi+24]:2, [esi+25]:2, [esi+26]:2, [esi+27]:2
|
||||
ret
|
||||
.arp_rep_out:
|
||||
DEBUGF 2,"t%u out ARP %u.%u.%u.%u is-at %x-%x-%x-%x-%x-%x\n", eax, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1, \
|
||||
[esi+22]:2, [esi+23]:2, [esi+24]:2, [esi+25]:2, [esi+26]:2, [esi+27]:2
|
||||
.done:
|
||||
ret
|
||||
|
||||
; Track incoming TCP sequence numbers per flow: gap counts segments
|
||||
; past a hole, retx segments with data already received (cumulative).
|
||||
; IN: ebx = device context, esi -> ethernet frame, ecx = frame length
|
||||
; Destroys everything but ebx and ebp.
|
||||
proc rndis_track_tcp
|
||||
|
||||
cmp ecx, 54 ; eth+min IP+min TCP
|
||||
jb .done
|
||||
cmp word [esi+12], 0x0008 ; EtherType IPv4
|
||||
jne .done
|
||||
cmp byte [esi+23], 6 ; IP protocol TCP
|
||||
jne .done
|
||||
movzx edx, byte [esi+14]
|
||||
and edx, 15
|
||||
shl edx, 2 ; IP header length
|
||||
movzx eax, word [esi+16]
|
||||
xchg al, ah ; IP total length
|
||||
sub eax, edx
|
||||
jbe .done
|
||||
lea edi, [esi+14+edx] ; TCP header
|
||||
movzx edx, byte [edi+12]
|
||||
shr edx, 4
|
||||
shl edx, 2 ; TCP header length
|
||||
sub eax, edx ; payload length
|
||||
jbe .done ; pure ACK: no sequence space
|
||||
mov ecx, eax
|
||||
mov edx, [esi+26] ; source IP
|
||||
xor edx, [edi] ; ^ source/destination ports
|
||||
mov eax, [edi+4]
|
||||
bswap eax ; sequence number
|
||||
|
||||
lea esi, [ebx+rndis_dev.Flows]
|
||||
mov edi, RNDIS_FLOWS
|
||||
.find:
|
||||
cmp [esi], edx
|
||||
je .found
|
||||
add esi, 8
|
||||
dec edi
|
||||
jnz .find
|
||||
; a new flow: take over the oldest slot
|
||||
mov edi, [ebx+rndis_dev.FlowNext]
|
||||
inc [ebx+rndis_dev.FlowNext]
|
||||
and edi, RNDIS_FLOWS-1
|
||||
lea esi, [ebx+rndis_dev.Flows+edi*8]
|
||||
mov [esi], edx
|
||||
jmp .advance
|
||||
|
||||
.found:
|
||||
mov edx, eax
|
||||
sub edx, [esi+4] ; seq - expected
|
||||
jz .advance
|
||||
js .old
|
||||
inc [ebx+rndis_dev.StatGap]
|
||||
jmp .advance
|
||||
.old:
|
||||
inc [ebx+rndis_dev.StatRetx]
|
||||
lea edx, [eax+ecx]
|
||||
sub edx, [esi+4]
|
||||
jle .done ; nothing new in it
|
||||
.advance:
|
||||
add eax, ecx
|
||||
mov [esi+4], eax
|
||||
.done:
|
||||
ret
|
||||
|
||||
endp
|
||||
end if ; DEBUG_STATS
|
||||
|
||||
@@ -1460,12 +1031,11 @@ proc rndis_rx_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .bu
|
||||
|
||||
locals
|
||||
msg_off dd ? ; offset of the current message
|
||||
rearmed dd ? ; the other buffer is already armed
|
||||
endl
|
||||
|
||||
mov ebx, [.calldata]
|
||||
DEBUGF 1,"RX cb st %u len %u\n", [.status], [.length]
|
||||
; this transfer has left the queue, whatever its outcome
|
||||
dec [ebx+rndis_dev.RxArmed]
|
||||
cmp [ebx+rndis_dev.Dead], 0
|
||||
jne .ret
|
||||
cmp [.status], USB_STATUS_CLOSED
|
||||
@@ -1489,13 +1059,28 @@ end if
|
||||
jae .rx_dead
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], [.buffer], \
|
||||
[ebx+rndis_dev.RxSize], rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jz .check_dry
|
||||
inc [ebx+rndis_dev.RxArmed]
|
||||
jmp .ret
|
||||
.status_ok:
|
||||
mov [ebx+rndis_dev.RxErrRun], 0 ; the error run is broken
|
||||
|
||||
; Re-arm the pipe with the other buffer BEFORE parsing this one: the
|
||||
; device streams the next frames while the host walks the current
|
||||
; buffer. The completed transfer is already off the queue, so still at
|
||||
; most one transfer is outstanding (a hard requirement of the EHCI
|
||||
; stack, see the note in usbcdc.asm).
|
||||
mov [rearmed], 0
|
||||
mov eax, [ebx+rndis_dev.RxBufs]
|
||||
cmp eax, [.buffer]
|
||||
jne @f
|
||||
mov eax, [ebx+rndis_dev.RxBufs+4]
|
||||
@@:
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], eax, \
|
||||
[ebx+rndis_dev.RxSize], rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov [rearmed], 1
|
||||
@@:
|
||||
|
||||
mov [msg_off], 0
|
||||
|
||||
.msg_loop:
|
||||
@@ -1566,30 +1151,9 @@ end if
|
||||
if DEBUG_STATS
|
||||
inc [ebx+rndis_dev.StatFrames]
|
||||
add [ebx+rndis_dev.StatBytes], ecx
|
||||
pushad
|
||||
lea esi, [edi+NET_BUFF.data]
|
||||
xor edi, edi
|
||||
call rndis_log_frame
|
||||
popad
|
||||
pushad
|
||||
lea esi, [edi+NET_BUFF.data]
|
||||
call rndis_track_tcp
|
||||
popad
|
||||
end if
|
||||
DEBUGF 1,"->host frame %u bytes\n", [edi+NET_BUFF.length]
|
||||
|
||||
; Frames arrive, so the link is up despite MEDIA_DISCONNECT (a phone
|
||||
; tethering at cold boot never sends MEDIA_CONNECT).
|
||||
cmp [ebx+rndis_dev.LinkDown], 0
|
||||
je .link_ok
|
||||
mov [ebx+rndis_dev.LinkDown], 0
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
DEBUGF 2,"frames arrive while the link is down, taking it as up\n"
|
||||
pushad
|
||||
invoke NetLinkChanged
|
||||
popad
|
||||
.link_ok:
|
||||
|
||||
; hand the buffer to the network stack. EthInput consumes
|
||||
; [esp] = buffer and returns to the address at [esp+4].
|
||||
push ebp ebx esi
|
||||
@@ -1604,31 +1168,19 @@ end if
|
||||
inc [ebx+rndis_dev.packets_rx_drop]
|
||||
jmp .msg_loop
|
||||
|
||||
; put this buffer back at the tail of the queue
|
||||
; End of processing. If arming the other buffer failed at entry, fall
|
||||
; back to re-submitting the just-parsed buffer so receive does not stop.
|
||||
.rearm:
|
||||
if DEBUG_STATS
|
||||
; bytes of the transfer not turned into frames; must stay 0
|
||||
mov eax, [.length]
|
||||
sub eax, [msg_off]
|
||||
jbe @f
|
||||
add [ebx+rndis_dev.StatTail], eax
|
||||
@@:
|
||||
call rndis_stats
|
||||
end if
|
||||
cmp [rearmed], 0
|
||||
jne .ret
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], [.buffer], \
|
||||
[ebx+rndis_dev.RxSize], rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jz .rearm_failed
|
||||
inc [ebx+rndis_dev.RxArmed]
|
||||
ret
|
||||
.rearm_failed:
|
||||
jnz .ret
|
||||
DEBUGF 2,"failed to re-arm RX\n"
|
||||
; Losing one buffer of the queue is survivable as long as something is
|
||||
; still outstanding; if nothing is, receive has stopped for good.
|
||||
.check_dry:
|
||||
cmp [ebx+rndis_dev.RxArmed], 0
|
||||
jne .ret
|
||||
DEBUGF 2,"receive queue ran dry, receive stopped\n"
|
||||
.ret:
|
||||
ret
|
||||
|
||||
@@ -1636,11 +1188,7 @@ end if
|
||||
DEBUGF 2,"bulk IN stalled, receive stopped\n"
|
||||
ret
|
||||
|
||||
; Every buffer still in the queue arrives here in turn; report the death
|
||||
; of the pipe only once.
|
||||
.rx_dead:
|
||||
cmp [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
je .ret
|
||||
DEBUGF 2,"RX stopped after repeated transfer errors\n"
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
push ebx
|
||||
@@ -1665,50 +1213,7 @@ proc rndis_tx_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .bu
|
||||
DEBUGF 1,"TX error %u\n", [.status]
|
||||
@@:
|
||||
mov eax, [.calldata]
|
||||
call rndis_tx_release
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Take a free transmit slot.
|
||||
; IN: ebx = device context. OUT: eax = slot, 0 if none. Destroys ecx, edx.
|
||||
; The stack transmits on its own thread while completions run on the USB
|
||||
; thread, possibly on another CPU, hence the locked bit operations.
|
||||
if RNDIS_TX_SLOT <> 2048
|
||||
err "rndis_tx_claim/rndis_tx_release shift by 11 for 2 KB slots"
|
||||
end if
|
||||
proc rndis_tx_claim
|
||||
|
||||
xor edx, edx
|
||||
.scan:
|
||||
mov eax, [ebx+rndis_dev.TxFree+edx*4]
|
||||
test eax, eax
|
||||
jz .next
|
||||
bsf ecx, eax
|
||||
lock btr [ebx+rndis_dev.TxFree+edx*4], ecx
|
||||
jnc .scan ; taken meanwhile: look again
|
||||
shl edx, 5
|
||||
add edx, ecx ; slot number
|
||||
shl edx, 11
|
||||
mov eax, [ebx+rndis_dev.TxArea]
|
||||
add eax, edx
|
||||
ret
|
||||
.next:
|
||||
inc edx
|
||||
cmp edx, RNDIS_TX_MAX_PENDING/32
|
||||
jb .scan
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Give a transmit slot back.
|
||||
; IN: ebx = device context, eax = slot. Destroys eax.
|
||||
proc rndis_tx_release
|
||||
|
||||
sub eax, [ebx+rndis_dev.TxArea]
|
||||
shr eax, 11 ; slot number
|
||||
lock bts [ebx+rndis_dev.TxFree], eax
|
||||
invoke Kfree
|
||||
ret
|
||||
|
||||
endp
|
||||
@@ -1722,8 +1227,8 @@ endp
|
||||
;; ;;
|
||||
;; The frame is prepended with a 44-byte REMOTE_NDIS_PACKET_MSG. ;;
|
||||
;; If the transfer would be a multiple of the endpoint packet ;;
|
||||
;; size, one extra zero byte is sent so that the transfer ends in ;;
|
||||
;; a short packet; it is counted in MessageLength (QEMU needs it). ;;
|
||||
;; size, one extra zero byte is sent (not counted in the message ;;
|
||||
;; length) so that the transfer ends in a short packet. ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -1746,22 +1251,13 @@ endl
|
||||
je .drop
|
||||
mov ecx, [esi+NET_BUFF.length]
|
||||
cmp ecx, 14
|
||||
jb .badlen
|
||||
jb .err
|
||||
cmp ecx, ETH_FRAME_MAX
|
||||
ja .badlen
|
||||
ja .err
|
||||
DEBUGF 1,"host-> frame %u bytes\n", ecx
|
||||
|
||||
; limit the number of messages in flight
|
||||
lock inc [ebx+rndis_dev.TxPending]
|
||||
if DEBUG_STATS
|
||||
; remember how deep the queue actually gets: the margin left before
|
||||
; frames start being refused
|
||||
mov eax, [ebx+rndis_dev.TxPending]
|
||||
cmp eax, [ebx+rndis_dev.StatTxHigh]
|
||||
jbe @f
|
||||
mov [ebx+rndis_dev.StatTxHigh], eax
|
||||
@@:
|
||||
end if
|
||||
cmp [ebx+rndis_dev.TxPending], RNDIS_TX_MAX_PENDING
|
||||
ja .overrun
|
||||
|
||||
@@ -1780,7 +1276,6 @@ end if
|
||||
test eax, edx
|
||||
jnz @f
|
||||
inc eax
|
||||
mov [msglen], eax ; the pad byte is part of it
|
||||
@@:
|
||||
mov [xferlen], eax
|
||||
; never exceed what the device declared it can receive
|
||||
@@ -1790,8 +1285,9 @@ end if
|
||||
cmp eax, edx
|
||||
ja .toobig
|
||||
@@:
|
||||
; take a slot for [context dword][message]
|
||||
call rndis_tx_claim
|
||||
; allocate [context dword][message]
|
||||
add eax, 4
|
||||
invoke Kmalloc
|
||||
test eax, eax
|
||||
jz .no_memory
|
||||
mov [alloc], eax
|
||||
@@ -1825,15 +1321,6 @@ end if
|
||||
rep stosb
|
||||
|
||||
if DEBUG_STATS
|
||||
; stats: spell out the control frames we send
|
||||
pushad
|
||||
mov esi, [alloc]
|
||||
add esi, 4+RNDIS_HDR_SIZE ; frame start
|
||||
mov ecx, edx ; frame length
|
||||
movi edi, 1
|
||||
call rndis_log_frame
|
||||
popad
|
||||
|
||||
; stats: remember the TCP receive window we advertise (rwnd health on
|
||||
; downloads; parsed from the outgoing frame: eth+IPv4+TCP)
|
||||
cmp edx, 54 ; eth+min IP+min TCP
|
||||
@@ -1872,7 +1359,7 @@ end if
|
||||
|
||||
.submit_failed:
|
||||
mov eax, [alloc]
|
||||
call rndis_tx_release
|
||||
invoke Kfree
|
||||
lock dec [ebx+rndis_dev.TxPending]
|
||||
jmp .err
|
||||
|
||||
@@ -1889,16 +1376,6 @@ end if
|
||||
inc [ebx+rndis_dev.packets_tx_ovr]
|
||||
jmp .drop
|
||||
|
||||
; A frame the stack handed down does not fit an ethernet frame at all.
|
||||
; Report the first few: the length says at once whether the stack built
|
||||
; an oversized segment (t_maxseg not clamped to our mtu, which shows up
|
||||
; as an endlessly retransmitting connection) or something else.
|
||||
.badlen:
|
||||
cmp [ebx+rndis_dev.LenErrNoted], 4
|
||||
jae .err
|
||||
inc [ebx+rndis_dev.LenErrNoted]
|
||||
DEBUGF 2,"refusing a frame of %u bytes\n", ecx
|
||||
|
||||
.err:
|
||||
inc [ebx+rndis_dev.packets_tx_err]
|
||||
.drop:
|
||||
@@ -1933,11 +1410,6 @@ proc DeviceDisconnected stdcall uses ebx esi edi, .devdata:dword
|
||||
mov ebx, [.devdata]
|
||||
DEBUGF 2,"device disconnected\n"
|
||||
mov [ebx+rndis_dev.Dead], 1
|
||||
mov eax, [ebx+rndis_dev.LinkTimer]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke CancelTimerHS, eax ; must not fire on a freed context
|
||||
@@:
|
||||
cmp [ebx+rndis_dev.Registered], 0
|
||||
je @f
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
@@ -1949,17 +1421,16 @@ proc DeviceDisconnected stdcall uses ebx esi edi, .devdata:dword
|
||||
pop ebx
|
||||
mov [ebx+rndis_dev.Registered], 0
|
||||
@@:
|
||||
; every transfer callback has run by now, so no slot or buffer is in use
|
||||
mov eax, [ebx+rndis_dev.RxArea]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke KernelFree, eax
|
||||
@@:
|
||||
mov eax, [ebx+rndis_dev.TxArea]
|
||||
xor esi, esi
|
||||
.free_loop:
|
||||
mov eax, [ebx+rndis_dev.RxBufs+esi*4]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke KernelFree, eax
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi, RNDIS_RX_BUFFERS
|
||||
jb .free_loop
|
||||
mov eax, ebx
|
||||
invoke Kfree
|
||||
ret
|
||||
@@ -2009,6 +1480,5 @@ end data
|
||||
|
||||
align 4
|
||||
parse_scratch rndis_parse
|
||||
random_mac rb 6 ; host address used instead of a made-up one
|
||||
|
||||
include_debug_strings
|
||||
@@ -2628,7 +2628,7 @@ modify_pce:
|
||||
|
||||
|
||||
iglobal
|
||||
cpustring db 'CPU',0
|
||||
cpustring db 'TASKMAN',0
|
||||
endg
|
||||
|
||||
uglobal
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[rbmenu]
|
||||
Диспетчер процессов=cpu
|
||||
Диспетчер задач=taskman
|
||||
Управление темой=skincfg
|
||||
Настройка фона=/sys/media/palitra
|
||||
Настройка устройств=setup
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
## TASKMAN - Task Manager
|
||||
|
||||
Replaces CPU and SYSMON. Starts from the menu, the system panel or by
|
||||
`Ctrl+Alt+Del`.
|
||||
|
||||
* **Processes** - threads with their CPU and memory. `Details` opens
|
||||
TINFO, `End` ends the thread, `Run...` starts a program. System threads
|
||||
(OS, @...) are shown with `System`.
|
||||
* **Performance** - CPU, temperature, memory and network: the values on
|
||||
the left, the history as a graph on the right. Temperature comes from
|
||||
the CPU sensor (Intel, AMD, Hygon, VIA, Zhaoxin) or else from a board
|
||||
monitoring chip (Winbond, ITE, ABIT uGuru); without either there is no
|
||||
temperature graph. `CPUID` starts CPUID.
|
||||
* **Disks** - partitions with label, size and, for memory disks, the
|
||||
space used. `Open` shows the disk in Eolite.
|
||||
* **Drivers** - the drivers the kernel has loaded. `Load...` starts
|
||||
LOADDRV.
|
||||
* **Autorun** - the programs of `/sys/settings/autorun.dat`. A program
|
||||
turned off has `#` before it and is shown pale; `Turn on/off` adds or
|
||||
removes the `#` in the file.
|
||||
|
||||
Lists sort by a click on a column header; a second click reverses the
|
||||
order.
|
||||
|
||||
### Keys
|
||||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| `Tab` | Next tab |
|
||||
| `Esc` | Close |
|
||||
| `Up`, `Down`, `PgUp`, `PgDn`, `Home`, `End` | Move in a list |
|
||||
| `Enter` | Processes: Details; Disks: Open |
|
||||
| `Del` | Processes: End |
|
||||
| `Space` | Autorun: turn the program on or off |
|
||||
| Right click on a row | Processes: Details; Disks: Open |
|
||||
| Mouse wheel | Scroll a list |
|
||||
|
||||
### History
|
||||
|
||||
* 2026-10 - First version. Replaces CPU (processes) and SYSMON (system
|
||||
monitor); adds the disks, drivers and autorun tabs and the CPU
|
||||
temperature sensors; the board chips come from GMON.
|
||||
@@ -0,0 +1,4 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
|
||||
lang = (tup.getconfig("LANG") == "") and "en_US" or tup.getconfig("LANG")
|
||||
tup.rule("taskman.asm", "fasm -dlang=" .. lang .. " %f %o " .. tup.getconfig("KPACK_CMD"), "taskman")
|
||||
@@ -0,0 +1,423 @@
|
||||
; Drawing and formatting helpers; they keep all registers unless noted.
|
||||
|
||||
macro __mov reg, a, b { ; mcall loads small constants shorter
|
||||
if (~a eq) & (~b eq)
|
||||
mpack reg, a, b
|
||||
else if (~a eq) & (b eq)
|
||||
movi reg, a
|
||||
end if
|
||||
}
|
||||
|
||||
; An item of a bar: a button with its color, a checkbox with its state or
|
||||
; a gap
|
||||
struct BAR
|
||||
kind db ?
|
||||
text dd ? ; the caption
|
||||
arg dd ? ; -> the color, -> the state as a byte
|
||||
ends
|
||||
BAR_END = 0
|
||||
BAR_BUTTON = 1
|
||||
BAR_CHECK = 2
|
||||
BAR_GAP = 3
|
||||
|
||||
; ebx = x shl 16 + y, ecx = color, edx -> string in UTF-8
|
||||
draw_text:
|
||||
pusha
|
||||
or ecx, TEXT_UTF8
|
||||
mcall SF_DRAW_TEXT
|
||||
popa
|
||||
ret
|
||||
|
||||
; eax -> string; out: eax = width in pixels
|
||||
text_width:
|
||||
push ecx esi
|
||||
mov esi, eax
|
||||
xor ecx, ecx
|
||||
|
||||
.next:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done
|
||||
call utf8_more
|
||||
je .next
|
||||
add ecx, 8
|
||||
jmp .next
|
||||
|
||||
.done:
|
||||
xchg eax, ecx
|
||||
pop esi ecx
|
||||
ret
|
||||
|
||||
; eax -> caption; out: eax = width of the button
|
||||
button_width:
|
||||
call text_width
|
||||
add eax, BTN_PAD*2
|
||||
ret
|
||||
|
||||
; Frame in the border color filled with edx. ebx = x shl 16 + w, ecx = y shl 16 + h
|
||||
frame_rect:
|
||||
pusha
|
||||
push edx
|
||||
mcall SF_DRAW_RECT, , , [sc.work_graph]
|
||||
pop edx
|
||||
|
||||
add ebx, 1 shl 16 - 2
|
||||
add ecx, 1 shl 16 - 2
|
||||
mcall SF_DRAW_RECT
|
||||
popa
|
||||
ret
|
||||
|
||||
; eax = icon, ebx = x shl 16 + y, edx = the background for its white
|
||||
draw_icon:
|
||||
pusha
|
||||
mov esi, [icons]
|
||||
test esi, esi
|
||||
jz .done
|
||||
|
||||
imul eax, ICON*ICON*4
|
||||
add esi, eax
|
||||
mov edi, icon_buf
|
||||
mov ecx, ICON*ICON
|
||||
@@:
|
||||
lodsd
|
||||
cmp eax, -1
|
||||
jne .pixel
|
||||
mov eax, edx
|
||||
|
||||
.pixel:
|
||||
stosd
|
||||
loop @b
|
||||
|
||||
mov edx, ebx
|
||||
mcall SF_PUT_IMAGE_EXT, icon_buf, (ICON shl 16) + ICON, , 32, 0, 0
|
||||
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
; eax, edx = colors; out: eax = the one half way between them, edx changed
|
||||
mix:
|
||||
and eax, 0xFEFEFE
|
||||
and edx, 0xFEFEFE
|
||||
add eax, edx
|
||||
shr eax, 1
|
||||
ret
|
||||
|
||||
; eax -> caption, edx = id, esi = color
|
||||
bar_button:
|
||||
pusha
|
||||
mov edi, eax
|
||||
call button_width
|
||||
call bar_place
|
||||
|
||||
dec ebx ; the kernel draws one pixel more
|
||||
dec ecx
|
||||
mcall SF_DEFINE_BUTTON
|
||||
|
||||
add ebx, BTN_PAD shl 16
|
||||
mov eax, [sc.work_button_text] ; then bar_text
|
||||
|
||||
; The end of the bar items: edi -> caption, eax = color, ebx = x shl 16,
|
||||
; ecx = y shl 16 of the item
|
||||
bar_text:
|
||||
shr ecx, 16
|
||||
add ecx, (BTN_H - TEXT_H)/2
|
||||
mov bx, cx
|
||||
xchg eax, ecx
|
||||
mov edx, edi
|
||||
call draw_text
|
||||
popa
|
||||
ret
|
||||
|
||||
; eax -> caption, edx = id, ebp = checked
|
||||
bar_checkbox:
|
||||
pusha
|
||||
mov edi, eax
|
||||
call button_width ; the box, PAD, the caption: 2 left
|
||||
call bar_place
|
||||
add [bar_left], 2*PAD + CHECK - 2*BTN_PAD ; then more room
|
||||
|
||||
or edx, BT_HIDE + BT_NOFRAME
|
||||
mcall SF_DEFINE_BUTTON
|
||||
|
||||
mov bx, CHECK
|
||||
add ecx, ((BTN_H - CHECK)/2) shl 16
|
||||
mov cx, CHECK
|
||||
mov [cb.left_s], ebx ; the box of box_lib, the caption
|
||||
mov [cb.top_s], ecx ; as the other ones
|
||||
|
||||
mov eax, [sc.work_light]
|
||||
mov [cb.color], eax
|
||||
mov eax, [sc.work_button] ; the frame and the check
|
||||
mov [cb.border_color], eax
|
||||
lea eax, [ebp + ebp] ; checked
|
||||
mov [cb.flags], eax
|
||||
|
||||
push cb
|
||||
call [check_box_draw2]
|
||||
|
||||
add ebx, (CHECK + PAD) shl 16
|
||||
sub ecx, ((BTN_H - CHECK)/2) shl 16
|
||||
mov eax, [sc.work_text]
|
||||
jmp bar_text
|
||||
|
||||
; Place in the bottom bar: from the left end, or from the right one for ids
|
||||
; with bit 3. eax = width, edx = id; out: ebx = x shl 16 + w, ecx = y shl 16 + h
|
||||
bar_place:
|
||||
lea ebx, [eax + PAD]
|
||||
test dl, 8
|
||||
jnz .right
|
||||
|
||||
xchg ebx, [bar_left]
|
||||
add [bar_left], ebx
|
||||
jmp @f
|
||||
|
||||
.right:
|
||||
sub [bar_right], ebx
|
||||
mov ebx, [bar_right]
|
||||
|
||||
@@:
|
||||
shl ebx, 16
|
||||
mov bx, ax
|
||||
|
||||
mov ecx, [bar_y]
|
||||
shl ecx, 16
|
||||
mov cx, BTN_H
|
||||
ret
|
||||
|
||||
; The items of a bar from the left, esi -> them; the buttons and the
|
||||
; checkboxes get the ids from BTN_OWN on. Changes all registers.
|
||||
bar_draw:
|
||||
mov edx, BTN_OWN
|
||||
|
||||
.item:
|
||||
mov bl, [esi + BAR.kind]
|
||||
mov eax, [esi + BAR.text]
|
||||
mov ecx, [esi + BAR.arg]
|
||||
add esi, sizeof.BAR
|
||||
dec bl
|
||||
js .done
|
||||
jz .button
|
||||
dec bl
|
||||
jz .check
|
||||
add [bar_left], PAD ; a gap
|
||||
jmp .item
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
.button:
|
||||
push esi
|
||||
mov esi, [ecx]
|
||||
call bar_button
|
||||
pop esi
|
||||
inc edx
|
||||
jmp .item
|
||||
|
||||
.check:
|
||||
movzx ebp, byte [ecx]
|
||||
call bar_checkbox
|
||||
inc edx
|
||||
jmp .item
|
||||
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; Formatting: write to edi and leave it at the terminating zero.
|
||||
|
||||
; eax = number; printed as 8 hex digits
|
||||
fmt_hex:
|
||||
pusha
|
||||
mov ebx, 16
|
||||
mov esi, 8
|
||||
jmp fmt_num
|
||||
|
||||
; eax = number
|
||||
fmt_uint:
|
||||
pusha
|
||||
mov ebx, 10
|
||||
xor esi, esi
|
||||
|
||||
fmt_num: ; ebx = base, esi = the fewest digits
|
||||
xor ecx, ecx
|
||||
|
||||
@@:
|
||||
xor edx, edx
|
||||
div ebx
|
||||
push edx
|
||||
inc ecx
|
||||
test eax, eax
|
||||
jnz @b
|
||||
cmp ecx, esi
|
||||
jb @b
|
||||
|
||||
@@:
|
||||
pop eax
|
||||
cmp al, 10 ; 0..15 to '0'..'9', 'A'..'F'
|
||||
sbb al, 0x69
|
||||
das
|
||||
stosb
|
||||
loop @b
|
||||
|
||||
mov [edi], cl
|
||||
mov [esp + PUSHA_EDI], edi
|
||||
popa
|
||||
ret
|
||||
|
||||
; al = a byte of UTF-8; out: ZF = 1 if it goes on with a character
|
||||
utf8_more:
|
||||
push eax
|
||||
and al, 0xC0
|
||||
cmp al, 0x80
|
||||
pop eax
|
||||
ret
|
||||
|
||||
; edx -> string; copies up to (ebx - eax) / 8 characters, TEXT_CHARS at
|
||||
; most, and keeps edi
|
||||
fmt_clip:
|
||||
pusha
|
||||
|
||||
mov esi, edx
|
||||
sub ebx, eax
|
||||
shr ebx, 3
|
||||
cmp ebx, TEXT_CHARS
|
||||
jb @f
|
||||
mov ebx, TEXT_CHARS
|
||||
|
||||
@@:
|
||||
lodsb
|
||||
test al, al
|
||||
jz @f
|
||||
call utf8_more
|
||||
je .put
|
||||
dec ebx
|
||||
js @f
|
||||
|
||||
.put:
|
||||
stosb
|
||||
cmp edi, text_buf + TEXT_CHARS*4
|
||||
jb @b
|
||||
|
||||
@@:
|
||||
mov byte [edi], 0
|
||||
popa
|
||||
ret
|
||||
|
||||
; esi -> string
|
||||
fmt_str:
|
||||
push eax esi
|
||||
@@:
|
||||
lodsb
|
||||
stosb
|
||||
test al, al
|
||||
jnz @b
|
||||
dec edi
|
||||
pop esi eax
|
||||
ret
|
||||
|
||||
; eax -> string
|
||||
fmt_unit:
|
||||
xchg esi, eax
|
||||
call fmt_str
|
||||
xchg esi, eax
|
||||
ret
|
||||
|
||||
; eax = KB; printed as "123 KB", "1.5 MB", "12.3 GB" etc.
|
||||
fmt_size:
|
||||
pusha
|
||||
mov ebx, 1024
|
||||
mov esi, sz_units
|
||||
jmp fmt_scaled
|
||||
|
||||
; eax = bits a second; printed as "500 bit/s", "1.5 Mbit/s" etc.
|
||||
fmt_rate:
|
||||
pusha
|
||||
mov ebx, 1000
|
||||
mov esi, sz_bits ; then fmt_scaled
|
||||
|
||||
; ebx = the step of the units, esi -> the units, each ended with 0: the
|
||||
; number in the largest one it fills, small ones with a decimal but .0
|
||||
fmt_scaled:
|
||||
xor ecx, ecx
|
||||
xor edx, edx
|
||||
|
||||
@@:
|
||||
cmp eax, ebx
|
||||
jb @f
|
||||
xor edx, edx
|
||||
div ebx
|
||||
inc ecx
|
||||
jmp @b
|
||||
|
||||
@@:
|
||||
call fmt_uint
|
||||
|
||||
cmp eax, 100
|
||||
jae .unit
|
||||
imul eax, edx, 10
|
||||
xor edx, edx
|
||||
div ebx
|
||||
test eax, eax
|
||||
jz .unit
|
||||
|
||||
mov byte [edi], "."
|
||||
inc edi
|
||||
call fmt_uint
|
||||
|
||||
.unit:
|
||||
dec ecx
|
||||
js @f
|
||||
|
||||
.skip:
|
||||
lodsb
|
||||
test al, al
|
||||
jnz .skip
|
||||
jmp .unit
|
||||
|
||||
@@:
|
||||
call fmt_str
|
||||
mov [esp + PUSHA_EDI], edi
|
||||
popa
|
||||
ret
|
||||
|
||||
; eax = seconds; printed as "h:mm:ss"
|
||||
fmt_time:
|
||||
pusha
|
||||
xor edx, edx
|
||||
mov ecx, 3600
|
||||
div ecx
|
||||
call fmt_uint
|
||||
|
||||
xchg eax, edx
|
||||
mov cl, 60
|
||||
div cl
|
||||
movzx edx, ah
|
||||
call .two
|
||||
xchg eax, edx
|
||||
call .two
|
||||
|
||||
mov [esp + PUSHA_EDI], edi
|
||||
popa
|
||||
ret
|
||||
|
||||
.two: ; eax = 0..99
|
||||
aam
|
||||
add ax, "00"
|
||||
xchg al, ah
|
||||
shl eax, 8
|
||||
mov al, ":"
|
||||
stosd
|
||||
dec edi
|
||||
ret
|
||||
|
||||
; esi -> path: the program without parameters
|
||||
run_plain:
|
||||
xor edx, edx ; then run_app
|
||||
|
||||
; esi -> path, edx -> parameters or 0
|
||||
run_app:
|
||||
pusha
|
||||
mov [app_info.Flags], edx
|
||||
mov [app_info.FileName], esi
|
||||
mcall SF_FILE, app_info
|
||||
popa
|
||||
ret
|
||||
@@ -0,0 +1,188 @@
|
||||
; The monitoring chips of older boards, ported from GMON: Winbond W836xx and
|
||||
; ITE IT87xx at ports 0x295/0x296, ABIT uGuru at 0xE0/0xE4. Their first
|
||||
; temperature stands in for a CPU without a sensor.
|
||||
|
||||
HWM_PORT = 0x295 ; index, data at + 1
|
||||
SIO_PORT = 0x2E ; Super I/O config, data at + 1
|
||||
UGURU_CMD = 0xE0
|
||||
UGURU_DATA = 0xE4
|
||||
|
||||
WB_BANK = 0x4E ; the registers of Winbond: the bank,
|
||||
WB_VENDOR = 0x4F ; the vendor, 0x80 in WB_BANK: its
|
||||
WB_ID = 0x5CA3 ; high byte
|
||||
WB_TEMP = 0x50 ; in bank 1
|
||||
SIO_CHIP_ID = 0x20 ; of the Super I/O, then of ITE
|
||||
ITE_ID = 0x87 ; the high byte
|
||||
ITE_TEMP = 0x29
|
||||
UGURU_TEMP = 0x2100 ; bank, sensor
|
||||
|
||||
; The chip of the board: hwm_read; out: eax = it, 0 if none: the ports
|
||||
; given back
|
||||
hwm_init:
|
||||
mcall SF_SET_PORTS, 0, HWM_PORT, HWM_PORT + 1
|
||||
test eax, eax
|
||||
jnz .uguru
|
||||
call wb_probe
|
||||
je .found
|
||||
|
||||
mcall SF_SET_PORTS, 0, SIO_PORT, SIO_PORT + 1
|
||||
test eax, eax
|
||||
jnz .uguru
|
||||
call ite_probe
|
||||
je .found
|
||||
|
||||
.uguru:
|
||||
mcall SF_SET_PORTS, 0, UGURU_CMD, UGURU_DATA
|
||||
test eax, eax
|
||||
jnz .none
|
||||
|
||||
in al, UGURU_CMD
|
||||
test al, al
|
||||
jz @f
|
||||
cmp al, 0xAC
|
||||
jne .none
|
||||
|
||||
@@:
|
||||
in al, UGURU_DATA
|
||||
test al, al
|
||||
jz @f
|
||||
cmp al, 8
|
||||
jne .none
|
||||
|
||||
@@:
|
||||
mov eax, uguru_read
|
||||
|
||||
.found:
|
||||
mov [hwm_read], eax
|
||||
ret
|
||||
|
||||
.none:
|
||||
mcall SF_SET_PORTS, 1, HWM_PORT, HWM_PORT + 1
|
||||
mcall SF_SET_PORTS, 1, UGURU_CMD, UGURU_DATA
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
; al = bank (or 0x80: the high byte of the vendor), ah = register; out: eax
|
||||
wb_get:
|
||||
push eax
|
||||
mov ah, WB_BANK
|
||||
call hwm_index
|
||||
pop eax
|
||||
out dx, al ; then hwm_get
|
||||
|
||||
; ah = register; out: eax
|
||||
hwm_get:
|
||||
call hwm_index
|
||||
in al, dx
|
||||
movzx eax, al
|
||||
ret
|
||||
|
||||
hwm_index: ; out: dx = the data port
|
||||
mov dx, HWM_PORT
|
||||
mov al, ah
|
||||
out dx, al
|
||||
inc edx
|
||||
ret
|
||||
|
||||
; out: ZF = 1 and eax = the read procedure if found
|
||||
wb_probe:
|
||||
mov ax, WB_VENDOR shl 8 ; a byte at a time
|
||||
call wb_get
|
||||
xchg ebx, eax
|
||||
mov ax, WB_VENDOR shl 8 + 0x80
|
||||
call wb_get
|
||||
mov bh, al
|
||||
|
||||
cmp bx, WB_ID
|
||||
jne .done
|
||||
|
||||
mov eax, wb_read
|
||||
cmp eax, eax
|
||||
.done:
|
||||
ret
|
||||
|
||||
; out: ZF = 1 and eax = the read procedure if found
|
||||
ite_probe:
|
||||
mov eax, 0x55550187 ; MB PnP mode
|
||||
mov ecx, 4
|
||||
@@:
|
||||
out SIO_PORT, al
|
||||
shr eax, 8
|
||||
loop @b
|
||||
|
||||
mov al, SIO_CHIP_ID
|
||||
out SIO_PORT, al
|
||||
in al, SIO_PORT + 1
|
||||
xchg eax, esi
|
||||
|
||||
mov al, 2 ; leave the mode
|
||||
out SIO_PORT, al
|
||||
out SIO_PORT + 1, al
|
||||
mcall SF_SET_PORTS, 1, SIO_PORT, SIO_PORT + 1
|
||||
|
||||
xchg eax, esi
|
||||
cmp al, ITE_ID
|
||||
mov eax, ite_read
|
||||
ret
|
||||
|
||||
; out: eax = the first temperature
|
||||
wb_read:
|
||||
mov ax, WB_TEMP shl 8 + 1
|
||||
jmp wb_get
|
||||
|
||||
ite_read:
|
||||
mov ah, ITE_TEMP
|
||||
jmp hwm_get
|
||||
|
||||
uguru_read:
|
||||
mov ax, UGURU_TEMP ; then uguru_sensor
|
||||
|
||||
; ax = sensor; out: eax
|
||||
uguru_sensor:
|
||||
push ebx
|
||||
mov ebx, eax
|
||||
mov al, ah ; the bank
|
||||
out UGURU_DATA, al
|
||||
mov ah, 8
|
||||
call .wait
|
||||
|
||||
mov al, bl
|
||||
out UGURU_CMD, al
|
||||
mov ah, 1
|
||||
call .wait
|
||||
|
||||
in al, UGURU_CMD
|
||||
movzx ebx, al
|
||||
|
||||
mov ecx, 1000 ; back to the ready state
|
||||
.ready:
|
||||
in al, UGURU_DATA
|
||||
cmp al, 8
|
||||
je .done
|
||||
xor eax, eax
|
||||
out UGURU_DATA, al
|
||||
mov ah, 9
|
||||
call .wait
|
||||
loop .ready
|
||||
|
||||
.done:
|
||||
xchg eax, ebx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
.wait: ; for ah at the data port
|
||||
push ecx
|
||||
mov ecx, 1000
|
||||
@@:
|
||||
in al, UGURU_DATA
|
||||
cmp al, ah
|
||||
loopne @b
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
hwm_read dd nothing ; the procedure of the chip
|
||||
|
||||
uglobal
|
||||
align 4
|
||||
hwm_temp dd ? ; degrees
|
||||
endg
|
||||
@@ -0,0 +1,684 @@
|
||||
; List of a tab: rows in columns with a header, a selected row and a scrollbar on
|
||||
; the panel. The columns go from the left, one of them, width 0, takes what
|
||||
; the others leave. A click on a row selects it, then calls the trigger of
|
||||
; that button; a key of the hotkeys calls its trigger. `list` is the list of
|
||||
; the open tab; a closed tab keeps it in its descriptor.
|
||||
|
||||
struct LIST
|
||||
cols dd ? ; the columns
|
||||
cols_end dd ?
|
||||
sort dd ? ; the sorted column
|
||||
left dd ? ; the triggers: a left click,
|
||||
right dd ? ; a right click,
|
||||
keys dd ? ; -> HOTKEYs, ended by 0
|
||||
dim dd ? ; a byte in the row: not 0, it is pale; 0: none
|
||||
count dd ?
|
||||
sel dd ?
|
||||
first dd ?
|
||||
key dd ? ; the first dword of the selected row
|
||||
desc dd ? ; 1: the sorted column goes down
|
||||
view dd ? ; -> the pointers to the rows
|
||||
ends
|
||||
|
||||
struct HOTKEY
|
||||
key db ?
|
||||
trigger dw ?
|
||||
ends
|
||||
|
||||
struct COL
|
||||
caption dd ?
|
||||
field db ? ; offset in the row
|
||||
kind db ?
|
||||
width db ? ; 0: what the others leave
|
||||
ends
|
||||
|
||||
; The list: the header, the rows and the scrollbar.
|
||||
list_draw:
|
||||
mov ebx, [area_w] ; what the others leave to the widest
|
||||
sub ebx, 1 + SB_W
|
||||
mov esi, [list.cols]
|
||||
|
||||
@@:
|
||||
movzx edx, byte [esi + COL.width]
|
||||
sub ebx, edx
|
||||
add esi, sizeof.COL
|
||||
cmp esi, [list.cols_end]
|
||||
jb @b
|
||||
mov [col_rest], ebx
|
||||
|
||||
mov eax, [area_h] ; the rows that fit
|
||||
sub eax, 2 + HDR_H + 1
|
||||
xor edx, edx
|
||||
mov ecx, ROW_H
|
||||
div ecx
|
||||
mov [rows], eax
|
||||
|
||||
mov ebx, PAD shl 16 ; the header and the line under it,
|
||||
mov bx, word [area_w] ; left of the scrollbar
|
||||
sub bx, SB_W - 1
|
||||
mov ecx, (AREA_Y shl 16) + HDR_H + 2
|
||||
mov edx, [mid]
|
||||
call frame_rect
|
||||
|
||||
xor eax, eax
|
||||
mov ebp, AREA_Y + 1 + (HDR_H - TEXT_H)/2
|
||||
call list_line ; then list_rows
|
||||
|
||||
; The rows and the scrollbar only, for new data.
|
||||
list_rows:
|
||||
call list_clamp
|
||||
mov edi, [list.first]
|
||||
mov ecx, ((AREA_Y + HDR_H + 2) shl 16) + ROW_H
|
||||
mov ebp, [rows]
|
||||
|
||||
.row:
|
||||
mov ebx, (PAD + 1) shl 16
|
||||
mov bx, word [area_w]
|
||||
sub bx, 1 + SB_W
|
||||
|
||||
mov edx, [sc.work_light]
|
||||
mov esi, [sc.work_text]
|
||||
cmp edi, [list.sel]
|
||||
jne @f
|
||||
cmp edi, [list.count] ; a row there
|
||||
jae @f
|
||||
mov edx, [sc.work_button]
|
||||
mov esi, [sc.work_button_text]
|
||||
|
||||
@@:
|
||||
mcall SF_DRAW_RECT
|
||||
|
||||
cmp edi, [list.count]
|
||||
jae @f
|
||||
|
||||
pusha
|
||||
mov eax, [list.view]
|
||||
mov eax, [eax + edi*4]
|
||||
mov ebp, ecx
|
||||
shr ebp, 16
|
||||
add ebp, (ROW_H - TEXT_H)/2
|
||||
mov ecx, esi
|
||||
|
||||
mov esi, [list.dim] ; pale: half way to the background
|
||||
test esi, esi
|
||||
jz .line
|
||||
cmp byte [eax + esi], 0
|
||||
je .line
|
||||
|
||||
xchg eax, ecx
|
||||
call mix
|
||||
xchg eax, ecx
|
||||
|
||||
.line:
|
||||
call list_line
|
||||
popa
|
||||
|
||||
@@:
|
||||
add ecx, ROW_H shl 16
|
||||
inc edi
|
||||
dec ebp
|
||||
jg .row ; then sb_draw
|
||||
|
||||
; The scrollbar of box_lib at the right of the list, as high as it
|
||||
sb_draw:
|
||||
call sb_set
|
||||
push sb
|
||||
call [scrollbar_v_draw]
|
||||
ret
|
||||
|
||||
; One line of the list at y = ebp: the captions if eax = 0, lines between
|
||||
; them, the sorted one with an arrow, otherwise the cells of row eax in color
|
||||
; ecx on background edx. Left or right as col_left says.
|
||||
list_line:
|
||||
pusha
|
||||
mov ebx, PAD + 1 ; the left of the column
|
||||
mov esi, [list.cols]
|
||||
|
||||
.col:
|
||||
pusha
|
||||
|
||||
movzx edx, byte [esi + COL.field]
|
||||
add edx, eax
|
||||
test eax, eax
|
||||
jnz .cell
|
||||
|
||||
mov edx, [esi + COL.caption]
|
||||
mov ecx, [sc.work_text]
|
||||
jmp .draw
|
||||
|
||||
.cell:
|
||||
call cell_text
|
||||
|
||||
.draw:
|
||||
call col_width ; the text in the cell
|
||||
lea eax, [ebx + eax - CELL_PAD]
|
||||
xchg eax, ebx
|
||||
add eax, CELL_PAD
|
||||
mov edi, text_buf
|
||||
call fmt_clip
|
||||
|
||||
mov edx, edi
|
||||
call col_left
|
||||
jc @f
|
||||
mov eax, edx
|
||||
call text_width
|
||||
neg eax
|
||||
add eax, ebx
|
||||
|
||||
@@:
|
||||
shl eax, 16
|
||||
mov ax, bp
|
||||
xchg eax, ebx
|
||||
call draw_text
|
||||
|
||||
cmp dword [esp + PUSHA_EAX], 0 ; the captions
|
||||
jne .picture
|
||||
|
||||
cmp esi, [list.cols] ; a line left of the column, but the
|
||||
je @f ; first one at the frame
|
||||
push ebx
|
||||
mov ebx, [esp + 4 + PUSHA_EBX] ; the left
|
||||
shl ebx, 16
|
||||
inc ebx
|
||||
mov ecx, ((AREA_Y + 1) shl 16) + HDR_H
|
||||
mcall SF_DRAW_RECT, , , [sc.work_graph]
|
||||
pop ebx
|
||||
|
||||
@@:
|
||||
cmp esi, [list.sort]
|
||||
jne .next
|
||||
mov edi, [list.desc]
|
||||
|
||||
sub ebx, 5 shl 16 ; 2 pixels before the caption on the
|
||||
call col_left ; right, after the one on the left
|
||||
jnc @f
|
||||
|
||||
mov eax, text_buf
|
||||
call text_width
|
||||
add eax, 11
|
||||
shl eax, 16
|
||||
add ebx, eax
|
||||
|
||||
@@:
|
||||
call draw_arrow
|
||||
jmp .next
|
||||
|
||||
.picture: ; a bar or an icon in a row
|
||||
movzx edx, byte [esi + COL.field]
|
||||
add edx, [esp + PUSHA_EAX] ; the row
|
||||
mov edx, [edx]
|
||||
call col_width
|
||||
cmp byte [esi + COL.kind], KIND_BAR
|
||||
jb .next
|
||||
ja .icon
|
||||
|
||||
mov ebx, [esp + PUSHA_EBX] ; the bar across the cell
|
||||
add ebx, CELL_PAD
|
||||
shl ebx, 16
|
||||
sub eax, 2*CELL_PAD
|
||||
mov bx, ax
|
||||
movzx ecx, bp
|
||||
shl ecx, 16
|
||||
mov cx, TEXT_H
|
||||
xchg eax, edx
|
||||
mov edx, [sc.work_light]
|
||||
call frame_rect
|
||||
|
||||
cmp eax, -1
|
||||
je .next
|
||||
add ebx, 2 shl 16 - 4 ; a light line around it, from the
|
||||
add ecx, 2 shl 16 - 4 ; selected row too
|
||||
movzx edx, bx
|
||||
mul edx
|
||||
shr eax, 10
|
||||
mov bx, ax
|
||||
mcall SF_DRAW_RECT, , , [sc.work_button] ; as the graphs
|
||||
jmp .next
|
||||
|
||||
.icon:
|
||||
sub eax, ICON ; in the middle of the cell
|
||||
shr eax, 1
|
||||
add eax, [esp + PUSHA_EBX]
|
||||
shl eax, 16
|
||||
lea ecx, [ebp - (ICON - TEXT_H)/2]
|
||||
mov ax, cx
|
||||
xchg eax, ebx
|
||||
xchg eax, edx
|
||||
mov edx, [esp + PUSHA_SIZE + PUSHA_EDX] ; of the first one:
|
||||
; the background
|
||||
call draw_icon
|
||||
|
||||
.next:
|
||||
call col_width ; the next column after this one
|
||||
add [esp + PUSHA_EBX], eax ; its left
|
||||
popa
|
||||
|
||||
add esi, sizeof.COL
|
||||
cmp esi, [list.cols_end]
|
||||
jb .col
|
||||
popa
|
||||
ret
|
||||
|
||||
; esi -> column, edx -> its field in the row; out: edx -> the text of the
|
||||
; cell, "" for a bar or an icon
|
||||
cell_text:
|
||||
cmp byte [esi + COL.kind], KIND_STR
|
||||
jb .done
|
||||
mov edx, [edx]
|
||||
je .done
|
||||
|
||||
mov eax, edx
|
||||
mov edi, text_buf
|
||||
mov edx, edi
|
||||
mov byte [edi], 0 ; -1: unknown, nothing to show
|
||||
cmp eax, -1
|
||||
je .done
|
||||
|
||||
cmp byte [esi + COL.kind], KIND_SIZE
|
||||
jb .uint
|
||||
ja .hex
|
||||
jmp fmt_size
|
||||
|
||||
.hex:
|
||||
cmp byte [esi + COL.kind], KIND_HEX ; a bar or an icon: drawn below
|
||||
jne .done
|
||||
jmp fmt_hex
|
||||
|
||||
.uint:
|
||||
call fmt_uint
|
||||
cmp byte [esi + COL.kind], KIND_PCT
|
||||
jne .done
|
||||
mov word [edi], "%"
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; esi -> column; out: CF = 1 if its caption and text go left: text and the
|
||||
; widest column, but the bar
|
||||
col_left:
|
||||
cmp byte [esi + COL.kind], KIND_NUM ; text: CF = 1
|
||||
jb .done
|
||||
cmp byte [esi + COL.kind], KIND_BAR ; the bar and icons: CF = 0
|
||||
jae .done
|
||||
cmp byte [esi + COL.width], 1 ; the widest: CF = 1
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; esi -> column; out: eax = its width
|
||||
col_width:
|
||||
movzx eax, byte [esi + COL.width]
|
||||
test eax, eax
|
||||
jnz @f
|
||||
mov eax, [col_rest]
|
||||
|
||||
@@:
|
||||
ret
|
||||
|
||||
; The end of a scan: ebp -> the end of the view.
|
||||
list_done:
|
||||
sub ebp, [list.view]
|
||||
shr ebp, 2
|
||||
mov [list.count], ebp ; then list_sort
|
||||
|
||||
; Sort the view by the sorted column and find the selected row again.
|
||||
list_sort:
|
||||
mov ebp, [list.view]
|
||||
mov ecx, 1 ; insertion sort, stable
|
||||
|
||||
.outer:
|
||||
cmp ecx, [list.count]
|
||||
jae .select
|
||||
mov esi, [ebp + ecx*4]
|
||||
mov ebx, ecx
|
||||
|
||||
.inner:
|
||||
mov edi, [ebp + ebx*4 - 4]
|
||||
call list_less
|
||||
jnc .put
|
||||
mov [ebp + ebx*4], edi
|
||||
dec ebx
|
||||
jnz .inner
|
||||
|
||||
.put:
|
||||
mov [ebp + ebx*4], esi
|
||||
inc ecx
|
||||
jmp .outer
|
||||
|
||||
.select:
|
||||
mov ecx, [list.count]
|
||||
mov eax, [list.key]
|
||||
|
||||
@@:
|
||||
dec ecx
|
||||
js @f
|
||||
mov esi, [ebp + ecx*4]
|
||||
cmp [esi], eax
|
||||
jne @b
|
||||
mov [list.sel], ecx
|
||||
|
||||
@@:
|
||||
ret
|
||||
|
||||
; esi, edi -> rows; out: CF = 1 if esi goes before edi
|
||||
list_less:
|
||||
pusha
|
||||
mov ebx, [list.sort]
|
||||
movzx ecx, byte [ebx + COL.field]
|
||||
add esi, ecx
|
||||
add edi, ecx
|
||||
|
||||
cmp [list.desc], 0
|
||||
je @f
|
||||
xchg esi, edi
|
||||
|
||||
@@:
|
||||
cmp byte [ebx + COL.kind], KIND_STR
|
||||
ja .num
|
||||
jb @f
|
||||
mov esi, [esi] ; the text by its pointer
|
||||
mov edi, [edi]
|
||||
|
||||
@@:
|
||||
lodsb ; the letters of either case alike
|
||||
mov ah, [edi]
|
||||
inc edi
|
||||
mov dl, al
|
||||
or ax, 0x2020
|
||||
cmp al, ah
|
||||
jne @f
|
||||
test dl, dl
|
||||
jz @f
|
||||
cmp byte [edi - 1], 0 ; the end of edi, not a blank
|
||||
jne @b
|
||||
|
||||
@@:
|
||||
popa
|
||||
ret
|
||||
|
||||
.num: ; -1, unknown, before 0
|
||||
mov eax, [esi]
|
||||
inc eax
|
||||
mov edx, [edi]
|
||||
inc edx
|
||||
cmp eax, edx
|
||||
popa
|
||||
ret
|
||||
|
||||
; An arrow up, or down if edi = 1: a triangle of 4 lines, line i of 2*i + 1
|
||||
; pixels, its tip at x = ebx shr 16, around the middle of the capitals of
|
||||
; text at y = bx.
|
||||
draw_arrow:
|
||||
pusha
|
||||
lea ecx, [edi*2 + edi + TEXT_H/2 - 2] ; from the top if it
|
||||
add cx, bx ; goes up, else from the bottom
|
||||
shl ecx, 16
|
||||
inc ecx
|
||||
|
||||
shl edi, 17 ; the next line: 1 down or up
|
||||
neg edi
|
||||
add edi, 1 shl 16
|
||||
|
||||
mov bx, 1
|
||||
mov esi, 4
|
||||
|
||||
@@:
|
||||
mcall SF_DRAW_RECT, , , [sc.work_text]
|
||||
add ebx, (-1 shl 16) + 2
|
||||
add ecx, edi
|
||||
dec esi
|
||||
jnz @b
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
; eax = rows the wheel moves, esi = mouse buttons: box_lib moves the list,
|
||||
; again while held; out: ebp = list.first before, drawn again if it changes
|
||||
scroll_mouse:
|
||||
mov ebp, [list.first]
|
||||
add [list.first], eax
|
||||
|
||||
call sb_set
|
||||
|
||||
xor eax, eax
|
||||
mov edi, [rows] ; all rows seen: no thumb to drag
|
||||
cmp edi, [list.count]
|
||||
jae @f
|
||||
|
||||
push sb
|
||||
call [scrollbar_v_mouse]
|
||||
|
||||
mov eax, [sb.position]
|
||||
xchg eax, [list.first]
|
||||
sub eax, [list.first] ; moved while held: again after 10
|
||||
jz @f ; waits of the main loop if pressed
|
||||
|
||||
mov eax, esi ; now, else after 2
|
||||
and eax, MB_LEFT
|
||||
jz @f
|
||||
mov al, 2
|
||||
test esi, MB_LEFT_DOWN
|
||||
jz @f
|
||||
mov al, 10
|
||||
|
||||
@@:
|
||||
mov [repeat_at], eax
|
||||
ret
|
||||
|
||||
sb_set: ; the list state to it
|
||||
mov eax, [area_w]
|
||||
add eax, PAD - SB_W
|
||||
mov [sb.x_pos], ax
|
||||
mov eax, [area_h]
|
||||
mov [sb.y_size], ax
|
||||
|
||||
mov [sb.all_redraw], 1
|
||||
mov edi, sb.max_area
|
||||
|
||||
mov eax, [list.count]
|
||||
stosd
|
||||
mov eax, [rows]
|
||||
stosd
|
||||
mov eax, [list.first]
|
||||
stosd
|
||||
mov eax, [sc.work_dark]
|
||||
stosd
|
||||
mov eax, [mid]
|
||||
stosd
|
||||
mov eax, [sc.work_graph]
|
||||
stosd
|
||||
ret
|
||||
|
||||
; Keep sel and first in range and remember the selected row.
|
||||
list_clamp:
|
||||
pusha
|
||||
mov ecx, [list.count]
|
||||
mov edi, list.sel
|
||||
call clamp
|
||||
|
||||
jecxz @f
|
||||
mov edx, [list.view]
|
||||
mov eax, [edx + eax*4]
|
||||
mov eax, [eax]
|
||||
mov [list.key], eax
|
||||
|
||||
@@:
|
||||
popa
|
||||
|
||||
pusha ; first in range
|
||||
mov ecx, [list.count]
|
||||
sub ecx, [rows]
|
||||
inc ecx
|
||||
mov edi, list.first
|
||||
call clamp
|
||||
popa
|
||||
ret
|
||||
|
||||
clamp: ; [edi] into [0, ecx - 1]
|
||||
mov eax, [edi]
|
||||
cmp eax, ecx
|
||||
jl @f
|
||||
lea eax, [ecx - 1]
|
||||
|
||||
@@:
|
||||
test eax, eax
|
||||
jns @f
|
||||
xor eax, eax
|
||||
|
||||
@@:
|
||||
stosd
|
||||
ret
|
||||
|
||||
list_key: ; al = key
|
||||
mov esi, [list.keys]
|
||||
|
||||
.hotkey:
|
||||
mov ah, [esi + HOTKEY.key]
|
||||
test ah, ah
|
||||
jz .move
|
||||
add esi, sizeof.HOTKEY
|
||||
cmp ah, al
|
||||
jne .hotkey
|
||||
movzx eax, [esi - sizeof.HOTKEY + HOTKEY.trigger]
|
||||
jmp eax
|
||||
|
||||
.move:
|
||||
sub al, KEY_DOWN
|
||||
cmp al, KEY_PGUP - KEY_DOWN
|
||||
ja .done
|
||||
|
||||
movzx eax, al
|
||||
movsx edx, byte [.moves + eax*2 + 1]
|
||||
imul edx, [rows]
|
||||
movsx eax, byte [.moves + eax*2]
|
||||
add edx, eax
|
||||
|
||||
add [list.sel], edx
|
||||
call list_clamp
|
||||
|
||||
mov ebx, [list.sel] ; scroll to the selection
|
||||
mov ecx, [rows]
|
||||
sub ebx, ecx
|
||||
inc ebx
|
||||
sub [list.first], ebx
|
||||
mov edi, list.first
|
||||
call clamp
|
||||
add [list.first], ebx
|
||||
jmp list_rows
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; rows, pages for the keys KEY_DOWN..KEY_PGUP: down, up, right, home, end,
|
||||
; del, pgdn, pgup
|
||||
.moves db 1, 0, -1, 0, 0, 0, 0, -128, 0, 127, 0, 0, 0, 1, 0, -1
|
||||
|
||||
; Wheel scrolls; left button selects a row, sorts by a column or moves the
|
||||
; scrollbar; right click opens the row.
|
||||
list_mouse:
|
||||
call get_mouse
|
||||
imul eax, 3
|
||||
call scroll_mouse ; every event: it follows a drag
|
||||
|
||||
test esi, MB_LEFT + MB_RIGHT_DOWN
|
||||
jz .moved
|
||||
|
||||
sub ebx, PAD ; inside the list, left of the
|
||||
jle .moved ; scrollbar
|
||||
mov eax, [area_w]
|
||||
sub eax, SB_W
|
||||
cmp ebx, eax
|
||||
jge .moved
|
||||
|
||||
sub ecx, AREA_Y + HDR_H + 2
|
||||
jl .header
|
||||
|
||||
test esi, MB_LEFT_DOWN + MB_RIGHT_DOWN ; a row: not dragged to
|
||||
jz .moved
|
||||
|
||||
xchg eax, ecx
|
||||
xor edx, edx
|
||||
mov ecx, ROW_H
|
||||
div ecx
|
||||
cmp eax, [rows]
|
||||
jae .moved
|
||||
|
||||
add eax, [list.first]
|
||||
cmp eax, [list.count]
|
||||
jae .moved
|
||||
|
||||
mov [list.sel], eax
|
||||
shr esi, 9 ; MB_RIGHT_DOWN: 0 left, 1 right
|
||||
and esi, 1
|
||||
push [list.left + esi*4] ; the selection drawn, then list_rows
|
||||
jmp list_rows ; returns to the trigger
|
||||
|
||||
.moved: ; a drag of the thumb keeps its pixels
|
||||
cmp ebp, [list.first]
|
||||
jne list_rows
|
||||
ret
|
||||
|
||||
.header:
|
||||
cmp ecx, -(HDR_H + 1)
|
||||
jl .moved
|
||||
test esi, MB_LEFT_DOWN
|
||||
jz .moved
|
||||
|
||||
mov esi, [list.cols] ; the column under the cursor
|
||||
dec ebx
|
||||
|
||||
.col:
|
||||
call col_width
|
||||
sub ebx, eax
|
||||
jl .sort
|
||||
add esi, sizeof.COL
|
||||
cmp esi, [list.cols_end]
|
||||
jb .col
|
||||
ret
|
||||
|
||||
.sort: ; again: the other way, else its own
|
||||
xor eax, eax
|
||||
cmp byte [esi + COL.kind], KIND_PCT
|
||||
setae al
|
||||
cmp esi, [list.sort]
|
||||
jne .order
|
||||
mov eax, [list.desc]
|
||||
xor al, 1
|
||||
|
||||
.order:
|
||||
mov [list.desc], eax
|
||||
mov [list.sort], esi
|
||||
call list_sort
|
||||
jmp list_draw
|
||||
|
||||
; out: esi = mouse buttons held, in bits 8.. the ones pressed, not held at
|
||||
; the last event, and the mouse not moved since; ebx, ecx = x, y in the
|
||||
; client area; eax = the wheel
|
||||
get_mouse:
|
||||
mcall SF_MOUSE_GET, SSF_BUTTON_EXT
|
||||
mov esi, eax
|
||||
movzx eax, al
|
||||
xchg al, byte [buttons]
|
||||
shl eax, 8
|
||||
not eax
|
||||
and esi, eax
|
||||
|
||||
mcall SF_MOUSE_GET, SSF_WINDOW_POSITION
|
||||
movsx ecx, ax ; in the client area
|
||||
sar eax, 16
|
||||
xchg edx, eax
|
||||
|
||||
mcall SF_MOUSE_GET, SSF_SCROLL_DATA
|
||||
mov ebx, edx
|
||||
movsx eax, ax ; the wheel
|
||||
ret
|
||||
|
||||
no_keys db 0 ; HOTKEYs of a list without them
|
||||
|
||||
uglobal
|
||||
align 4
|
||||
list LIST
|
||||
rows dd ? ; that fit the panel
|
||||
col_rest dd ? ; the width of the widest column
|
||||
repeat_at dd ? ; waits till a held arrow repeats
|
||||
endg
|
||||
@@ -0,0 +1,94 @@
|
||||
; Strings in UTF-8; the caption starts with its encoding byte.
|
||||
|
||||
if lang eq ru_RU
|
||||
sz_title db 3, "Диспетчер задач", 0
|
||||
sz_tab_procs db "Процессы", 0
|
||||
sz_tab_perf db "Нагрузка", 0
|
||||
sz_tab_disks db "Диски", 0
|
||||
sz_col_free db "Свободно", 0
|
||||
sz_run db "Запустить...", 0
|
||||
sz_kill db "Завершить", 0
|
||||
sz_shutdown db "Завершение работы...", 0
|
||||
sz_info db "Детали", 0
|
||||
sz_system db "Системные", 0
|
||||
sz_col_name db "Имя", 0
|
||||
sz_col_cpu db "ЦП", 0
|
||||
sz_col_mem db "Память", 0
|
||||
sz_freq db "Частота", 0
|
||||
sz_mhz db " МГц", 0
|
||||
sz_uptime db "Время работы", 0
|
||||
sz_threads db "Потоки", 0
|
||||
sz_used db "Занято", 0
|
||||
sz_total db "Всего", 0
|
||||
sz_temp db "Температура", 0
|
||||
sz_net db "Сеть", 0
|
||||
sz_received db "Принято", 0
|
||||
sz_sent db "Отправлено", 0
|
||||
sz_crit db "Критическая", 0
|
||||
sz_units db " КБ", 0, " МБ", 0, " ГБ", 0, " ТБ", 0
|
||||
sz_bits db " бит/с", 0, " Кбит/с", 0, " Мбит/с", 0, " Гбит/с", 0
|
||||
|
||||
else if lang eq es_ES
|
||||
sz_title db 3, "Gestor de tareas", 0
|
||||
sz_tab_procs db "Procesos", 0
|
||||
sz_tab_perf db "Recursos", 0
|
||||
sz_tab_disks db "Discos", 0
|
||||
sz_col_free db "Libre", 0
|
||||
sz_run db "Ejecutar...", 0
|
||||
sz_kill db "Finalizar", 0
|
||||
sz_shutdown db "Apagar el sistema...", 0
|
||||
sz_info db "Detalles", 0
|
||||
sz_system db "Sistema", 0
|
||||
sz_col_name db "Nombre", 0
|
||||
sz_col_cpu db "CPU", 0
|
||||
sz_col_mem db "Memoria", 0
|
||||
sz_freq db "Frecuencia", 0
|
||||
sz_uptime db "Activo", 0
|
||||
sz_threads db "Hilos", 0
|
||||
sz_used db "En uso", 0
|
||||
sz_total db "Total", 0
|
||||
sz_temp db "Temperatura", 0
|
||||
sz_net db "Red", 0
|
||||
sz_received db "Recibido", 0
|
||||
sz_sent db "Enviado", 0
|
||||
sz_crit db "Crítica", 0
|
||||
|
||||
else
|
||||
sz_title db 3, "Task Manager", 0
|
||||
sz_tab_procs db "Processes", 0
|
||||
sz_tab_perf db "Performance", 0
|
||||
sz_tab_disks db "Disks", 0
|
||||
sz_col_free db "Free", 0
|
||||
sz_run db "Run...", 0
|
||||
sz_kill db "End", 0
|
||||
sz_shutdown db "Shut down...", 0
|
||||
sz_info db "Details", 0
|
||||
sz_system db "System", 0
|
||||
sz_col_name db "Name", 0
|
||||
sz_col_cpu db "CPU", 0
|
||||
sz_col_mem db "Memory", 0
|
||||
sz_freq db "Frequency", 0
|
||||
sz_uptime db "Uptime", 0
|
||||
sz_threads db "Threads", 0
|
||||
sz_used db "Used", 0
|
||||
sz_total db "Total", 0
|
||||
sz_temp db "Temperature", 0
|
||||
sz_net db "Network", 0
|
||||
sz_received db "Received", 0
|
||||
sz_sent db "Sent", 0
|
||||
sz_crit db "Critical", 0
|
||||
end if
|
||||
|
||||
if ~ lang eq ru_RU
|
||||
sz_mhz db " MHz", 0
|
||||
sz_units db " KB", 0, " MB", 0, " GB", 0, " TB", 0
|
||||
sz_bits db " bit/s", 0, " kbit/s", 0, " Mbit/s", 0, " Gbit/s", 0
|
||||
end if
|
||||
sz_col_id db "ID", 0
|
||||
if lang eq ru_RU | lang eq es_ES
|
||||
sz_col_num db "Nº", 0
|
||||
else
|
||||
sz_col_num db " #", 0
|
||||
end if
|
||||
sz_deg db " °C", 0
|
||||
sz_pct db "%", 0
|
||||
@@ -0,0 +1,386 @@
|
||||
; Temperature on the Performance tab: the sensor of the CPU (Intel from
|
||||
; Core, AMD from K8, Hygon, VIA C7, Nano and Zhaoxin; the rules are those
|
||||
; of Linux coretemp, k8temp, k10temp and via-cputemp), else the first one
|
||||
; of a monitoring chip of the board (hwmon.inc).
|
||||
|
||||
MSR_THERM_STATUS = 0x19C ; Intel: the core, the package,
|
||||
MSR_PKG_THERM = 0x1B1 ; TjMax in bits 16-23
|
||||
MSR_TEMP_TARGET = 0x1A2
|
||||
MSR_VIA_TEMP = 0x1423 ; Nano and Zhaoxin, C7
|
||||
MSR_C7_TEMP = 0x1169
|
||||
|
||||
AMD_NB = 0xC300 ; PCI 00:18.3, then its registers:
|
||||
K8_THERMTRIP = 0xC3E4 ; K8, the others to Family 16h
|
||||
NB_TEMP = 0xC3A4
|
||||
VENDOR_AMD = 0x1022
|
||||
VENDOR_HYGON = 0x1D94
|
||||
SMN_ZEN_TEMP = 0x59800 ; the address, the index register
|
||||
SMN_ZEN_INDEX = 0x60 ; on the root complex, 00:00.0
|
||||
SMN_F15_TEMP = 0xD8200CA4 ; Family 15h from model 60h
|
||||
SMN_F15_INDEX = 0xB8
|
||||
|
||||
; The sensor of the CPU, else the chip; the temperature graph if any.
|
||||
sensors_init:
|
||||
pusha
|
||||
call cpu_sensor
|
||||
cmp [cpu_temp], chip_temp
|
||||
je .chip
|
||||
|
||||
mcall SF_THREAD_CONTROL, SSF_CREATE_THREAD, msr_probe, probe_stack_top
|
||||
mov esi, 20 ; up to 0.2 s
|
||||
|
||||
@@:
|
||||
cmp [probe], 2
|
||||
je @f
|
||||
mcall SF_SLEEP, 1
|
||||
dec esi
|
||||
jnz @b
|
||||
|
||||
@@:
|
||||
cmp [probe], 0
|
||||
jne @f
|
||||
mov [cpu_temp], chip_temp ; the kernel killed the probe
|
||||
|
||||
@@:
|
||||
cmp [tjmax], 0
|
||||
jne .chip
|
||||
mov byte [tjmax], 100
|
||||
|
||||
.chip:
|
||||
cmp [cpu_temp], chip_temp ; the chip for a CPU without a sensor
|
||||
jne .temp
|
||||
call hwm_init
|
||||
test eax, eax
|
||||
jz @f
|
||||
|
||||
.temp:
|
||||
inc [temp_on] ; a graph for any sensor
|
||||
|
||||
@@:
|
||||
cmp [cpu_temp], intel_temp ; TjMax of Intel only
|
||||
je @f
|
||||
mov [temp_graph.info], no_info
|
||||
|
||||
@@:
|
||||
popa
|
||||
ret
|
||||
|
||||
; cpu_temp and what it reads, by the vendor and the model
|
||||
cpu_sensor:
|
||||
pushfd ; CPUID if the ID flag can be changed
|
||||
pop eax
|
||||
xor eax, 1 shl 21
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop ecx
|
||||
cmp eax, ecx
|
||||
jne .done
|
||||
|
||||
xor eax, eax
|
||||
cpuid
|
||||
mov esi, eax ; the last leaf
|
||||
mov edi, ebx ; vendor
|
||||
|
||||
mov eax, 1
|
||||
cpuid
|
||||
mov ebp, eax ; signature
|
||||
|
||||
movzx ecx, ah
|
||||
and cl, 0xF ; family
|
||||
movzx edx, al
|
||||
shr edx, 4 ; model
|
||||
|
||||
cmp cl, 6
|
||||
jb @f
|
||||
shr eax, 12
|
||||
and al, 0xF0
|
||||
or dl, al
|
||||
cmp cl, 0xF
|
||||
jne @f
|
||||
movzx eax, ah
|
||||
add ecx, eax
|
||||
|
||||
@@:
|
||||
cmp edi, "Genu"
|
||||
je intel_sensor
|
||||
cmp edi, " Sh" ; C7, Nano and Zhaoxin, the probe
|
||||
je via_sensor ; drops the others
|
||||
cmp edi, "Cent"
|
||||
je via_sensor
|
||||
cmp edi, "Auth"
|
||||
je amd_sensor
|
||||
cmp edi, "Hygo"
|
||||
je amd_sensor
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; ecx = family, edx = model, esi = the last leaf of CPUID, ebp = signature
|
||||
intel_sensor:
|
||||
cmp esi, 6
|
||||
jb .done
|
||||
push ecx edx
|
||||
mov eax, 6
|
||||
cpuid
|
||||
pop edx ecx
|
||||
|
||||
test al, 1 ; digital thermal sensor
|
||||
jz .done
|
||||
mov [cpu_temp], intel_temp
|
||||
test al, 1 shl 6 ; the package one
|
||||
jz @f
|
||||
mov [therm_msr], MSR_PKG_THERM
|
||||
mov [therm_valid], 1 shl 31 ; it has no "reading valid" bit
|
||||
|
||||
@@:
|
||||
cmp ecx, 6 ; TjMax: 100 before Nehalem,
|
||||
jne .done ; then from the CPU but on Atoms
|
||||
cmp edx, 0x1A
|
||||
jb .done
|
||||
mov esi, .atoms
|
||||
@@:
|
||||
lodsw
|
||||
test al, al
|
||||
jz @f ; 0: msr_probe reads it
|
||||
cmp al, dl
|
||||
jne @b
|
||||
@@:
|
||||
mov byte [tjmax], ah
|
||||
|
||||
cmp dl, 0x1C ; Pineview: stepping 10
|
||||
jne .done
|
||||
and ebp, 0xF
|
||||
cmp ebp, 10
|
||||
jne .done
|
||||
mov byte [tjmax], 100
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; TjMax of Atoms without MSR_TEMPERATURE_TARGET, and Xeon 7400
|
||||
.atoms db 0x1C, 90, 0x1D, 100, 0x26, 90, 0x27, 90, 0x35, 90, 0x36, 100, 0, 0
|
||||
|
||||
; ecx = family, edx = model
|
||||
via_sensor:
|
||||
mov eax, MSR_VIA_TEMP
|
||||
cmp ecx, 6
|
||||
ja @f
|
||||
cmp dl, 0xF
|
||||
jae @f
|
||||
mov ax, MSR_C7_TEMP
|
||||
|
||||
@@:
|
||||
mov [therm_msr], eax
|
||||
mov [cpu_temp], via_temp
|
||||
ret
|
||||
|
||||
; ecx = family, edx = model
|
||||
amd_sensor:
|
||||
cmp ecx, 0xF
|
||||
jb .done
|
||||
ja .k10
|
||||
|
||||
push edx ; K8 with a thermal sensor
|
||||
mov eax, 0x80000007
|
||||
cpuid
|
||||
test dl, 1
|
||||
pop edx
|
||||
jz .done
|
||||
|
||||
cmp dl, 0x69 ; revision G desktops read lower
|
||||
jb @f
|
||||
xchg eax, edx
|
||||
mov edi, .k8_mobile
|
||||
mov ecx, 3
|
||||
repne scasb
|
||||
je @f
|
||||
mov [k8_zero], 49 - 21
|
||||
@@:
|
||||
mov esi, k8_temp
|
||||
jmp .nb
|
||||
|
||||
.k10:
|
||||
mov eax, SMN_ZEN_TEMP ; Zen
|
||||
mov [smn_index], SMN_ZEN_INDEX
|
||||
cmp ecx, 0x17
|
||||
jae .smn
|
||||
|
||||
mov eax, SMN_F15_TEMP
|
||||
mov [smn_index], SMN_F15_INDEX
|
||||
cmp ecx, 0x15
|
||||
jne @f
|
||||
cmp edx, 0x60
|
||||
jae .smn
|
||||
|
||||
@@:
|
||||
cmp ecx, 0x16
|
||||
ja .done
|
||||
mov esi, amd_nb_temp
|
||||
|
||||
.nb:
|
||||
mov ecx, AMD_NB
|
||||
jmp .pci
|
||||
|
||||
.smn:
|
||||
mov [smn_addr], eax
|
||||
xor ecx, ecx
|
||||
mov esi, amd_smn_temp
|
||||
|
||||
.pci: ; esi = the procedure, if the
|
||||
call pci_read ; device is AMD or Hygon
|
||||
cmp ax, VENDOR_AMD
|
||||
je @f
|
||||
cmp ax, VENDOR_HYGON
|
||||
jne .done
|
||||
@@:
|
||||
mov [cpu_temp], esi
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
.k8_mobile db 0x6C, 0x7C, 0xC1
|
||||
|
||||
; ecx = device shl 8 + register on bus 0; out: eax
|
||||
pci_read: ; the callers keep ebx
|
||||
mcall SF_PCI, SSF_READ_DWORD
|
||||
ret
|
||||
|
||||
; out: eax = temperature of the CPU, CF = 1 if unknown
|
||||
via_temp:
|
||||
call read_therm
|
||||
and eax, 0xFFFFFF
|
||||
ret
|
||||
|
||||
; out: eax = the low dword of [therm_msr]
|
||||
read_therm:
|
||||
mcall SF_SYS_MISC, SSF_READ_MSR, , [therm_msr]
|
||||
ret
|
||||
|
||||
intel_temp:
|
||||
call read_therm
|
||||
or eax, [therm_valid] ; the reading is valid
|
||||
jns no_temp
|
||||
|
||||
shr eax, 16
|
||||
and eax, 0x7F
|
||||
neg eax
|
||||
add eax, [tjmax]
|
||||
clc
|
||||
ret
|
||||
|
||||
k8_temp:
|
||||
mov ecx, K8_THERMTRIP
|
||||
call pci_read
|
||||
|
||||
shr eax, 16
|
||||
movzx eax, al
|
||||
sub eax, [k8_zero]
|
||||
clc
|
||||
ret
|
||||
|
||||
amd_smn_temp:
|
||||
mcall SF_PCI, SSF_WRITE_DWORD, [smn_index], [smn_addr]
|
||||
add ecx, 4 ; the data after the index
|
||||
call pci_read
|
||||
|
||||
test eax, 1 shl 19 ; the range is -49..206
|
||||
jz amd_temp
|
||||
or eax, 3 shl 16
|
||||
jmp amd_temp
|
||||
|
||||
amd_nb_temp:
|
||||
mov ecx, NB_TEMP
|
||||
call pci_read ; then amd_temp
|
||||
|
||||
; eax = the reported temperature of AMD
|
||||
amd_temp:
|
||||
mov edx, eax
|
||||
shr eax, 24 ; 1/8 of a degree from bit 21
|
||||
and edx, 3 shl 16
|
||||
cmp edx, 3 shl 16
|
||||
jne @f
|
||||
sub eax, 49
|
||||
|
||||
@@:
|
||||
clc
|
||||
ret
|
||||
|
||||
chip_temp: ; none in the CPU: the first of the chip
|
||||
mov eax, [hwm_temp]
|
||||
jmp @b
|
||||
|
||||
no_temp:
|
||||
stc
|
||||
ret
|
||||
|
||||
; A thread reads the MSRs first: if one is not there, the kernel kills
|
||||
; the thread, not the program.
|
||||
msr_probe:
|
||||
call [cpu_temp]
|
||||
inc [probe]
|
||||
|
||||
cmp [tjmax], 0
|
||||
jne @f
|
||||
mcall SF_SYS_MISC, SSF_READ_MSR, , MSR_TEMP_TARGET
|
||||
shr eax, 16
|
||||
test al, al ; 0 in some virtual machines
|
||||
jz @f
|
||||
mov byte [tjmax], al
|
||||
|
||||
@@:
|
||||
inc [probe]
|
||||
mcall SF_TERMINATE_PROCESS
|
||||
|
||||
; Once a second: the sensors and the temperature for the graph
|
||||
sensors_read:
|
||||
pusha
|
||||
xor eax, eax
|
||||
call [hwm_read]
|
||||
cmp eax, 127 ; 127 and more: no sensor
|
||||
jb @f
|
||||
xor eax, eax
|
||||
@@:
|
||||
mov [hwm_temp], eax
|
||||
|
||||
call [cpu_temp]
|
||||
jnc .got
|
||||
mov eax, [last_temp] ; not valid this time
|
||||
|
||||
.got:
|
||||
mov [last_temp], eax
|
||||
mov edi, last_temp ; not below 0
|
||||
mov ecx, 1000
|
||||
call clamp
|
||||
|
||||
mov ecx, [hist_pos]
|
||||
mov [hist_temp + ecx*4], eax
|
||||
popa
|
||||
ret
|
||||
|
||||
; An ITEM of temp_info
|
||||
get_tjmax:
|
||||
mov eax, [tjmax]
|
||||
call fmt_uint ; then deg_unit
|
||||
|
||||
deg_unit:
|
||||
mov eax, sz_deg
|
||||
jmp fmt_unit
|
||||
|
||||
cpu_temp dd chip_temp ; the procedure
|
||||
therm_msr dd MSR_THERM_STATUS
|
||||
therm_valid dd 0
|
||||
tjmax dd 100
|
||||
k8_zero dd 49
|
||||
|
||||
uglobal
|
||||
align 4
|
||||
temp_on dd ? ; a graph of the temperature
|
||||
smn_addr dd ?
|
||||
smn_index dd ?
|
||||
last_temp dd ?
|
||||
probe dd ? ; 1: the sensor is read, 2: done
|
||||
rb 256
|
||||
probe_stack_top:
|
||||
hist_temp rd HIST_LEN
|
||||
endg
|
||||
@@ -0,0 +1,111 @@
|
||||
; Statistics shared by the tabs, once a second: the threads, their CPU and
|
||||
; memory, the history of the graphs.
|
||||
|
||||
struct PROC ; an item of `procs`
|
||||
pid dd ?
|
||||
cpu dd ? ; cycles / 256, then percent
|
||||
mem dd ? ; KB
|
||||
name rb 12 ; zero padded
|
||||
ends
|
||||
|
||||
struct RAM_INFO ; function 18.20
|
||||
total dd ? ; pages
|
||||
free dd ?
|
||||
page_faults dd ?
|
||||
heap_size dd ? ; the kernel heap, bytes
|
||||
heap_free dd ?
|
||||
heap_blocks dd ?
|
||||
heap_free_blocks dd ?
|
||||
heap_max_free dd ?
|
||||
heap_max_used dd ?
|
||||
ends
|
||||
|
||||
; The threads, their CPU and memory, the history of the graphs.
|
||||
sample:
|
||||
pusha
|
||||
mov edi, procs
|
||||
xor edx, edx ; cycles of all threads / 256
|
||||
xor ecx, ecx
|
||||
|
||||
.slot:
|
||||
inc ecx
|
||||
mcall SF_THREAD_INFO, pinfo
|
||||
mov ebp, eax ; the last slot
|
||||
cmp [pinfo.slot_state], TSTATE_FREE
|
||||
je .next
|
||||
|
||||
mov eax, [ebx + process_information.PID]
|
||||
stosd ; PROC.pid
|
||||
mov eax, [ebx + process_information.cpu_usage]
|
||||
shr eax, 8 ; the sum fits 32 bits
|
||||
stosd ; PROC.cpu
|
||||
add edx, eax
|
||||
mov eax, [ebx + process_information.used_memory]
|
||||
inc eax
|
||||
shr eax, 10
|
||||
stosd ; PROC.mem
|
||||
|
||||
lea esi, [ebx + process_information.process_name]
|
||||
movsd ; PROC.name: 11 bytes and 0
|
||||
movsd
|
||||
movsd
|
||||
mov byte [edi - 1], 0
|
||||
|
||||
cmp edi, procs + MAX_PROCS * sizeof.PROC
|
||||
jae .done
|
||||
|
||||
.next:
|
||||
cmp ecx, ebp
|
||||
jb .slot
|
||||
|
||||
.done:
|
||||
mov [procs_end], edi
|
||||
|
||||
; Percent of CPU = cycles of the thread / 1% of cycles of all threads.
|
||||
xchg eax, edx
|
||||
cdq
|
||||
mov ecx, 100
|
||||
div ecx
|
||||
inc eax
|
||||
xchg eax, ecx
|
||||
|
||||
mov esi, procs
|
||||
@@:
|
||||
mov eax, [esi + PROC.cpu]
|
||||
cdq
|
||||
div ecx
|
||||
mov [esi + PROC.cpu], eax
|
||||
add esi, sizeof.PROC
|
||||
cmp esi, edi
|
||||
jb @b
|
||||
|
||||
inc [hist_pos] ; the place of this sample
|
||||
and [hist_pos], HIST_LEN - 1
|
||||
|
||||
mcall SF_SYSTEM, SSF_GET_RAM_INFO, ram_info
|
||||
mov eax, [ram_info.total]
|
||||
sub eax, [ram_info.free]
|
||||
imul eax, 100
|
||||
cdq
|
||||
div [ram_info.total]
|
||||
|
||||
call sensors_read
|
||||
call net_sample
|
||||
|
||||
mov ecx, [hist_pos]
|
||||
mov [hist_mem + ecx*4], eax
|
||||
mov eax, 100
|
||||
sub eax, dword [procs + PROC.cpu] ; the first thread is IDLE
|
||||
mov [hist_cpu + ecx*4], eax
|
||||
popa
|
||||
ret
|
||||
|
||||
uglobal
|
||||
align 4
|
||||
ram_info RAM_INFO
|
||||
hist_pos dd ?
|
||||
hist_cpu rd HIST_LEN
|
||||
hist_mem rd HIST_LEN
|
||||
procs_end dd ?
|
||||
procs rb MAX_PROCS * sizeof.PROC
|
||||
endg
|
||||
@@ -0,0 +1,231 @@
|
||||
; Autorun tab: the programs /sys/LAUNCHER starts from /sys/settings/autorun.dat.
|
||||
; A line is: program parameters delay; "text" may hold spaces, # starts
|
||||
; a comment. A program after # is turned off: the button or Space turns it
|
||||
; on or off in the file.
|
||||
|
||||
struct AR
|
||||
prog dd ?
|
||||
params dd ?
|
||||
delay dd ?
|
||||
num dd ? ; of the entry
|
||||
off db ? ; 1: after #, turned off
|
||||
ends
|
||||
|
||||
; Read the file, its lines into the list.
|
||||
autorun_load:
|
||||
mcall SF_FILE, autorun_info ; its size; read a byte more to see
|
||||
mov ecx, [autorun_bdfe.FileSizeLow] ; its end
|
||||
test eax, eax
|
||||
jz @f
|
||||
xor ecx, ecx
|
||||
|
||||
@@:
|
||||
inc ecx
|
||||
mov [autorun_file.Count], ecx
|
||||
inc ecx ; a # more, then 0
|
||||
inc ecx
|
||||
mcall SF_SYS_MISC, SSF_MEM_REALLOC, , [autorun_file.Buffer]
|
||||
mov [autorun_file.Buffer], eax
|
||||
mov [autorun_save.Buffer], eax
|
||||
mov ebp, [list.view]
|
||||
test eax, eax
|
||||
jz list_done
|
||||
|
||||
mcall SF_FILE, autorun_file
|
||||
cmp eax, 6 ; the end of the file: all of it
|
||||
je @f
|
||||
xor ebx, ebx
|
||||
|
||||
@@:
|
||||
mov esi, [autorun_file.Buffer]
|
||||
mov byte [esi + ebx], 0
|
||||
add ebx, esi
|
||||
|
||||
mov edi, esi ; the rows: at most the bytes that
|
||||
xor edx, edx ; may end a line, 0..13, and one
|
||||
|
||||
.count:
|
||||
inc edx
|
||||
@@:
|
||||
cmp edi, ebx
|
||||
jae @f
|
||||
cmp byte [edi], 14
|
||||
inc edi
|
||||
jb .count
|
||||
jmp @b
|
||||
|
||||
@@:
|
||||
imul ecx, edx, 4 + sizeof.AR ; the view, then the rows
|
||||
push ebx edx
|
||||
mcall SF_SYS_MISC, SSF_MEM_REALLOC, , [list.view]
|
||||
pop edx ebx
|
||||
mov [list.view], eax
|
||||
mov ebp, eax
|
||||
lea edi, [eax + edx*4]
|
||||
test eax, eax
|
||||
jz list_done
|
||||
|
||||
.line:
|
||||
cmp esi, ebx
|
||||
jae list_done
|
||||
|
||||
push esi
|
||||
@@:
|
||||
lodsb ; find the end of the line
|
||||
cmp al, 13
|
||||
je @f
|
||||
cmp al, 10
|
||||
je @f
|
||||
test al, al
|
||||
jnz @b
|
||||
|
||||
@@:
|
||||
mov byte [esi - 1], 0
|
||||
xchg esi, [esp]
|
||||
|
||||
call get_token ; the row goes to edi, its pointer to ebp
|
||||
cmp byte [eax], 0 ; empty line
|
||||
je .next
|
||||
cmp word [eax], "#/" ; a program turned off
|
||||
je @f
|
||||
cmp byte [eax], "#" ; comment
|
||||
je .next
|
||||
|
||||
@@:
|
||||
mov dl, [eax]
|
||||
mov [ebp], edi
|
||||
add ebp, 4
|
||||
stosd ; AR.prog, params, delay
|
||||
|
||||
call get_token
|
||||
stosd
|
||||
call get_token
|
||||
stosd
|
||||
|
||||
mov eax, ebp
|
||||
sub eax, [list.view]
|
||||
shr eax, 2
|
||||
stosd
|
||||
cmp dl, "#" ; AR.off
|
||||
sete al
|
||||
stosb
|
||||
|
||||
.next:
|
||||
pop esi
|
||||
jmp .line
|
||||
|
||||
; Put # before the selected program or take it away and save the file.
|
||||
autorun_toggle:
|
||||
cmp [list.count], 0 ; no rows, maybe no buffer
|
||||
je .done
|
||||
mcall SF_FILE, autorun_file ; the file again, as it is
|
||||
cmp eax, 6 ; all of it
|
||||
jne .done
|
||||
|
||||
mov edi, [list.key] ; AR.prog: the line in the buffer
|
||||
mov ecx, [autorun_file.Buffer]
|
||||
add ecx, ebx
|
||||
sub ecx, edi ; not past the end: the file was cut
|
||||
jbe .done
|
||||
|
||||
cmp byte [edi], "#"
|
||||
je .on
|
||||
|
||||
lea esi, [edi + ecx - 1] ; one byte on from the end
|
||||
lea edi, [esi + 1]
|
||||
std
|
||||
rep movsb
|
||||
cld
|
||||
|
||||
mov byte [edi], "#"
|
||||
inc ebx
|
||||
jmp .save
|
||||
|
||||
.on:
|
||||
lea esi, [edi + 1]
|
||||
dec ecx
|
||||
rep movsb
|
||||
dec ebx
|
||||
|
||||
.save:
|
||||
mov [autorun_save.Count], ebx
|
||||
mcall SF_FILE, autorun_save
|
||||
call autorun_load
|
||||
jmp list_rows
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; esi -> text; out: eax -> the next word or "text", cut with zero; esi after it
|
||||
get_token:
|
||||
mov eax, esi
|
||||
mov dh, [esi]
|
||||
test dh, dh
|
||||
jz .done
|
||||
inc esi
|
||||
cmp dh, " " ; skip blanks
|
||||
jbe get_token
|
||||
|
||||
mov cx, " " shl 8 ; a word ends with a blank
|
||||
cmp dh, '"'
|
||||
jne .next
|
||||
mov cx, '"' ; "text" with the quote
|
||||
mov eax, esi
|
||||
|
||||
.next:
|
||||
mov dh, [esi]
|
||||
test dh, dh
|
||||
jz .done
|
||||
inc esi
|
||||
sub dh, cl ; cl..cl + ch ends it
|
||||
cmp dh, ch
|
||||
ja .next
|
||||
|
||||
mov byte [esi - 1], 0
|
||||
.done:
|
||||
ret
|
||||
|
||||
autorun_bar:
|
||||
BAR BAR_BUTTON, sz_ar_toggle, sc.work_button
|
||||
db BAR_END
|
||||
|
||||
autorun_list LIST autorun_cols, autorun_cols_end, autorun_cols, nothing, nothing, autorun_keys, AR.off, 0, 0, 0, 0, 0, 0 ; the view on the heap
|
||||
autorun_keys:
|
||||
HOTKEY KEY_SPACE, autorun_toggle
|
||||
db 0
|
||||
autorun_cols:
|
||||
COL sz_col_num, AR.num, KIND_NUM, ID_W
|
||||
COL sz_col_program, AR.prog, KIND_STR, 0
|
||||
COL sz_col_params, AR.params, KIND_STR, COL_W
|
||||
COL sz_col_delay, AR.delay, KIND_STR, COL_W
|
||||
autorun_cols_end:
|
||||
|
||||
if lang eq ru_RU
|
||||
sz_tab_autorun db "Автозагрузка", 0
|
||||
sz_col_program db "Программа", 0
|
||||
sz_col_params db "Параметры", 0
|
||||
sz_col_delay db "Задержка", 0
|
||||
sz_ar_toggle db "Включить/выключить", 0
|
||||
else if lang eq es_ES
|
||||
sz_tab_autorun db "Inicio", 0
|
||||
sz_col_program db "Programa", 0
|
||||
sz_col_params db "Parámetros", 0
|
||||
sz_col_delay db "Retardo", 0
|
||||
sz_ar_toggle db "Activar/desactivar", 0
|
||||
else
|
||||
sz_tab_autorun db "Autorun", 0
|
||||
sz_col_program db "Program", 0
|
||||
sz_col_params db "Parameters", 0
|
||||
sz_col_delay db "Delay", 0
|
||||
sz_ar_toggle db "Turn on/off", 0
|
||||
end if
|
||||
|
||||
autorun_info FileInfoBlock SSF_GET_INFO, 0, 0, 0, autorun_bdfe, 0, sz_autorun
|
||||
autorun_file FileInfoBlock SSF_READ_FILE, 0, 0, 0, 0, 0, sz_autorun ; the buffer on
|
||||
autorun_save FileInfoBlock SSF_CREATE_FILE, 0, 0, 0, 0, 0, sz_autorun ; the heap
|
||||
sz_autorun db "/sys/settings/autorun.dat", 0
|
||||
|
||||
virtual at tab_data ; only the open tab uses it
|
||||
autorun_bdfe FileInfoA
|
||||
AUTORUN_DATA = $ - tab_data
|
||||
end virtual
|
||||
@@ -0,0 +1,343 @@
|
||||
; Disks tab: the partitions in a sortable list, the used space as a bar
|
||||
; across what the other columns leave. The kernel does not report free
|
||||
; space, so for memory disks (/rd, /tmp*) the space taken by files is summed
|
||||
; up. The disks are found in a thread, the tab is drawn at once.
|
||||
|
||||
struct DISK
|
||||
num dd ? ; in the order found, the key of the row
|
||||
icon dd ? ; in ICONS18, by the kind of the disk
|
||||
fill dd ? ; used, 1/1024 of the size, -1: unknown
|
||||
used dd ? ; KB, -1: unknown
|
||||
total dd ? ; KB
|
||||
name rb 16 ; the path
|
||||
label rb 28
|
||||
ends
|
||||
|
||||
MAX_DISKS = 16
|
||||
WALK_MAX = 1024 ; path length
|
||||
WALK_DEPTH = 16
|
||||
|
||||
; Start the thread that finds the disks.
|
||||
disks_scan:
|
||||
xor eax, eax
|
||||
mov [list.count], eax
|
||||
mov [list.first], eax
|
||||
mov [disk_n], eax
|
||||
mov [walk_stop], eax
|
||||
|
||||
inc [walking]
|
||||
mcall SF_THREAD_CONTROL, SSF_CREATE_THREAD, walker, walk_stack_top
|
||||
|
||||
inc eax ; -1: no thread, nothing to wait for
|
||||
jnz @f
|
||||
and [walking], 0
|
||||
@@:
|
||||
ret
|
||||
|
||||
; The walker found more: the view of the disks found so far, sorted.
|
||||
disks_update:
|
||||
xor eax, eax
|
||||
xchg eax, [walk_new]
|
||||
test eax, eax
|
||||
jz .done
|
||||
|
||||
mov esi, disks
|
||||
mov ebp, disks_view
|
||||
mov ecx, [disk_n]
|
||||
@@:
|
||||
mov [ebp], esi
|
||||
add ebp, 4
|
||||
add esi, sizeof.DISK
|
||||
loop @b
|
||||
|
||||
call list_done
|
||||
jmp list_rows
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
disks_open: ; the selected disk in Eolite
|
||||
cmp [list.count], 0
|
||||
je .done
|
||||
imul edx, [list.key], sizeof.DISK ; DISK.num
|
||||
add edx, disks + DISK.name
|
||||
mov esi, sz_eolite_path
|
||||
jmp run_app
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; The thread that finds the disks and sums up the files of memory disks.
|
||||
|
||||
disks_find:
|
||||
xor ebp, ebp ; device index in "/"
|
||||
|
||||
.device:
|
||||
mov word [walk_path], "/"
|
||||
call read_entry
|
||||
jnz .done
|
||||
|
||||
mov edi, walk_path + 1
|
||||
call fmt_str
|
||||
mov ecx, edi ; end of "/device"
|
||||
xor edx, edx ; partition index
|
||||
|
||||
.partition:
|
||||
mov byte [ecx], 0
|
||||
xchg ebp, edx
|
||||
call read_entry
|
||||
xchg ebp, edx
|
||||
jnz .device
|
||||
|
||||
cmp [disk_n], MAX_DISKS
|
||||
jae .done
|
||||
|
||||
mov edi, ecx
|
||||
mov byte [edi], "/"
|
||||
inc edi
|
||||
call fmt_str
|
||||
call disk_add
|
||||
jmp .partition
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; Read entry ebp of the folder [walk_path], ebp to the next one; out:
|
||||
; ZF = 1 if read, esi -> its name
|
||||
read_entry:
|
||||
cmp [walk_stop], 0 ; asked to stop: the thread ends
|
||||
jne walker.stop
|
||||
mov [fs_read.Position], ebp
|
||||
inc ebp
|
||||
mcall SF_FILE, fs_read
|
||||
mov esi, fs_entry.FileName
|
||||
test eax, eax
|
||||
ret
|
||||
|
||||
; [walk_path] = root of the partition, edi -> its end
|
||||
disk_add:
|
||||
pusha
|
||||
mcall SF_FILE, fs_info
|
||||
test eax, eax
|
||||
jnz .done
|
||||
|
||||
mov eax, [disk_n]
|
||||
imul ebx, eax, sizeof.DISK
|
||||
add ebx, disks
|
||||
mov [ebx + DISK.num], eax
|
||||
|
||||
mov ax, word [walk_path + 1] ; the kind by the device
|
||||
mov esi, disk_icons - 3
|
||||
@@:
|
||||
add esi, 3
|
||||
cmp word [esi], 0
|
||||
je @f
|
||||
cmp [esi], ax
|
||||
jne @b
|
||||
|
||||
@@:
|
||||
movzx eax, byte [esi + 2]
|
||||
mov [ebx + DISK.icon], eax
|
||||
|
||||
mov esi, walk_path
|
||||
lea edi, [ebx + DISK.name]
|
||||
mov ecx, DISK.label - DISK.name
|
||||
call copy_cut
|
||||
mov esi, fs_buf + FileInfoA.FileName ; of the partition
|
||||
lea edi, [ebx + DISK.label]
|
||||
mov ecx, sizeof.DISK - DISK.label
|
||||
call copy_cut
|
||||
|
||||
mov eax, [fs_buf + FileInfoA.FileSizeLow]
|
||||
mov edx, [fs_buf + FileInfoA.FileSizeHigh]
|
||||
shrd eax, edx, 10
|
||||
shr edx, 10 ; 4 TB and more: unknown
|
||||
jz @f
|
||||
or eax, -1
|
||||
@@:
|
||||
mov [ebx + DISK.total], eax
|
||||
or dword [ebx + DISK.used], -1
|
||||
or dword [ebx + DISK.fill], -1
|
||||
|
||||
inc [disk_n] ; listed when it is all there
|
||||
mov [walk_new], ebx
|
||||
test eax, eax
|
||||
jz .done
|
||||
|
||||
mov eax, dword [walk_path + 1]
|
||||
cmp ax, "rd"
|
||||
je @f
|
||||
and eax, 0xFFFFFF
|
||||
cmp eax, "tmp"
|
||||
jne .done
|
||||
|
||||
@@:
|
||||
xor ecx, ecx
|
||||
xor edx, edx
|
||||
mov edi, [esp + PUSHA_EDI] ; the end of the path
|
||||
call disk_walk
|
||||
|
||||
cmp ecx, [ebx + DISK.total] ; not more used than there is
|
||||
jbe @f
|
||||
mov ecx, [ebx + DISK.total]
|
||||
|
||||
@@:
|
||||
mov [ebx + DISK.used], ecx
|
||||
xchg eax, ecx
|
||||
mov edx, 1024
|
||||
mul edx
|
||||
div dword [ebx + DISK.total]
|
||||
mov [ebx + DISK.fill], eax
|
||||
mov [walk_new], ebx
|
||||
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
; esi -> text, edi -> a field of ecx bytes: the text, cut to fit it, not in
|
||||
; the middle of a character
|
||||
copy_cut:
|
||||
rep movsb
|
||||
|
||||
@@:
|
||||
dec edi
|
||||
mov al, [edi]
|
||||
and al, 0xC0
|
||||
cmp al, 0x80
|
||||
je @b
|
||||
mov [edi], cl
|
||||
ret
|
||||
|
||||
; The thread.
|
||||
walker:
|
||||
call disks_find
|
||||
|
||||
.stop:
|
||||
and [walking], 0
|
||||
mcall SF_TERMINATE_PROCESS
|
||||
|
||||
; Ask the walker to stop and wait till it is gone.
|
||||
stop_walker:
|
||||
mov [walk_stop], 1
|
||||
|
||||
@@:
|
||||
and [walk_new], 0
|
||||
cmp [walking], 0
|
||||
je @f
|
||||
mcall SF_SLEEP, 1
|
||||
jmp @b
|
||||
|
||||
@@:
|
||||
ret
|
||||
|
||||
; Add the size of files under [walk_path] to ecx, KB; edi -> end of the path,
|
||||
; edx = depth
|
||||
disk_walk:
|
||||
pusha
|
||||
xor ebp, ebp ; index in the folder
|
||||
inc edx
|
||||
|
||||
.next:
|
||||
call read_entry
|
||||
jnz .done
|
||||
|
||||
test byte [fs_entry.Attributes], FA_LABEL
|
||||
jnz .next
|
||||
test byte [fs_entry.Attributes], FA_FOLDER
|
||||
jnz .folder
|
||||
|
||||
mov eax, [fs_entry.FileSizeLow]
|
||||
add eax, 1023
|
||||
shr eax, 10
|
||||
add ecx, eax
|
||||
jmp .next
|
||||
|
||||
.folder:
|
||||
cmp byte [esi], "." ; skip "." and ".."
|
||||
jne @f
|
||||
cmp byte [esi + 1], 0
|
||||
je .next
|
||||
cmp word [esi + 1], "."
|
||||
je .next
|
||||
|
||||
@@:
|
||||
cmp edx, WALK_DEPTH
|
||||
jae .next
|
||||
|
||||
lea eax, [edi + 264]
|
||||
cmp eax, walk_path + WALK_MAX
|
||||
jae .next
|
||||
|
||||
push edi
|
||||
mov byte [edi], "/"
|
||||
inc edi
|
||||
call fmt_str
|
||||
call disk_walk
|
||||
pop edi
|
||||
mov byte [edi], 0
|
||||
jmp .next
|
||||
|
||||
.done:
|
||||
mov [esp + PUSHA_ECX], ecx
|
||||
popa
|
||||
ret
|
||||
|
||||
disks_bar:
|
||||
BAR BAR_BUTTON, sz_open, sc.work_button
|
||||
db BAR_END
|
||||
|
||||
disks_list LIST disks_cols, disks_cols_end, disks_cols + sizeof.COL, nothing, disks_open, disks_keys, 0, 0, 0, 0, 0, 0, tab_data
|
||||
disks_keys:
|
||||
HOTKEY KEY_ENTER, disks_open
|
||||
db 0
|
||||
disks_cols:
|
||||
COL sz_col_num, DISK.icon, KIND_ICON, ID_W
|
||||
COL sz_col_name, DISK.name, KIND_TEXT, COL_W
|
||||
COL sz_col_label, DISK.label, KIND_TEXT, COL_W
|
||||
COL sz_pct, DISK.fill, KIND_BAR, 0
|
||||
COL sz_used, DISK.used, KIND_SIZE, COL_W
|
||||
COL sz_col_size, DISK.total, KIND_SIZE, COL_W
|
||||
disks_cols_end:
|
||||
|
||||
if lang eq ru_RU
|
||||
sz_col_size db "Размер", 0
|
||||
sz_col_label db "Метка", 0
|
||||
sz_open db "Открыть", 0
|
||||
else if lang eq es_ES
|
||||
sz_col_size db "Tamaño", 0
|
||||
sz_col_label db "Etiqueta", 0
|
||||
sz_open db "Abrir", 0
|
||||
else
|
||||
sz_col_size db "Size", 0
|
||||
sz_col_label db "Label", 0
|
||||
sz_open db "Open", 0
|
||||
end if
|
||||
|
||||
sz_eolite_path db "/sys/File Managers/EOLITE", 0
|
||||
|
||||
; the first two letters of the device, the icon; the last one for the others
|
||||
disk_icons db "rd", 58, "tm", 51, "fd", 5, "cd", 19, "us", 57, 0, 0, 50
|
||||
|
||||
fs_read FileInfoBlock SSF_READ_FOLDER, 0, 1, 1, fs_buf, 0, walk_path ; cp866
|
||||
; names, one entry from Position on
|
||||
fs_info FileInfoBlock SSF_GET_INFO, 0, 3, 0, fs_buf, 0, walk_path ; UTF-8
|
||||
; volume label
|
||||
|
||||
uglobal
|
||||
disk_n dd ? ; the disks the walker found
|
||||
walking dd ?
|
||||
walk_stop dd ?
|
||||
walk_new dd ?
|
||||
rb 1024
|
||||
walk_stack_top:
|
||||
endg
|
||||
|
||||
virtual at tab_data ; only the open tab uses it
|
||||
disks_view rd MAX_DISKS
|
||||
disks rb MAX_DISKS * sizeof.DISK
|
||||
fs_buf FileInfoHeader ; then an entry of a folder; a
|
||||
fs_entry FileInfoA ; partition from fs_buf on
|
||||
walk_path rb WALK_MAX
|
||||
DISKS_DATA = $ - tab_data
|
||||
end virtual
|
||||
@@ -0,0 +1,92 @@
|
||||
; Drivers tab: the drivers loaded by the kernel (function 68.31).
|
||||
|
||||
struct DRV
|
||||
num dd ? ; in the list, the key of the row
|
||||
name rb 16 ; from here on the item of the kernel
|
||||
next dd ?
|
||||
handle dd ? ; the kernel keeps the previous item here
|
||||
base dd ?
|
||||
start dd ? ; the entry of the driver
|
||||
service dd ?
|
||||
ends
|
||||
|
||||
MAX_DRIVERS = 64
|
||||
|
||||
; The drivers the kernel has now.
|
||||
drivers_scan:
|
||||
mcall SF_SYS_MISC, SSF_GET_DRIVER_DATA, 1
|
||||
mov esi, ecx ; the last driver
|
||||
mov edx, ebx ; the first one
|
||||
|
||||
mov ebp, drivers_view
|
||||
mov edi, drivers + DRV.name
|
||||
|
||||
.next:
|
||||
cmp ebp, drivers_view + MAX_DRIVERS*4
|
||||
jae list_done
|
||||
|
||||
mcall SF_SYS_MISC, SSF_GET_DRIVER_DATA, 2
|
||||
test eax, eax
|
||||
jnz list_done
|
||||
|
||||
lea eax, [edi - DRV.name]
|
||||
mov [ebp], eax
|
||||
add ebp, 4
|
||||
|
||||
lea eax, [ebp - drivers_view]
|
||||
shr eax, 2
|
||||
mov dword [edi + DRV.num - DRV.name], eax
|
||||
|
||||
mov eax, dword [edi + DRV.next - DRV.name]
|
||||
mov dword [edi + DRV.handle - DRV.name], edx
|
||||
|
||||
add edi, sizeof.DRV
|
||||
cmp edx, esi
|
||||
mov edx, eax
|
||||
jne .next
|
||||
jmp list_done
|
||||
|
||||
drivers_load: ; RUN with the name of the driver to type
|
||||
mov esi, sz_run_path
|
||||
mov edx, sz_loaddrv
|
||||
jmp run_app
|
||||
|
||||
drivers_bar:
|
||||
BAR BAR_BUTTON, sz_load, sc.work_button
|
||||
db BAR_END
|
||||
|
||||
drivers_list LIST drivers_cols, drivers_cols_end, drivers_cols, nothing, nothing, no_keys, 0, 0, 0, 0, 0, 0, tab_data
|
||||
drivers_cols:
|
||||
COL sz_col_num, DRV.num, KIND_NUM, ID_W
|
||||
COL sz_col_name, DRV.name, KIND_TEXT, 0
|
||||
COL sz_col_handle, DRV.handle, KIND_HEX, COL_W
|
||||
COL sz_col_base, DRV.base, KIND_HEX, COL_W
|
||||
COL sz_col_service, DRV.service, KIND_HEX, COL_W
|
||||
drivers_cols_end:
|
||||
|
||||
if lang eq ru_RU
|
||||
sz_tab_drivers db "Драйверы", 0
|
||||
sz_col_handle db "Дескриптор", 0
|
||||
sz_col_base db "База", 0
|
||||
sz_col_service db "Сервис", 0
|
||||
sz_load db "Загрузить...", 0
|
||||
else if lang eq es_ES
|
||||
sz_tab_drivers db "Controladores", 0
|
||||
sz_col_handle db "Manejador", 0
|
||||
sz_col_base db "Base", 0
|
||||
sz_col_service db "Servicio", 0
|
||||
sz_load db "Cargar...", 0
|
||||
else
|
||||
sz_tab_drivers db "Drivers", 0
|
||||
sz_col_handle db "Handle", 0
|
||||
sz_col_base db "Base", 0
|
||||
sz_col_service db "Service", 0
|
||||
sz_load db "Load...", 0
|
||||
end if
|
||||
sz_loaddrv db "/sys/LOADDRV ", 0
|
||||
|
||||
virtual at tab_data ; only the open tab uses it
|
||||
drivers_view rd MAX_DRIVERS
|
||||
drivers rb MAX_DRIVERS * sizeof.DRV
|
||||
DRIVERS_DATA = $ - tab_data
|
||||
end virtual
|
||||
@@ -0,0 +1,532 @@
|
||||
; Performance tab: CPU, temperature when there is a sensor, memory and
|
||||
; network history in rows, lines between them. A row: the icon, the title
|
||||
; and the items on the left, the graph on the right.
|
||||
|
||||
GRAPH_STEP = 4 ; pixels per sample
|
||||
INFO_W = 256 + 2*PAD + ICON ; the icon, the title, the items, PAD
|
||||
NET_DEVICES = 16 ; of the kernel
|
||||
|
||||
struct G ; a graph
|
||||
title dd ?
|
||||
hist dd ? ; dwords up to the top
|
||||
hist2 dd ? ; 0, the network: received, sent
|
||||
info dd ? ; items left of the graph
|
||||
unit dd ? ; of the value in the title
|
||||
top dd ? ; -> the top of the scale
|
||||
on dd ? ; -> not 0 if shown
|
||||
icon dd ? ; before the title
|
||||
ends
|
||||
|
||||
struct ITEM ; a line left of a graph
|
||||
text dd ?
|
||||
get dd ? ; edi -> the text; out: edi after it
|
||||
ends
|
||||
|
||||
struct NET_BYTES ; of all the devices
|
||||
rx dq ?
|
||||
tx dq ?
|
||||
ends
|
||||
|
||||
perf_draw: ; eax = TAB.draw: with the frames,
|
||||
lea esi, [eax - TAB.update] ; TAB.update: esi = 0, without
|
||||
mov edi, shown ; the graphs there is data for
|
||||
mov eax, graphs
|
||||
|
||||
.shown:
|
||||
mov edx, [eax + G.on]
|
||||
cmp dword [edx], 0
|
||||
je @f
|
||||
stosd
|
||||
@@:
|
||||
add eax, sizeof.G
|
||||
cmp eax, graphs_end
|
||||
jb .shown
|
||||
|
||||
sub edi, shown
|
||||
shr edi, 2
|
||||
xchg edi, [shown_n]
|
||||
cmp edi, [shown_n] ; one came or went: all again
|
||||
je .draw
|
||||
test esi, esi
|
||||
jz draw_window
|
||||
|
||||
.draw:
|
||||
xor ebp, ebp
|
||||
.graph:
|
||||
call graph_frame
|
||||
call perf_graph
|
||||
inc ebp
|
||||
cmp ebp, [shown_n]
|
||||
jb .graph
|
||||
ret
|
||||
|
||||
; The button of the bar.
|
||||
perf_cpuid:
|
||||
mov esi, sz_cpuid_path
|
||||
jmp run_plain
|
||||
|
||||
; ebp = graph; out: ebx = x shl 16 + w, ecx = y shl 16 + h of its frame.
|
||||
; Between the rows a line, PAD from both.
|
||||
graph_frame:
|
||||
mov eax, [area_h]
|
||||
dec eax
|
||||
xor edx, edx
|
||||
div [shown_n] ; from a row to the next one
|
||||
|
||||
mov ecx, ebp
|
||||
imul ecx, eax
|
||||
add ecx, AREA_Y + 1 + PAD
|
||||
shl ecx, 16
|
||||
|
||||
sub eax, 2*PAD + 1
|
||||
mov cx, ax
|
||||
|
||||
mov ebx, (3*PAD + 1 + INFO_W) shl 16
|
||||
mov bx, word [area_w]
|
||||
sub bx, 2 + 3*PAD + INFO_W
|
||||
ret
|
||||
|
||||
; ecx = y shl 16 of a frame: the line between its row and the one above
|
||||
row_line:
|
||||
pusha
|
||||
shr ecx, 16
|
||||
sub ecx, PAD + 1 ; the middle of the gap above
|
||||
shl ecx, 16
|
||||
inc ecx
|
||||
|
||||
mov ebx, (PAD + 1) shl 16
|
||||
mov bx, word [area_w]
|
||||
sub bx, 2
|
||||
mcall SF_DRAW_RECT, , , [sc.work_graph]
|
||||
popa
|
||||
ret
|
||||
|
||||
; ebp = graph, ebx and ecx = its frame, esi = 0: no frame
|
||||
perf_graph:
|
||||
pusha
|
||||
test esi, esi
|
||||
jz .title
|
||||
mov edx, [sc.work_light]
|
||||
call frame_rect
|
||||
call row_line ; the first one on the panel border
|
||||
|
||||
.title:
|
||||
mov ebp, [shown + ebp*4]
|
||||
mov esi, [ebp + G.hist]
|
||||
mov edx, [ebp + G.hist2]
|
||||
|
||||
mov edi, [hist_pos] ; the last value
|
||||
mov eax, [esi + edi*4]
|
||||
test edx, edx
|
||||
jz @f
|
||||
add eax, [edx + edi*4] ; the network: both ways
|
||||
mov edi, text_buf
|
||||
call fmt_rate
|
||||
jmp .titled
|
||||
|
||||
@@:
|
||||
mov edi, text_buf
|
||||
call fmt_uint
|
||||
mov eax, [ebp + G.unit]
|
||||
call fmt_unit
|
||||
|
||||
.titled:
|
||||
call info_lines ; the lines left of it
|
||||
|
||||
mov eax, [ebp + G.top] ; the top: 100 %, TjMax, the network:
|
||||
mov eax, [eax] ; the largest rate of the columns
|
||||
|
||||
add ebx, 1 shl 16 - 2 ; bars inside the frame, newest on the right
|
||||
add ecx, 1 shl 16 - 2
|
||||
movzx edi, bx
|
||||
|
||||
test edx, edx
|
||||
jz .scaled
|
||||
call net_scale
|
||||
|
||||
.scaled:
|
||||
mov [scale], eax
|
||||
|
||||
mov ebp, [hist_pos]
|
||||
|
||||
.bar: ; the network: received on the left,
|
||||
mov eax, GRAPH_STEP ; sent on the right, lighter
|
||||
cmp edi, eax
|
||||
jae @f
|
||||
mov eax, edi
|
||||
|
||||
@@:
|
||||
mov bx, ax
|
||||
sub edi, eax
|
||||
pusha
|
||||
shl edi, 16
|
||||
add ebx, edi
|
||||
|
||||
mov edi, [sc.work_button]
|
||||
test edx, edx
|
||||
jz .last
|
||||
|
||||
mov eax, ebx
|
||||
shr ax, 1
|
||||
sub bx, ax
|
||||
call .value
|
||||
shl ebx, 16
|
||||
add eax, ebx
|
||||
xchg eax, ebx
|
||||
|
||||
mov esi, edx
|
||||
mov eax, [sc.work_light] ; sent: half way to the background
|
||||
mov edx, edi
|
||||
call mix
|
||||
xchg eax, edi
|
||||
|
||||
.last:
|
||||
call .value
|
||||
popa
|
||||
|
||||
dec ebp
|
||||
and ebp, HIST_LEN - 1
|
||||
test edi, edi
|
||||
jnz .bar
|
||||
|
||||
test edx, edx ; the network: its top at the top right
|
||||
jz .critical
|
||||
mov edi, text_buf
|
||||
mov eax, [scale]
|
||||
call fmt_rate
|
||||
mov ebx, [area_w]
|
||||
shl ebx, 16
|
||||
mov bx, [esp + PUSHA_ECX + 2] ; y of the frame
|
||||
add ebx, ((-6 - INFO_W + ICON + PAD) shl 16) + 4
|
||||
call info_value
|
||||
|
||||
@@:
|
||||
popa
|
||||
ret
|
||||
|
||||
.critical: ; the temperature: a line 10 below
|
||||
cmp esi, hist_temp ; the top
|
||||
jne @b
|
||||
|
||||
movzx eax, cx
|
||||
imul eax, 10
|
||||
div [scale] ; edx = G.hist2 = 0 here
|
||||
shl eax, 16
|
||||
add ecx, eax
|
||||
mov cx, 1
|
||||
|
||||
mov ebx, [esp + PUSHA_EBX] ; the frame
|
||||
add ebx, 1 shl 16 - 2
|
||||
mcall SF_DRAW_RECT, , , [red]
|
||||
jmp @b
|
||||
|
||||
; esi + ebp*4 -> value, edi = color: its bar at the bottom, the background
|
||||
; above it, not one over the other, so it does not flicker
|
||||
.value:
|
||||
pusha
|
||||
mov eax, [esi + ebp*4]
|
||||
cmp eax, [scale] ; not over the top
|
||||
jb @f
|
||||
mov eax, [scale]
|
||||
|
||||
@@:
|
||||
movzx esi, cx
|
||||
mul esi
|
||||
div [scale]
|
||||
xchg ebp, eax
|
||||
sub cx, bp
|
||||
mcall SF_DRAW_RECT, , , [sc.work_light]
|
||||
|
||||
movzx edx, cx
|
||||
shl edx, 16
|
||||
add ecx, edx
|
||||
mov cx, bp
|
||||
mcall SF_DRAW_RECT, , , edi
|
||||
popa
|
||||
ret
|
||||
|
||||
; esi, edx -> the history received and sent, edi = the width of the graph;
|
||||
; out: eax = its top, the largest rate shown up to 1, 2, 5, 10, 20, 50...
|
||||
; bit/s while it fits
|
||||
net_scale:
|
||||
push edi
|
||||
mov ebp, [hist_pos]
|
||||
xor eax, eax
|
||||
|
||||
.max:
|
||||
cmp eax, [esi + ebp*4]
|
||||
jae @f
|
||||
mov eax, [esi + ebp*4]
|
||||
@@:
|
||||
cmp eax, [edx + ebp*4]
|
||||
jae @f
|
||||
mov eax, [edx + ebp*4]
|
||||
|
||||
@@:
|
||||
dec ebp
|
||||
and ebp, HIST_LEN - 1
|
||||
sub edi, GRAPH_STEP
|
||||
jg .max
|
||||
pop edi
|
||||
|
||||
cmp eax, 2000000000
|
||||
ja .done
|
||||
|
||||
xor ebp, ebp
|
||||
inc ebp
|
||||
@@:
|
||||
cmp ebp, eax
|
||||
jae @f
|
||||
add ebp, ebp
|
||||
cmp ebp, eax
|
||||
jae @f
|
||||
lea ebp, [ebp*4 + ebp]
|
||||
shr ebp, 1
|
||||
cmp ebp, eax
|
||||
jae @f
|
||||
add ebp, ebp
|
||||
jmp @b
|
||||
|
||||
@@:
|
||||
xchg eax, ebp
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
; text_buf on the right of an item line at ebx = x shl 16 + y
|
||||
info_value:
|
||||
pusha
|
||||
mov ecx, [sc.work_text]
|
||||
mov edx, text_buf
|
||||
mov eax, edx
|
||||
call text_width
|
||||
|
||||
neg eax
|
||||
add eax, INFO_W - ICON - PAD
|
||||
shl eax, 16
|
||||
add ebx, eax
|
||||
|
||||
call draw_text
|
||||
popa
|
||||
ret
|
||||
|
||||
; ebp -> graph, ecx = y shl 16 + h of its frame, text_buf = its value:
|
||||
; the title and the items a line each as fit, the label on the left, the
|
||||
; value on the right. The ITEMs end with 0.
|
||||
info_lines:
|
||||
pusha
|
||||
movzx esi, cx ; the height left
|
||||
mov ebx, ((2*PAD + 1) shl 16) + INFO_W
|
||||
mcall SF_DRAW_RECT, , , [sc.work_light]
|
||||
|
||||
mov ebx, ecx ; the icon, the lines after it
|
||||
shr ebx, 16
|
||||
add ebx, (2*PAD + 1) shl 16 - 1
|
||||
mov eax, [ebp + G.icon]
|
||||
mov edx, [sc.work_light]
|
||||
call draw_icon
|
||||
add ebx, ((ICON + PAD) shl 16) + 1
|
||||
|
||||
mov edx, [ebp + G.title]
|
||||
mov ebp, [ebp + G.info]
|
||||
mov ecx, [sc.work_text]
|
||||
jmp .line
|
||||
|
||||
.item:
|
||||
mov edx, [ebp + ITEM.text]
|
||||
test edx, edx
|
||||
jz .done
|
||||
|
||||
mov edi, text_buf
|
||||
pusha
|
||||
call [ebp + ITEM.get]
|
||||
popa
|
||||
add ebp, sizeof.ITEM
|
||||
|
||||
.line:
|
||||
sub esi, 16
|
||||
jb .done
|
||||
call draw_text
|
||||
|
||||
mov eax, edx ; the value in the rest of the line
|
||||
call text_width
|
||||
|
||||
pusha
|
||||
mov ebx, INFO_W - 8 - ICON - PAD
|
||||
mov edx, text_buf
|
||||
mov edi, edx
|
||||
call fmt_clip
|
||||
popa
|
||||
|
||||
call info_value
|
||||
add ebx, 16
|
||||
jmp .item
|
||||
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
; Once a second: the bytes of the network devices, but the loopback.
|
||||
net_sample:
|
||||
pusha
|
||||
mov edi, net_sum
|
||||
xor eax, eax
|
||||
mov ecx, (net_last - net_sum) / 4 ; and net_up
|
||||
rep stosd
|
||||
|
||||
mov ebx, (NET_DEVICES - 1) shl 8
|
||||
|
||||
.device:
|
||||
push ebx ; bl = SSF_DEVICE_TYPE
|
||||
mcall SF_NETWORK_GET
|
||||
test eax, eax ; -1: none, 0: the loopback
|
||||
jle .next
|
||||
|
||||
inc [net_up]
|
||||
mov bl, SSF_RX_BYTE_COUNT
|
||||
mcall SF_NETWORK_GET
|
||||
add dword [net_sum.rx], eax
|
||||
adc dword [net_sum.rx + 4], ebx
|
||||
|
||||
mov ebx, [esp]
|
||||
mov bl, SSF_TX_BYTE_COUNT
|
||||
mcall SF_NETWORK_GET
|
||||
add dword [net_sum.tx], eax
|
||||
adc dword [net_sum.tx + 4], ebx
|
||||
|
||||
.next:
|
||||
pop ebx
|
||||
dec bh
|
||||
jns .device
|
||||
|
||||
mov ecx, [hist_pos]
|
||||
mov esi, net_sum.rx
|
||||
mov ebx, hist_rx
|
||||
call .rate
|
||||
mov ebx, hist_tx
|
||||
call .rate
|
||||
|
||||
or [net_primed], -1
|
||||
popa
|
||||
ret
|
||||
|
||||
.rate: ; since the last second, 0 at first
|
||||
mov eax, [esi]
|
||||
mov edx, [esi + 4]
|
||||
sub eax, [edi]
|
||||
sbb edx, [edi + 4]
|
||||
movsd ; the sum is the last one now
|
||||
movsd
|
||||
jae @f
|
||||
xor eax, eax ; a device went away
|
||||
|
||||
@@:
|
||||
shl eax, 3 ; bits
|
||||
and eax, [net_primed]
|
||||
mov [ebx + ecx*4], eax
|
||||
ret
|
||||
|
||||
; The items of the lines left of the graphs: edi -> the text; out:
|
||||
; edi after it.
|
||||
get_freq:
|
||||
mcall SF_SYSTEM, SSF_GET_CPU_FREQUENCY
|
||||
mov ecx, 1000000
|
||||
call fmt_quot
|
||||
mov eax, sz_mhz
|
||||
jmp fmt_unit
|
||||
|
||||
get_uptime:
|
||||
mcall SF_SYSTEM_GET, SSF_TIME_COUNT
|
||||
xor edx, edx
|
||||
mov ecx, 100
|
||||
div ecx
|
||||
jmp fmt_time
|
||||
|
||||
get_threads:
|
||||
mov eax, [procs_end]
|
||||
sub eax, procs
|
||||
mov ecx, sizeof.PROC ; then fmt_quot
|
||||
|
||||
; eax / ecx, edx = the remainder
|
||||
fmt_quot:
|
||||
xor edx, edx
|
||||
div ecx
|
||||
jmp fmt_uint
|
||||
|
||||
get_used:
|
||||
mov eax, [ram_info.total]
|
||||
sub eax, [ram_info.free]
|
||||
jmp @f
|
||||
|
||||
get_free:
|
||||
mov eax, [ram_info.free]
|
||||
jmp @f
|
||||
|
||||
get_total:
|
||||
mov eax, [ram_info.total]
|
||||
|
||||
@@:
|
||||
shl eax, 2 ; pages to KB
|
||||
jmp fmt_size
|
||||
|
||||
get_rx:
|
||||
mov esi, net_sum.rx
|
||||
mov ebx, hist_rx
|
||||
jmp @f
|
||||
|
||||
get_tx:
|
||||
mov esi, net_sum.tx
|
||||
mov ebx, hist_tx
|
||||
|
||||
@@: ; the rate, then the total
|
||||
mov eax, [hist_pos]
|
||||
mov eax, [ebx + eax*4]
|
||||
call fmt_rate
|
||||
mov word [edi], " ("
|
||||
scasw
|
||||
|
||||
mov eax, [esi]
|
||||
mov edx, [esi + 4]
|
||||
shrd eax, edx, 10
|
||||
call fmt_size
|
||||
mov word [edi], ")"
|
||||
inc edi
|
||||
ret
|
||||
|
||||
graphs:
|
||||
G sz_col_cpu, hist_cpu, 0, cpu_info, sz_pct, pct_top, pct_top, 48
|
||||
temp_graph G sz_temp, hist_temp, 0, temp_info, sz_deg, tjmax, temp_on, 68
|
||||
G sz_col_mem, hist_mem, 0, mem_info, sz_pct, pct_top, pct_top, 51
|
||||
G sz_net, hist_rx, hist_tx, net_info, 0, pct_top, net_up, 12
|
||||
graphs_end:
|
||||
pct_top dd 100
|
||||
perf_bar:
|
||||
BAR BAR_BUTTON, sz_cpuid_path + 5, sc.work_button ; "CPUID"
|
||||
db BAR_END
|
||||
sz_cpuid_path db "/sys/CPUID", 0
|
||||
cpu_info ITEM sz_freq, get_freq
|
||||
ITEM sz_uptime, get_uptime
|
||||
ITEM sz_threads, get_threads
|
||||
dd 0
|
||||
mem_info ITEM sz_used, get_used
|
||||
ITEM sz_col_free, get_free
|
||||
ITEM sz_total, get_total
|
||||
dd 0
|
||||
net_info ITEM sz_received, get_rx
|
||||
ITEM sz_sent, get_tx
|
||||
dd 0
|
||||
temp_info ITEM sz_crit, get_tjmax ; Intel
|
||||
no_info dd 0
|
||||
|
||||
uglobal
|
||||
align 4
|
||||
shown rd 4 ; -> graphs
|
||||
shown_n dd ?
|
||||
net_primed dd ?
|
||||
scale dd ? ; of the bars being drawn
|
||||
net_sum NET_BYTES
|
||||
net_up dd ? ; the devices, but the loopback
|
||||
net_last NET_BYTES
|
||||
hist_rx rd HIST_LEN ; bits a second
|
||||
hist_tx rd HIST_LEN
|
||||
endg
|
||||
@@ -0,0 +1,98 @@
|
||||
; Processes tab: the threads in a sortable list.
|
||||
|
||||
; The threads to show, then the whole list or the rows only.
|
||||
procs_draw:
|
||||
call procs_filter
|
||||
jmp list_draw
|
||||
|
||||
procs_update:
|
||||
call procs_filter
|
||||
jmp list_rows
|
||||
|
||||
; The threads to show, without the system ones unless asked.
|
||||
procs_filter:
|
||||
mov esi, procs
|
||||
mov ebp, procs_view
|
||||
|
||||
.next:
|
||||
cmp esi, [procs_end]
|
||||
jae list_done
|
||||
|
||||
cmp [show_system], 0
|
||||
jne .add
|
||||
|
||||
cmp esi, procs ; IDLE
|
||||
je .skip
|
||||
cmp byte [esi + PROC.name], "@"
|
||||
je .skip
|
||||
cmp dword [esi + PROC.name], "OS"
|
||||
je .skip
|
||||
|
||||
.add:
|
||||
mov [ebp], esi
|
||||
add ebp, 4
|
||||
|
||||
.skip:
|
||||
add esi, sizeof.PROC
|
||||
jmp .next
|
||||
|
||||
procs_button: ; edx = button id
|
||||
jmp [.btns + (edx - BTN_OWN)*4]
|
||||
.btns dd .system, procs_info, procs_kill, procs_run ; as in procs_bar
|
||||
|
||||
.system:
|
||||
xor [show_system], 1
|
||||
jmp draw_window
|
||||
|
||||
; The buttons: Run..., End, Details.
|
||||
procs_run:
|
||||
mov esi, sz_run_path
|
||||
jmp run_plain
|
||||
|
||||
procs_kill: ; the key of a row is its PID
|
||||
mcall SF_SYSTEM, SSF_TERMINATE_THREAD_ID, [list.key]
|
||||
ret
|
||||
|
||||
procs_info:
|
||||
mcall SF_SYSTEM, SSF_GET_THREAD_SLOT, [list.key]
|
||||
test eax, eax
|
||||
jz .done
|
||||
|
||||
mov edi, text_buf
|
||||
call fmt_uint
|
||||
|
||||
mov esi, sz_tinfo_path
|
||||
mov edx, text_buf
|
||||
jmp run_app
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
procs_bar:
|
||||
BAR BAR_CHECK, sz_system, show_system
|
||||
BAR BAR_BUTTON, sz_info, sc.work_button
|
||||
BAR BAR_BUTTON, sz_kill, red
|
||||
BAR BAR_GAP, 0, 0 ; away from End
|
||||
BAR BAR_BUTTON, sz_run, green
|
||||
db BAR_END
|
||||
|
||||
procs_list LIST procs_cols, procs_cols_end, procs_cols, nothing, procs_info, procs_keys, 0, 0, 0, 0, 0, 0, tab_data
|
||||
procs_keys:
|
||||
HOTKEY KEY_ENTER, procs_info
|
||||
HOTKEY KEY_DEL, procs_kill
|
||||
db 0
|
||||
procs_cols:
|
||||
COL sz_col_id, PROC.pid, KIND_NUM, ID_W
|
||||
COL sz_col_name, PROC.name, KIND_TEXT, 0
|
||||
COL sz_col_cpu, PROC.cpu, KIND_PCT, COL_W
|
||||
COL sz_col_mem, PROC.mem, KIND_SIZE, COL_W
|
||||
procs_cols_end:
|
||||
|
||||
uglobal
|
||||
show_system db ?
|
||||
endg
|
||||
|
||||
virtual at tab_data ; only the open tab uses it
|
||||
procs_view rd MAX_PROCS
|
||||
PROCS_DATA = $ - tab_data
|
||||
end virtual
|
||||
@@ -0,0 +1,344 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-only
|
||||
;
|
||||
; Task manager. A tab is a row of the `tabs` table: its caption, list
|
||||
; and handlers. To add a tab, add a row and an .inc file with the handlers.
|
||||
|
||||
include "../../KOSfuncs.inc"
|
||||
include "../../macros.inc"
|
||||
include "../../develop/libraries/box_lib/box_lib.mac"
|
||||
include "../../develop/libraries/libs-dev/libio/libio.inc"
|
||||
|
||||
format meos 01
|
||||
entry start
|
||||
|
||||
include "gui.inc"
|
||||
include "hwmon.inc"
|
||||
include "list.inc"
|
||||
include "locale.inc"
|
||||
include "sensors.inc"
|
||||
include "stats.inc"
|
||||
include "window.inc"
|
||||
|
||||
include "tabs/autorun.inc"
|
||||
include "tabs/disks.inc"
|
||||
include "tabs/drivers.inc"
|
||||
include "tabs/perf.inc"
|
||||
include "tabs/procs.inc"
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
start:
|
||||
mcall SF_SET_EVENTS_MASK, EVENTS
|
||||
|
||||
mcall SF_SYS_MISC, SSF_LOAD_DLL, box_lib_path
|
||||
test eax, eax
|
||||
jz exit
|
||||
xchg ecx, eax
|
||||
mov ebp, box_lib ; the names become the procs
|
||||
|
||||
.import:
|
||||
mov ebx, ecx
|
||||
.export:
|
||||
mov esi, [ebx]
|
||||
test esi, esi
|
||||
jz exit
|
||||
add ebx, 8
|
||||
mov edi, [ebp]
|
||||
@@:
|
||||
lodsb
|
||||
scasb
|
||||
jne .export
|
||||
test al, al
|
||||
jnz @b
|
||||
mov edx, [ebx - 4]
|
||||
mov [ebp], edx
|
||||
add ebp, 4
|
||||
cmp dword [ebp], 0
|
||||
jne .import
|
||||
|
||||
mcall SF_SYS_MISC, SSF_HEAP_INIT
|
||||
mcall SF_SYS_MISC, SSF_MEM_OPEN, icons_name, 0, 0 ; of @RESHARE
|
||||
mov [icons], eax
|
||||
|
||||
call sensors_init
|
||||
|
||||
reopen:
|
||||
call open_tab
|
||||
redraw:
|
||||
call draw_window
|
||||
|
||||
still:
|
||||
mcall SF_SYSTEM_GET, SSF_TIME_COUNT
|
||||
mov ebx, [next_tick]
|
||||
sub ebx, eax
|
||||
jg .wait
|
||||
|
||||
add eax, TICK
|
||||
mov [next_tick], eax
|
||||
call sample
|
||||
|
||||
mcall SF_THREAD_INFO, pinfo, -1
|
||||
test [pinfo.wnd_state], WND_MINIMIZED + WND_ROLLED_UP
|
||||
jnz still
|
||||
mov eax, TAB.update
|
||||
call tab_call
|
||||
jmp still
|
||||
|
||||
.wait:
|
||||
cmp [repeat_at], 0 ; an arrow held: the mouse again soon
|
||||
je @f
|
||||
mov ebx, 4
|
||||
|
||||
@@:
|
||||
mcall SF_WAIT_EVENT_TIMEOUT
|
||||
dec eax ; EV_REDRAW
|
||||
jz redraw
|
||||
dec eax ; EV_KEY
|
||||
jz key
|
||||
dec eax ; EV_BUTTON
|
||||
jz button
|
||||
|
||||
cmp al, EV_MOUSE - EV_BUTTON ; the mouse, or the time with
|
||||
je .mouse ; it held
|
||||
cmp al, EV_IDLE - EV_BUTTON
|
||||
jne still
|
||||
|
||||
cmp [repeat_at], 0 ; a held arrow when it is time
|
||||
je still
|
||||
dec [repeat_at]
|
||||
jnz still
|
||||
|
||||
.mouse:
|
||||
mov eax, TAB.mouse
|
||||
call tab_call
|
||||
jmp still
|
||||
|
||||
key:
|
||||
mcall SF_GET_KEY
|
||||
shr eax, 8
|
||||
|
||||
cmp al, KEY_ESC
|
||||
je exit
|
||||
cmp al, KEY_TAB ; the next tab
|
||||
je next_tab
|
||||
|
||||
call tab_list ; other keys are for lists
|
||||
jz still
|
||||
call list_key
|
||||
jmp still
|
||||
|
||||
button:
|
||||
mcall SF_GET_BUTTON
|
||||
shr eax, 8
|
||||
|
||||
cmp eax, 1
|
||||
je exit
|
||||
|
||||
cmp eax, BTN_OWN
|
||||
jae .own
|
||||
|
||||
sub eax, BTN_TAB
|
||||
cmp eax, BTN_SHUTDOWN - BTN_TAB
|
||||
jb switch_tab
|
||||
|
||||
mov esi, sz_end_path
|
||||
call run_plain
|
||||
jmp still
|
||||
|
||||
.own:
|
||||
xchg eax, edx
|
||||
mov eax, TAB.button
|
||||
call tab_call
|
||||
jmp still
|
||||
|
||||
next_tab:
|
||||
mov eax, [cur_tab]
|
||||
inc eax
|
||||
cmp eax, NTABS
|
||||
jb switch_tab
|
||||
xor eax, eax ; then switch_tab
|
||||
|
||||
switch_tab: ; eax = tab
|
||||
cmp eax, [cur_tab] ; the open one: nothing to do
|
||||
je still
|
||||
push eax
|
||||
call tab_list ; the old tab keeps its list
|
||||
mov esi, list
|
||||
call copy_list
|
||||
pop [cur_tab]
|
||||
jmp reopen
|
||||
|
||||
exit:
|
||||
call stop_walker
|
||||
mcall SF_TERMINATE_PROCESS
|
||||
|
||||
; Open the current tab: its list, then its activate handler.
|
||||
open_tab:
|
||||
and [repeat_at], 0
|
||||
call stop_walker
|
||||
|
||||
call tab_list
|
||||
mov esi, edi
|
||||
mov edi, list
|
||||
call copy_list
|
||||
|
||||
mov eax, TAB.activate
|
||||
tab_call: ; eax = handler in TAB
|
||||
imul ecx, [cur_tab], sizeof.TAB
|
||||
movzx ecx, word [tabs + ecx + eax]
|
||||
jmp ecx
|
||||
|
||||
nothing:
|
||||
ret
|
||||
|
||||
; out: edi -> list of the current tab or 0, ZF = 1 if 0
|
||||
tab_list:
|
||||
imul edi, [cur_tab], sizeof.TAB
|
||||
movzx edi, word [tabs + edi + TAB.list]
|
||||
test edi, edi
|
||||
ret
|
||||
|
||||
; Copy the list at esi to edi unless ZF = 1: the tab has none.
|
||||
copy_list:
|
||||
jz @f
|
||||
mov ecx, sizeof.LIST / 4
|
||||
rep movsd
|
||||
@@:
|
||||
ret
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; Settings
|
||||
MIN_W = 640 ; fits the longest bottom bar (ru_RU)
|
||||
MIN_H = 400 ; four graphs are still readable
|
||||
TICK = 100 ; statistics period, 1/100 s
|
||||
HIST_LEN = 1024 ; power of 2, the bars of a 4K wide window
|
||||
MAX_PROCS = 256
|
||||
|
||||
; Layout
|
||||
PAD = 8 ; margins and gaps
|
||||
TOP = 12 ; above the tabs
|
||||
TAB_H = 24
|
||||
AREA_Y = TOP + TAB_H - 1 ; top of the panel, the bottom of the tabs
|
||||
BTN_H = 24
|
||||
BTN_PAD = 12 ; text to the sides of a button
|
||||
CHECK = 14 ; checkbox
|
||||
ICON = 18 ; icons of @RESHARE
|
||||
TEXT_CHARS = 63 ; the longest text drawn
|
||||
TEXT_H = 14 ; 8x16 glyphs look centered as 14 lines
|
||||
|
||||
; The window and the text
|
||||
EVENTS = EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_MOUSE + EVM_MOUSE_FILTER
|
||||
WIN_STYLE = 0x73000000 ; skinned, a caption, coordinates in
|
||||
; the client area, not filled: drawn
|
||||
TEXT_UTF8 = 0xB0000000 ; asciiz, UTF-8, 8x16
|
||||
WND_MAXIMIZED = 1 ; process_information.wnd_state
|
||||
WND_MINIMIZED = 2
|
||||
WND_ROLLED_UP = 4
|
||||
|
||||
; Lists
|
||||
COL_W = 112
|
||||
ID_W = 3*8 + 2*CELL_PAD ; a number: ID, Nº or #, the arrow
|
||||
|
||||
KIND_TEXT = 0 ; zero ended text in the row, sorted ascending
|
||||
KIND_STR = 1 ; pointer to text
|
||||
KIND_NUM = 2
|
||||
KIND_PCT = 3 ; from here on sorted down at first
|
||||
KIND_SIZE = 4
|
||||
KIND_HEX = 5
|
||||
KIND_BAR = 6 ; 1/1024 of the cell filled
|
||||
KIND_ICON = 7 ; in ICONS18
|
||||
|
||||
HDR_H = 24 - 2 ; 24 with its lines, as an arrow
|
||||
ROW_H = 20
|
||||
SB_W = 24 ; scrollbar, as high as the list
|
||||
CELL_PAD = 8
|
||||
|
||||
; Keys and mouse buttons
|
||||
KEY_TAB = 9
|
||||
KEY_ENTER = 13
|
||||
KEY_SPACE = 32
|
||||
KEY_ESC = 27
|
||||
KEY_DOWN = 177 ; the moves in the lists up to
|
||||
KEY_DEL = 182
|
||||
KEY_PGUP = 184 ; here
|
||||
MB_LEFT = 1 ; held
|
||||
MB_LEFT_DOWN = 0x100 ; pressed, not held at the last event
|
||||
MB_RIGHT_DOWN = 0x200
|
||||
|
||||
; pusha: where it keeps the registers
|
||||
PUSHA_EDI = 0
|
||||
PUSHA_EBX = 16
|
||||
PUSHA_EDX = 20
|
||||
PUSHA_ECX = 24
|
||||
PUSHA_EAX = 28
|
||||
PUSHA_SIZE = 32
|
||||
|
||||
; Buttons
|
||||
BTN_TAB = 2
|
||||
BTN_SHUTDOWN = 8 ; ids with bit 3 go to the right
|
||||
BTN_OWN = 16 ; ids from here on belong to the tab
|
||||
|
||||
struct TAB ; a row of `tabs`
|
||||
caption dw ?
|
||||
list dw ? ; LIST or 0
|
||||
activate dw ? ; the tab is opened
|
||||
draw dw ? ; full redraw of the panel
|
||||
update dw ? ; new statistics
|
||||
button dw ? ; edx = button id
|
||||
mouse dw ?
|
||||
bar dw ? ; the items of its bottom bar
|
||||
ends
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
tabs:
|
||||
TAB sz_tab_procs, procs_list, nothing, procs_draw, procs_update, procs_button, list_mouse, procs_bar
|
||||
TAB sz_tab_perf, 0, nothing, perf_draw, perf_draw, perf_cpuid, get_mouse, perf_bar
|
||||
TAB sz_tab_disks, disks_list, disks_scan, list_draw, disks_update, disks_open, list_mouse, disks_bar
|
||||
TAB sz_tab_drivers, drivers_list, drivers_scan, list_draw, nothing, drivers_load, list_mouse, drivers_bar
|
||||
TAB sz_tab_autorun, autorun_list, autorun_load, list_draw, nothing, autorun_toggle, list_mouse, autorun_bar
|
||||
NTABS = ($ - tabs) / sizeof.TAB
|
||||
|
||||
app_info FileInfoBlock SSF_START_APP, 0, 0, 0, 0, 0, 0 ; the parameters, the path
|
||||
sz_run_path db "/sys/RUN", 0
|
||||
sz_end_path db "/sys/END", 0
|
||||
sz_tinfo_path db "/sys/TINFO", 0
|
||||
icons_name db "ICONS18", 0
|
||||
box_lib_path db "/sys/lib/box_lib.obj", 0
|
||||
align 4
|
||||
box_lib:
|
||||
import box_lib, \
|
||||
scrollbar_v_draw, "scrollbar_v_draw", \
|
||||
scrollbar_v_mouse, "scrollbar_v_mouse", \
|
||||
check_box_draw2, "check_box_draw2"
|
||||
sb scrollbar SB_W - 1, 0, 0, AREA_Y, SB_W - 1, 0, 0, 0, 0, 0, 0, 1 ; the sizes - 1:
|
||||
; box_lib draws a pixel more
|
||||
cb check_box2 0, 0, PAD, 0, 0, 0x80000000, cb.size_of_str, 0 ; no text: its length
|
||||
|
||||
IncludeUGlobals
|
||||
align 4
|
||||
sc system_colors ; the button color: the main one
|
||||
green dd ? ; of the button: run
|
||||
red dd ? ; and of high values, end
|
||||
mid dd ? ; the list header, the scrollbar
|
||||
pinfo process_information
|
||||
next_tick dd ?
|
||||
cur_tab dd ?
|
||||
buttons dd ? ; mouse buttons held at the last event
|
||||
area_w dd ? ; panel: x = PAD, y = AREA_Y
|
||||
area_h dd ?
|
||||
bar_y dd ? ; bottom bar
|
||||
bar_left dd ?
|
||||
bar_right dd ? ; left end of the right buttons
|
||||
icons dd ? ; ICONS18 or 0
|
||||
icon_buf rd ICON*ICON
|
||||
text_buf rb TEXT_CHARS * 4 + 1 ; UTF-8 takes up to 4 bytes
|
||||
|
||||
macro max_of name, [value] {
|
||||
common name = 0
|
||||
forward
|
||||
if value > name
|
||||
name = value
|
||||
end if
|
||||
}
|
||||
max_of TAB_DATA, PROCS_DATA, DISKS_DATA, DRIVERS_DATA, AUTORUN_DATA
|
||||
align 4
|
||||
tab_data rb TAB_DATA ; data of the open tab
|
||||
@@ -0,0 +1,240 @@
|
||||
; The window: its colors, size and place, the panel and the tabs, then the
|
||||
; panel of the open tab.
|
||||
|
||||
draw_window:
|
||||
mcall SF_REDRAW, SSF_BEGIN_DRAW
|
||||
mcall SF_STYLE_SETTINGS, SSF_GET_COLORS, sc, sizeof.system_colors
|
||||
|
||||
mov eax, [sc.work_button] ; its channels high to low: al, ah, dl
|
||||
mov edx, eax
|
||||
shr edx, 16
|
||||
cmp al, ah
|
||||
jae @f
|
||||
xchg al, ah
|
||||
@@:
|
||||
cmp al, dl
|
||||
jae @f
|
||||
xchg al, dl
|
||||
@@:
|
||||
cmp ah, dl
|
||||
jae @f
|
||||
xchg ah, dl
|
||||
|
||||
@@:
|
||||
movzx ecx, dl ; blue, green, red
|
||||
shl ecx, 16
|
||||
mov cx, ax
|
||||
mov [sc.work_button], ecx
|
||||
|
||||
mov dl, al ; the low ones half the high one
|
||||
shr dl, 1
|
||||
movzx ecx, dl ; all low, then green, red high
|
||||
imul ecx, 0x10101
|
||||
mov [green], ecx
|
||||
mov byte [green + 1], al
|
||||
mov [red], ecx
|
||||
mov byte [red + 2], al
|
||||
|
||||
mov eax, [sc.work] ; between the window and the panel
|
||||
mov edx, [sc.work_light]
|
||||
call mix
|
||||
mov [mid], eax
|
||||
|
||||
mcall SF_GET_SCREEN_SIZE ; half the screen, the kernel takes
|
||||
shr eax, 1 ; it the first time
|
||||
xchg esi, eax
|
||||
mcall SF_STYLE_SETTINGS, SSF_GET_SCREEN_AREA
|
||||
mov edx, esi
|
||||
shr edx, 16
|
||||
mov ebp, MIN_W - 1
|
||||
call .fit
|
||||
xchg eax, ebx
|
||||
movzx edx, si
|
||||
and dh, 0x7F
|
||||
mov ebp, MIN_H - 1
|
||||
call .fit
|
||||
xchg eax, ecx
|
||||
|
||||
mov edx, [sc.work]
|
||||
or edx, WIN_STYLE
|
||||
mcall SF_CREATE_WINDOW, , , , 0, sz_title
|
||||
|
||||
mcall SF_THREAD_INFO, pinfo, -1
|
||||
test [pinfo.wnd_state], WND_ROLLED_UP
|
||||
jnz .done
|
||||
test [pinfo.wnd_state], WND_MAXIMIZED ; the size it gets
|
||||
jnz .layout
|
||||
|
||||
mov edx, [pinfo.box.width] ; not smaller than the minimum
|
||||
mov esi, [pinfo.box.height]
|
||||
cmp edx, MIN_W - 1 ; the kernel keeps the size - 1
|
||||
jae @f
|
||||
mov edx, MIN_W - 1
|
||||
@@:
|
||||
cmp esi, MIN_H - 1
|
||||
jae @f
|
||||
mov esi, MIN_H - 1
|
||||
@@:
|
||||
cmp edx, [pinfo.box.width]
|
||||
jne @f
|
||||
cmp esi, [pinfo.box.height]
|
||||
je .layout
|
||||
|
||||
@@:
|
||||
mcall SF_CHANGE_WINDOW, -1, -1 ; it sends a new redraw
|
||||
jmp .done
|
||||
|
||||
.layout:
|
||||
mov eax, [pinfo.client_box.width]
|
||||
lea ecx, [eax - PAD*2]
|
||||
mov [area_w], ecx
|
||||
mov [bar_right], eax
|
||||
mov [bar_left], PAD
|
||||
|
||||
mov eax, [pinfo.client_box.height]
|
||||
sub eax, PAD + BTN_H
|
||||
mov [bar_y], eax
|
||||
sub eax, AREA_Y + PAD
|
||||
mov [area_h], eax
|
||||
|
||||
mov ebx, PAD shl 16
|
||||
mov bx, word [area_w]
|
||||
mov ecx, AREA_Y shl 16
|
||||
mov cx, ax
|
||||
mov edx, [sc.work_light]
|
||||
call frame_rect
|
||||
|
||||
mov edx, [sc.work] ; around the tabs and the panel: above,
|
||||
mov ebx, [area_w] ; below with the bar, left, right
|
||||
add ebx, 2*PAD + 1
|
||||
mcall SF_DRAW_RECT, , TOP
|
||||
|
||||
mov ecx, [bar_y]
|
||||
sub ecx, PAD
|
||||
shl ecx, 16
|
||||
mov cx, 2*PAD + BTN_H + 1
|
||||
mcall SF_DRAW_RECT
|
||||
|
||||
mov ecx, [area_h]
|
||||
add ecx, (TOP shl 16) + TAB_H - 1
|
||||
mov ebx, PAD
|
||||
mcall SF_DRAW_RECT
|
||||
|
||||
mov ebx, [area_w]
|
||||
add ebx, PAD
|
||||
shl ebx, 16
|
||||
mov bx, PAD + 1
|
||||
mcall SF_DRAW_RECT
|
||||
|
||||
mov esi, [area_w] ; the tabs as wide as the panel, the
|
||||
add esi, NTABS - 1 ; room left shared alike
|
||||
xor ebp, ebp
|
||||
@@:
|
||||
call .content
|
||||
sub esi, eax
|
||||
inc ebp
|
||||
cmp ebp, NTABS
|
||||
jb @b
|
||||
|
||||
xchg eax, esi
|
||||
xor edx, edx
|
||||
mov ecx, NTABS
|
||||
div ecx
|
||||
xchg eax, esi
|
||||
|
||||
mov ebx, PAD shl 16
|
||||
xor ebp, ebp
|
||||
|
||||
.tab:
|
||||
call .content
|
||||
add eax, esi
|
||||
cmp ebp, NTABS - 1 ; the last one to the end of the panel
|
||||
jne @f
|
||||
mov eax, [area_w]
|
||||
add eax, PAD
|
||||
mov edx, ebx
|
||||
shr edx, 16
|
||||
sub eax, edx
|
||||
|
||||
@@:
|
||||
mov bx, ax
|
||||
call .draw
|
||||
imul eax, ebx, 1 shl 16
|
||||
lea ebx, [ebx + eax - 1 shl 16] ; neighbours share the border
|
||||
inc ebp
|
||||
cmp ebp, NTABS
|
||||
jb .tab
|
||||
|
||||
mov eax, sz_shutdown ; at the right end
|
||||
mov edx, BTN_SHUTDOWN
|
||||
mov esi, [sc.work_graph]
|
||||
call bar_button
|
||||
|
||||
imul esi, [cur_tab], sizeof.TAB ; the bar of the tab, then its
|
||||
movzx esi, word [tabs + esi + TAB.bar] ; panel
|
||||
call bar_draw
|
||||
mov eax, TAB.draw
|
||||
call tab_call
|
||||
|
||||
.done:
|
||||
mcall SF_REDRAW, SSF_END_DRAW
|
||||
ret
|
||||
|
||||
; eax = start shl 16 + end of the work area, edx = the size - 1 wanted,
|
||||
; ebp = the least; out: eax = start shl 16 + size - 1 of the window in its
|
||||
; middle
|
||||
.fit:
|
||||
cmp edx, ebp
|
||||
jae @f
|
||||
mov edx, ebp
|
||||
|
||||
@@:
|
||||
movzx ecx, ax
|
||||
shr eax, 16
|
||||
sub ecx, eax
|
||||
cmp edx, ecx
|
||||
jb @f
|
||||
mov edx, ecx
|
||||
|
||||
@@:
|
||||
sub ecx, edx
|
||||
shr ecx, 1
|
||||
add eax, ecx
|
||||
shl eax, 16
|
||||
mov ax, dx
|
||||
ret
|
||||
|
||||
.draw: ; the caption in the middle
|
||||
pusha
|
||||
mov ecx, (TOP shl 16) + TAB_H
|
||||
mov esi, [sc.work_dark]
|
||||
cmp ebp, [cur_tab]
|
||||
jne @f
|
||||
mov esi, [sc.work_light]
|
||||
|
||||
@@:
|
||||
mov edx, esi
|
||||
call frame_rect
|
||||
|
||||
lea edx, [ebp + BTN_TAB + BT_HIDE + BT_NOFRAME]
|
||||
mcall SF_DEFINE_BUTTON
|
||||
|
||||
call .content
|
||||
movzx ecx, bx
|
||||
sub ecx, eax
|
||||
shr ecx, 1
|
||||
shl ecx, 16
|
||||
add ebx, ecx
|
||||
|
||||
mov ecx, TOP shl 16
|
||||
mov eax, [sc.work_text]
|
||||
jmp bar_text ; as high as the bar items
|
||||
|
||||
; ebp = tab; out: edi -> its caption, eax = its width
|
||||
.content:
|
||||
imul edi, ebp, sizeof.TAB
|
||||
movzx edi, word [tabs + edi + TAB.caption]
|
||||
mov eax, edi
|
||||
call text_width
|
||||
ret
|
||||
|
||||
Reference in new issue
Block a user