Compare commits

..
Author SHA1 Message Date
Burerandefpiem e268b223df libs/asm-xml: add the AsmXml XML parser as xml.obj
Test PR / Build (es_ES) (pull_request) Successful in 2m24s
Test PR / Build (ru_RU) (pull_request) Successful in 2m29s
Test PR / Build (en_US) (pull_request) Successful in 2m30s
AsmXml 1.4 by Marc Kerbiquet (BSD 3-clause, tibleiz.net), unmodified,
with a KolibriOS wrapper: COFF export table, lib_init and cdecl
adapters for the heap functions passed by the loader. It exports
lib_init and the ax_* functions used by FeedFlow and by the C--
header lib/obj/xml.h, and is shipped as /sys/lib/xml.obj.

Co-authored-by: efpiem <fpmastrorilli@gmail.com>
Assisted-by: Claude:claude-opus-5-5
2026-10-04 11:18:22 +03:00
Leency bd071d588b kernel/net: fix use-after-free on refused TCP connections (#622)
Build system / Build (en_US) (push) Successful in 3m2s
Build system / Build (es_ES) (push) Successful in 3m9s
Build system / Build (ru_RU) (push) Successful in 3m15s
Build system / Publish Images (push) Successful in 11m5s
tcp_input: on RST+ACK in SYN_SENT, unlock the socket mutex before
tcp_drop and leave through .drop_no_socket. tcp_drop frees the socket
and locks that mutex itself, so the network thread hung on it.

Assisted-by: Claude:claude-opus-5
Reviewed-on: #622
Reviewed-by: hidnplayr <hidnplayr@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: Kiril Lipatov <lipatov.kiril@gmail.com>
2026-09-29 19:12:30 +00:00
Leency 9ec66b0eba drivers/i8255x: get to work on a real device (#725)
Build system / Build (en_US) (push) Successful in 3m23s
Build system / Build (es_ES) (push) Successful in 3m27s
Build system / Build (ru_RU) (push) Successful in 3m31s
Build system / Publish Images (push) Successful in 11m54s
- the TX reclaim loop in int_handler multiplied sizeof.txfd by itself  (mul eax) instead of by last_tx, so it looked 1024 bytes past tx_ring and never freed a descriptor
- it also left txfd.status set, and transmit treats a non-zero status as busy, so once the 16-entry ring wrapped every send ended in "TX overrun": DHCP fell back to link-local, ping showed "Socket error", while the link still read as connected
- reclaim only descriptors the device completed (TXFD_STATUS_C) and zero their status; transmit now checks for an unreclaimed buffer (virt_addr)

Seen on an EtherExpress Pro/100 in a Pentium II. Reproduced in QEMU (-cpu pentium2, i82557b): ping stopped at the 12th reply every time; with the fix it runs indefinitely, also under a UDP flood.

Reviewed-on: #725
Reviewed-by: hidnplayr <hidnplayr@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-29 19:03:24 +00:00
Leency 95bcf78537 kernel/ahci: support CD/DVD drives (ATAPI) (#694)
Build system / Build (es_ES) (push) Successful in 3m34s
Build system / Build (en_US) (push) Successful in 3m39s
Build system / Build (ru_RU) (push) Successful in 3m46s
Build system / Publish Images (push) Successful in 10m4s
Summary: an optical drive on an AHCI port was detected and then ignored,
so CD/DVD only worked with the controller switched to IDE mode. It now
shows up as /srN and ISO9660 discs are readable, including disc changes.

Details:
- ahci_atapi_cmd sends a SCSI command through the ATA PACKET command
  (A bit in the command header, CDB in acmd, DMA when IDENTIFY PACKET
  word 49 allows it, DMADIR when word 62 requires it). Built on top of it:
  TEST UNIT READY, REQUEST SENSE, READ CAPACITY(10), READ(10), READ TOC
  (start of the last session for multisession discs) and START STOP UNIT
  for DISKFUNC.LoadTray.
- Drives are registered as sr0, sr1, ... with DISK_NO_INSERT_NOTIFICATION,
  2048-byte sectors and read-only media; iso9660 mounts them as /srN/1.
  They cannot be named cd*: fs_lfn.inc sends every path starting with "cd"
  to the old ATAPI-over-IDE code.
- Disc change: the kernel lets go of a mounted medium only when querymedia
  fails, so after a UNIT ATTENTION querymedia fails once and the kernel
  immediately mounts the new disc. A READ(10) that hits UNIT ATTENTION
  fails instead of silently reading the new disc.
- One ATAPI transfer is capped at (PRDT_MAX_ENTRIES - 1) * 4096 bytes, so
  the PRDT always covers the whole request. The PRDT builder moved out of
  ahci_rw_sectors into ahci_build_prdt and is shared by both paths.
- A command the drive refuses (an empty tray does that on every TEST UNIT
  READY) restarts the port quietly instead of running the full recovery.
- Optical ports never busy-poll a long command and never switch the whole
  controller to polling: missing interrupts are counted per port and only
  that port's PxIE is turned off.
- Diagnostic output (command statistics, interrupt wakeups, register dumps
  during init) is now behind AHCI_DBGLVL, off by default. Errors and one
  line per detected device are still printed.

Tested: QEMU, VirtualBox and VMware (detection, listings and reads checked
against host checksums; eject/insert in QEMU and VirtualBox, a direct disc
swap in VirtualBox, an empty drive in VMware), SATA disk read/write on the
same controller in QEMU, and a GA-D525TUD (NM10) with an ASUS DRW-24B3ST:
detection, reading, disc change. The debug level change was build-tested
only.

Assisted-by: Claude Opus 5
Reviewed-on: #694
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: Ivan B <1+dunkaist@noreply.localhost>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-29 15:44:06 +00:00
Leency 6f3cae4e0c kernel/network: fix window-update check in tcp_output (#711)
Build system / Build (en_US) (push) Successful in 4m8s
Build system / Build (es_ES) (push) Successful in 3m58s
Build system / Build (ru_RU) (push) Successful in 4m9s
Build system / Publish Images (push) Successful in 11m38s
`tcp_output`: the window-update check computed `min(free, max_win - advertised)` instead of BSD's `min(free, max_win) - advertised`. With unread data in the receive buffer, every `send()` produced an empty ACK and never reached the persist state: no zero-window probes, and the connection hung.

- Clamp to the free space first, then subtract the advertised window.
- Compare signed: the result is negative when the window shrank.

Tested in QEMU with pcap: ~11000 empty ACKs in 0.6 s and no probe before the fix; 12 ACKs and a 1-byte persist probe after it.

Reviewed-on: #711
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: hidnplayr <hidnplayr@gmail.com>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-29 13:38:57 +00:00
Leency b59e371c0e kernel/network: forget a network device's state when it is removed (#719)
Build system / Build (en_US) (push) Successful in 5m45s
Build system / Build (es_ES) (push) Successful in 5m55s
Build system / Build (ru_RU) (push) Successful in 6m4s
Build system / Publish Images (push) Failing after 11m50s
- `net_remove_device`: clear the slot's IPv4 settings, ARP table and counters, and drop its frames from the ethernet input queue.
- `ipv4_route`:
  - skip slots without a device;
  - an interface without an address routes broadcasts only;
  - off-link without a gateway fails instead of resolving 0.0.0.0.
- `ipv4_output_raw`: check the route before resolving it.
- `eth_output`, `arp_output_request`: refuse a null device.
- `eth_output`: count a too-large frame on the device, not on `eax`.

Reviewed-on: #719
Reviewed-by: hidnplayr <hidnplayr@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-29 13:30:00 +00:00
Leency 939505198f http.obj: close the socket when connect() fails; kernel: unlock on tcp_connect errors
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 25s
Test PR / Build (ru_RU) (pull_request) Successful in 2m2s
Test PR / Build (en_US) (pull_request) Successful in 2m11s
Test PR / Build (es_ES) (pull_request) Successful in 2m18s
Build system / Build (en_US) (push) Successful in 3m50s
Build system / Build (es_ES) (push) Successful in 3m52s
Build system / Build (ru_RU) (push) Successful in 3m55s
Build system / Publish Images (push) Successful in 11m8s
open_connection in http.obj left the socket open whenever connect()
failed. The kernel never reclaims sockets of a finished process
(socket_process_end is a stub), so every failed connect leaked a socket
with its two SOCKET_BUFFER_SIZE rings for good, and a late SYN+ACK could
still connect the orphan. WebView with a few dead image hosts ran the
kernel heap dry ("SOCKET_ring_create: Out of memory!"), after which every
application lost the network. Close the socket on the way out.

The socket() error check compared against 0, but the syscall returns -1
on failure; compare with -1.

The close() above exposed a second bug: tcp_connect took SOCKET.mutex
before creating the rings and returned from .nomem and .enoroute without
releasing it. Any later socket_free on that socket - close() from the
application, once http.obj does it - then waited for the mutex forever
and the thread became unkillable. Unlock on both error exits.

Assisted-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 14:38:01 +03:00
Burer 75cb80fd33 ci: compact older builds on the storage server (#697)
Build system / Build (es_ES) (push) Successful in 3m23s
Build system / Build (en_US) (push) Successful in 3m27s
Build system / Build (ru_RU) (push) Successful in 3m28s
Build system / Publish Images (push) Successful in 3m14s
Every push to main publishes 4 images per language plus the unpacked build tree, and nothing on the storage server ever shrinks. `kolibri.raw` is a fixed 128 MiB regardless of content, and `kolibri.img` ends up stored three times per language.

This adds a compaction step at the end of the deploy playbook. It runs on the storage server itself, so nothing extra crosses the network.

- The build that was just published stays as it is: bare images and a browsable tree.
- Every older build keeps its images zipped and loses the unpacked tree, which is rebuildable from the commit anyway.

`*.distr.zip`, `sha256sums.txt` and `build.log` are never touched.

Reviewed-on: #697
Reviewed-by: Gleb Zaharov <risdeveau@lair.moe>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
2026-09-28 07:32:37 +00:00
Burer 6ba901606d ci: open submodule bump PRs as the bot, not as Actions
Test PR / Build (es_ES) (pull_request) Successful in 4m48s
Test PR / Build (en_US) (pull_request) Successful in 5m3s
Test PR / Build (ru_RU) (pull_request) Successful in 2m18s
Build system / Build (ru_RU) (push) Successful in 4m52s
Build system / Build (es_ES) (push) Successful in 5m11s
Build system / Build (en_US) (push) Successful in 5m16s
Build system / Publish Images (push) Successful in 4m8s
A branch pushed and a pull request opened with the built-in GITEA_TOKEN
come from the Actions user, and events it creates start no workflow run.
Test PR never ran on a bump, so the required check stayed missing and
the PRs could not be merged however many approvals they collected.

Put BOT_TOKEN back in both places: checkout persists it for the push,
and the API call needs it to open the PR under the bot account. This
reverts 882f1f024.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-28 07:17:58 +00:00
kolibrios-bot Bot b1d329da2a chore/submodules: bump cmm to 4aeaee3386dac12fc4ef57ad531b632890df5425
Test PR / Build (es_ES) (pull_request) Successful in 2m22s
Test PR / Build (ru_RU) (pull_request) Successful in 2m25s
Test PR / Build (en_US) (pull_request) Successful in 2m27s
Build system / Build (es_ES) (push) Successful in 6m5s
Build system / Build (en_US) (push) Successful in 6m31s
Build system / Build (ru_RU) (push) Successful in 6m35s
Build system / Publish Images (push) Successful in 5m18s
2026-09-28 07:14:00 +00:00
Leency df9946fe80 libs/libimg: make the grayscale JPEG palette opaque
Test PR / Build (en_US) (pull_request) Successful in 1m55s
Test PR / Build (ru_RU) (pull_request) Successful in 2m1s
Test PR / Build (es_ES) (pull_request) Successful in 2m5s
Build system / Build (es_ES) (push) Successful in 2m59s
Build system / Build (en_US) (push) Successful in 3m5s
Build system / Build (ru_RU) (push) Successful in 3m10s
Build system / Publish Images (push) Successful in 3m27s
A grayscale JPEG is decoded as Image.bpp8i with a 256-level gray
palette built from xor eax, eax, so every entry had alpha 0. After
img.convert to Image.bpp32 the picture was fully transparent: programs
that blend by alpha (WebView) reserved its room and drew nothing.
The palette now starts at 0xFF000000, as the PNG decoder fills its own.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 20:13:13 +03:00
Leency e3d744f1b5 Clean IMG (#721)
Build system / Build (en_US) (push) Successful in 3m0s
Build system / Build (ru_RU) (push) Successful in 3m6s
Build system / Build (es_ES) (push) Successful in 3m9s
Build system / Publish Images (push) Successful in 3m34s
- Move ImgF to ISO (closed source)
- Move Examples to ISO (any normal app is a better example... and also there is already /sys/example.asm)
- Remove /sys/settings/kolibri.lbl as unnecessary
- Kpack /sys/settings/keymap.key (this is a binnary file so no matter, -2.5KB) and load it by 68.27

Reviewed-on: #721
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-26 17:29:42 +00:00
igorshandIgor Shutrov 8ca3758efb apps/ftpd: bound the pasv port search (#710)
Build system / Build (es_ES) (push) Successful in 3m36s
Build system / Build (ru_RU) (push) Successful in 3m37s
Build system / Build (en_US) (push) Successful in 3m38s
Build system / Publish Images (push) Successful in 3m2s
On a failed bind cmdPASV jumped straight back to .next_port, and
nextpasvport wraps within [start, end], so a range with no usable port
spun forever without reading the control connection again: the client
hangs.

Count the ports in the range (end - start + 1), decrement after a
failed bind and give up at zero, then close the listener, reset the
state and answer 425 Can't open data connection. The counter lives in a
new thread_data field rather than a register, because mcall bind
clobbers eax/ebx/ecx/edx/esi/edi and esi already carries the sockaddr
length for bind. Decrementing after the failed bind and not before the
next attempt is what keeps a single-port range (start = end) working:
it still gets its one attempt.

Also validate the pair read from the ini. With start > end the range
degenerates and no port is bindable, so fall back to 2000/5000.

---------

Co-authored-by: Igor Shutrov <kolibridev@inbox.ru>
Reviewed-on: #710
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: Igor shutrov <kolibridev@mail.ru>
2026-09-25 09:17:16 +00:00
Leency 02916ed0ee drivers/i2chid: reset a pad stuck on one frame, bring-up ladder only in debug builds
Test PR / Build (es_ES) (pull_request) Successful in 1m58s
Test PR / Build (ru_RU) (pull_request) Successful in 2m5s
Test PR / Build (en_US) (pull_request) Successful in 2m9s
Build system / Build (en_US) (push) Successful in 3m5s
Build system / Build (es_ES) (push) Successful in 3m8s
Build system / Build (ru_RU) (push) Successful in 3m15s
Build system / Publish Images (push) Successful in 3m28s
Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-24 10:01:16 +00:00
IgorAandBurer 873d4de379 apps/animage: attempt to fix the scrollbar (#715)
Build system / Build (en_US) (push) Successful in 3m8s
Build system / Build (es_ES) (push) Successful in 3m17s
Build system / Build (ru_RU) (push) Successful in 3m20s
Build system / Publish Images (push) Successful in 4m11s
- replace the hand drawn scrollbars with the box_lib widget
- separate start and minimal window size, enforce minimal on resize
- use the libimg and box_lib import lists instead of hand written ones
- use the process_information struct for procinfo
- drop the dead sound handler and the unused palette offset
- bump version to 1.53

---------

Co-authored-by: Burer <burer@kolibrios.org>
Reviewed-on: #715
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: IgorA <aie85playm@gmail.com>
2026-09-24 08:27:25 +00:00
Leency b2f9cc9809 kpack: add native Windows and Linux ports (#696)
Build system / Build (es_ES) (push) Successful in 2m53s
Build system / Build (en_US) (push) Successful in 3m1s
Build system / Build (ru_RU) (push) Successful in 3m5s
Build system / Publish Images (push) Successful in 3m29s
Windowless in-place compressor (kpackw.exe / kpackl), reusing the
original LZMA + kerpack sources; auto-detects kernel.mnt. Tupfile builds both.

Assisted-by: Claude Opus 5
Reviewed-on: #696
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: IgorA <22+igora@noreply.localhost>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-23 22:48:55 +00:00
Leency 298155191d apps/tinypad: fix select all delete crash (fix #173) (#700)
Build system / Build (es_ES) (push) Successful in 3m2s
Build system / Build (en_US) (push) Successful in 3m9s
Build system / Build (ru_RU) (push) Successful in 3m11s
Build system / Publish Images (push) Successful in 3m24s
fixes both issues in #173

Reviewed-on: #700
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: IgorA <22+igora@noreply.localhost>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-23 20:19:17 +00:00
Burer 49b8cdcd54 ci: mark submodule contents dirty after a bump
Test PR / Build (es_ES) (pull_request) Successful in 2m5s
Test PR / Build (ru_RU) (pull_request) Successful in 2m7s
Test PR / Build (en_US) (pull_request) Successful in 2m14s
Build system / Build (es_ES) (push) Successful in 12m10s
Build system / Build (ru_RU) (push) Successful in 12m13s
Build system / Build (en_US) (push) Successful in 12m17s
Build system / Publish Images (push) Successful in 3m33s
git diff reports a submodule bump as a bare gitlink, so the files inside
kept their cached ctime alignment and tup never rebuilt them.
2026-09-22 21:28:30 +03:00
Egor00f c121db7a88 libc.obj: use bitfield flags in file instead of int variables && rewrite freopen, fopen (#691)
Build system / Build (es_ES) (push) Successful in 3m18s
Build system / Build (en_US) (push) Successful in 3m23s
Build system / Build (ru_RU) (push) Successful in 3m25s
Build system / Publish Images (push) Successful in 4m52s
Use bitfield `flags` flags in file instead of `int` variables `mode`, `error`, `eof`.

And rewrite weird logic opening/close files

Reviewed-on: #691
Reviewed-by: Ivan B <1+dunkaist@noreply.localhost>
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Co-authored-by: Egor00f <y.yarin@inbox.ru>
2026-09-22 12:39:50 +00:00
Egor00f 9527a0f3d1 libshell & shell: implement a return value for the shell API (#660)
Build system / Build (en_US) (push) Successful in 3m35s
Build system / Build (es_ES) (push) Successful in 3m29s
Build system / Build (ru_RU) (push) Successful in 3m29s
Build system / Publish Images (push) Successful in 4m41s
Require: #657 ([compare](https://git.kolibrios.org/Egor00f/kolibrios/compare/update-shell-api...shell-api-implement-return-value))

Implement a return value for shell API functions.
required for updating libc streams.

The return value is declared after `data` for consistency with older programs.

# Changes:
## [`shell`](https://git.kolibrios.org/KolibriOS/kolibrios/pulls/660/files#diff-9e9982c0c3e401531fcfbc1f9dd5f1f3d85452fd)
+ `SHELL_PUTS` and `SHELL_GETS` return the number of bytes written
+ `SHELL_GETC` write full `int` value
## `libshell`
+ [`shell_gets`](https://git.kolibrios.org/KolibriOS/kolibrios/pulls/660/files#diff-8840a9f9a5e28f05f5f46e1b5106caf3ce6c470e) returns `NULL` or `EOF`, or a pointer to a string and returns the number of bytes received
+ [`shell_getc`](https://git.kolibrios.org/KolibriOS/kolibrios/pulls/660/files#diff-955a257b2a02cfc5ee9879b7efc50d0644ad179c) return `int`
+ [`shell_printf`](https://git.kolibrios.org/KolibriOS/kolibrios/pulls/660/files#diff-4ffb653a63ef098530e336370053615fee66be03) returns the number of bytes written
+ [`shell_puts`](https://git.kolibrios.org/KolibriOS/kolibrios/pulls/660/files#diff-ee4df9617f16bc52153701c0edc6c2947dd877a8) returns the number of bytes written
+ [`shell_write_string`](https://git.kolibrios.org/KolibriOS/kolibrios/pulls/660/files#diff-cebe23f17158adc73d20c5f9096862c209732598) returns the number of bytes written

Reviewed-on: https://git.kolibrios.org/KolibriOS/kolibrios/pulls/660
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
2026-09-22 10:01:06 +00:00
Leency 1e05d19c4c kernel/disk: release the partition scan buffer with kernel_free (#695)
Build system / Build (es_ES) (push) Successful in 2m59s
Build system / Build (en_US) (push) Successful in 3m3s
Build system / Build (ru_RU) (push) Successful in 3m7s
Build system / Publish Images (push) Successful in 3m20s
Summary: disk_scan_partitions takes its three-sector buffer from
kernel_alloc but gave it back with the malloc heap's free, which reads a
chunk header that a kernel_alloc block does not have. Mounting a disk
with non-512-byte sectors could fault or corrupt the malloc heap.

Details:
The global mbr_buffer is used only for 512-byte sectors and only while no
other scan holds it; every other case allocates the buffer with
kernel_alloc. The release path still called free, the malloc heap
function: it looks at [ptr-8] for the chunk head. A kernel_alloc block is
page-aligned, so that is the tail of the previous page - a page fault when
that page is not mapped, otherwise a bogus header and possibly a damaged
heap.

Since "disk cache: support for sector sizes other than 512 bytes"
(9d022746f) every CD/DVD mount takes this path, so it is no longer a rare
race of two scans. It was hit as a page fault in free+0xF called from
disk_scan_partitions while an AHCI optical drive remounted a changed disc
in QEMU.

kernel_free keeps ebx and esi; the only caller, disk_media_changed, saves
ebx, esi and edi itself, so replacing the call does not disturb it.

Tested: kernel builds; in QEMU a CD on an AHCI port was mounted at boot and
remounted after swapping discs A -> B -> A, without faults, with this change
on top of origin/main and the AHCI ATAPI support branch.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
Reviewed-on: #695
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-20 09:49:44 +00:00
Matou1306 ecdebae231 Kernel/fs: Add symlink flag to sysfunc70 and update the English documentation (#656)
Build system / Build (en_US) (push) Successful in 2m57s
Build system / Build (es_ES) (push) Successful in 2m59s
Build system / Build (ru_RU) (push) Successful in 3m3s
Build system / Publish Images (push) Successful in 4m44s
Used in 70.1 and 70.5 in the ext driver

Reviewed-on: #656
Reviewed-by: Ivan B <1+dunkaist@noreply.localhost>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Co-authored-by: Matou1306 <mathieubotros@gmail.com>
2026-09-20 04:46:24 +00:00
0150178c90 ftpd: actually close the passive listening socket (#707)
Build system / Build (es_ES) (push) Successful in 3m15s
Build system / Build (ru_RU) (push) Successful in 3m20s
Build system / Build (en_US) (push) Successful in 3m26s
Build system / Publish Images (push) Successful in 4m26s
mcall close takes the socket number in ecx, but the operand was
commented out in the two places that close the PASV listener, so close
ran with whatever ecx happened to hold. Both call sites had just put the
listener in ecx, so the socket was closed by accident: the code worked
only as long as that accident held. The cmdPASV cleanup was commented
out completely, so a second PASV before the client connected left the
previous listener open.

Restore the operand in threadloop (ftpd.asm) and in open_datasock, and
re-enable the cmdPASV prologue, which also resets passivesocknum to -1.

Closing the data socket needed the same care: datasocketnum only holds
a live socket in MODE_PASSIVE_OK and MODE_ACTIVE, so the new
close_data_sock helper closes it in those two states only. The
.cannot_open label is also reachable before open_datasock runs (the
length checks at the top of cmdSTOR), where datasocketnum is either
stale or never initialised, and closing it unconditionally there could
have closed an unrelated socket that had reused the number. The field
is now initialised to -1 at thread start and reset to -1 after every
close.

---------

Co-authored-by: leency <lipatov.kiril@gmail.com>
Co-authored-by: Igor Shutrov <kolibridev@inbox.ru>
Reviewed-on: #707
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: igorsh <kolibridev@mail.ru>
2026-09-19 23:45:35 +00:00
3caf2a7a72 apps/ftpd: truncate the file on STOR instead of overwriting in place (#706)
Build system / Build (es_ES) (push) Successful in 2m50s
Build system / Build (en_US) (push) Successful in 2m53s
Build system / Build (ru_RU) (push) Successful in 3m1s
Build system / Publish Images (push) Successful in 3m40s
cmdSTOR opens the destination with O_CREATE + O_WRITE, and libio only
truncates on write when the position is already at EOF (libio.asm:314),
which never happens here. Replacing a longer file with a shorter one
therefore kept the old tail: 4096-byte A overwritten by 1024-byte B
produced a 4096-byte file holding B followed by A[1024:4096], and
overwriting with zero bytes left the file completely untouched.

Call file.truncate (SF 70.4, size = Position = 0) right after a
successful open so that STOR replaces the file, as RFC 959 requires.
The descriptor survives the call in ebx because sendFTP clobbers the
registers. A failed truncate closes the descriptor and answers 550
through a new .truncate_error path.

The libio import list gains file_truncate, exported since 2009.

-------------------------

STOR: усекать файл при перезаписи, чтобы не оставался старый хвост

Проблема

cmdSTOR открывает целевой файл с O_CREATE + O_WRITE, а libio усекает файл при записи только если позиция уже находится в EOF (libio.asm:314). В этом сценарии условие никогда не выполняется. Поэтому при замене длинного файла коротким сохранялся старый хвост: 4096-байтный A, перезаписанный 1024-байтным B, давал 4096-байтный файл, содержащий B, а затем A[1024:4096]. Перезапись нулевым количеством байт вообще не изменяла файл.

Решение

Сразу после успешного открытия вызывается file.truncate (SF 70.4, size = Position = 0), чтобы STOR заменял файл, как требует RFC 959. Дескриптор сохраняется в ebx после вызова, так как sendFTP затирает регистры. Если truncate завершается ошибкой, дескриптор закрывается, а ответ 550 отправляется через новый обработчик .truncate_error.

Дополнительно

В список импортов libio добавлен file_truncate (экспортируется с 2009 года).
Co-authored-by: leency <lipatov.kiril@gmail.com>
Co-authored-by: Igor Shutrov <kolibridev@inbox.ru>
Reviewed-on: #706
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: igorsh <kolibridev@mail.ru>
2026-09-19 16:56:31 +00:00
Leency 019f2629dc apps/cedit: do not free the menu canvas from another thread (fix #636) (#702)
Build system / Build (en_US) (push) Successful in 3m9s
Build system / Build (es_ES) (push) Successful in 3m13s
Build system / Build (ru_RU) (push) Successful in 3m23s
Build system / Publish Images (push) Successful in 6m10s
Fixes #636

**Причина.** Каждое меню работает в своём потоке и рисует себя из холста `m.canvas`. Этот холст освобождал (`G.destroy`) не только сам поток меню, но и другие потоки:
- `Menu.close()` вызывается из главного потока и при переключении подменю. Он освобождал холст до `K.ExitID()`.
- При срабатывании шортката из подменю холст родительского меню освобождал поток-потомок.

При быстрых кликах поток меню в этот момент как раз внутри `DrawCanvas` (sysfn 65). Ядро читает из уже освобождённого буфера и получает page fault в режиме ядра, поэтому в логе CS=8. Кроме того, если поток сам выходил через `exit`/`escape` одновременно с чужим `close()`, получался двойной free.

**Исправление.** В [Menu.ob07](develop/cedit/SRC/Menu.ob07) убрал все четыре `G.destroy` для холста меню: в `exit`, `escape`, `close` и в ветке шорткатов. Холст и так создаётся лениво в `open()` при `m.canvas = NIL`. Меню создаются один раз при старте, и размер у них не меняется, так что холст теперь живёт всё время работы программы. Утечки нет, и кроме того больше нет выделения и освобождения памяти при каждом открытии меню.

Reviewed-on: #702
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: Alexey Ryabov <alex@b00bl1k.ru>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-18 22:07:28 +00:00
Gitea Actionsandkolibrios-bot Bot 63ee53f4a3 chore/submodules: bump cmm_apps to upstream (#698)
Build system / Build (ru_RU) (push) Successful in 4m4s
Build system / Build (es_ES) (push) Successful in 4m4s
Build system / Build (en_US) (push) Successful in 4m7s
Build system / Publish Images (push) Successful in 3m30s
Co-authored-by: kolibri-bot <bot@kolibrios.org>
Reviewed-on: #698
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: Gitea Actions <-2+gitea-actions@noreply.localhost>
2026-09-18 12:09:51 +00:00
IgorA 7c8eba2ed4 libs/sort: cleared the DF flag for safety reasons (#704)
Build system / Build (es_ES) (push) Successful in 3m2s
Build system / Build (ru_RU) (push) Successful in 3m9s
Build system / Build (en_US) (push) Successful in 3m13s
Build system / Publish Images (push) Successful in 5m23s
Reviewed-on: #704
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Co-authored-by: IgorA <aie85playm@gmail.com>
2026-09-18 11:44:46 +00:00
Leency 15396a0304 drivers: add i2chid HID-over-I2C touchpad driver (#692)
Build system / Build (es_ES) (push) Successful in 3m6s
Build system / Build (en_US) (push) Successful in 3m10s
Build system / Build (ru_RU) (push) Successful in 3m15s
Build system / Publish Images (push) Successful in 3m33s
I2C touchpad driver.
Tested on Олег Александрович and my GF laptop.

Assisted-by: Claude Opus 5
Reviewed-on: #692
Reviewed-by: Ivan B <1+dunkaist@noreply.localhost>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-16 10:28:47 +00:00
Leency 0969869ba8 derivers/hdaudio: irq polling (#679)
Build system / Build (en_US) (push) Successful in 3m3s
Build system / Build (es_ES) (push) Successful in 3m7s
Build system / Build (ru_RU) (push) Successful in 3m14s
Build system / Publish Images (push) Successful in 4m45s
Now I have sound on a pretty new UEFI machine (AMD 4500U) without IRQ attached. Also ran regression on 3 BIOS machines. All OK.

drivers/hdaudio: attach IRQ before enabling interrupts, poll when no IRQ line

- attach the interrupt handler before azx_init_chip enables GIE/CIE: an
  unclaimed level IRQ made the kernel (irq_serv .try_other_irqs) call and
  relink foreign handlers onto our line, corrupting the dispatch list
- no interrupt line (INTLINE=0xFF, UEFI without CSM): fall back to RIRB
  polling plus a 10 ms TimerHS driving hda_irq; sound works on AMD Renoir
- acknowledge all STATESTS bits instead of codec №2 only
- serialize RIRB readers (timer/IRQ vs command thread) with aspinlock
- fix azx_int_disable (edx reused after azx_readl), quiesce before attach
- zero the unsolicited-event ring pointers, mask its write index
- move 'data fixups' after code and data so fasm converges

Reviewed-on: #679
Reviewed-by: Ivan B <1+dunkaist@noreply.localhost>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-16 04:55:24 +00:00
Doczom dd3af88a30 Kernel: The source value has been changed for bgrlockpid
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 21s
Test PR / Build (en_US) (pull_request) Successful in 2m13s
Test PR / Build (ru_RU) (pull_request) Successful in 2m16s
Test PR / Build (es_ES) (pull_request) Successful in 2m20s
Build system / Build (en_US) (push) Successful in 3m5s
Build system / Build (ru_RU) (push) Successful in 3m12s
Build system / Build (es_ES) (push) Successful in 3m16s
Build system / Publish Images (push) Successful in 3m46s
for bgrlockpid, the source value was changed from current_slot_idx to APPDATA.tid
2026-09-14 21:56:19 +00:00
Doczom 85ae0c8703 Kernel: The APPDATA.debugger_slot field has been changed to APPDATA.debugger_thread
The APPDATA.debugger_slot field has been changed to APPDATA.debugger_thread. The API for the internal functions of the kernel has been changed. Mathematical expressions have been replaced with constants and the code has been cleaned up.
2026-09-14 21:56:19 +00:00
Doczom 2ad11d3acc Kernel/fpu.inc: added edi case preservation for *_restore functions. Added a description of the functions 2026-09-14 21:56:19 +00:00
Doczom 450054a86c Kernel: the value source has been changed for fpu_owner and timer_list_owner
for fpu_owner and timer_list_owner, the value source has been changed from current_slot_idx to current_slot
2026-09-14 21:56:19 +00:00
IgorA b0055ba472 msgbox: increasing the window width for long text (#690)
Build system / Build (en_US) (push) Successful in 3m4s
Build system / Build (ru_RU) (push) Successful in 3m7s
Build system / Build (es_ES) (push) Successful in 3m15s
Build system / Publish Images (push) Successful in 3m10s
Reviewed-on: #690
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Co-authored-by: IgorA <aie85playm@gmail.com>
2026-09-14 12:33:21 +00:00
IgorA f711f9286b optimize import: (#689)
Build system / Build (es_ES) (push) Successful in 2m58s
Build system / Build (en_US) (push) Successful in 3m12s
Build system / Build (ru_RU) (push) Successful in 3m15s
Build system / Publish Images (push) Successful in 3m43s
color_dialog, fspeed, hdd_info, mgb, skincfg, zsea

Reviewed-on: #689
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Co-authored-by: IgorA <aie85playm@gmail.com>
2026-09-13 20:31:16 +00:00
Leency 7802c7b18a fat: fix stack imbalance on fatal hd_extend_file error (#631)
Build system / Build (en_US) (push) Successful in 3m6s
Build system / Build (es_ES) (push) Successful in 3m17s
Build system / Build (ru_RU) (push) Successful in 3m23s
Build system / Publish Images (push) Successful in 3m19s
The FAT/device error path in fat_Write jumped to the shared one-dword
epilogue with four dwords live, so ret returned into the error-code
slot and faulted in ring 0. Give the path its own named label.

Reviewed-on: #631
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
2026-09-12 21:25:21 +00:00
Leency 8a94db94a5 remove comments
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 17s
Test PR / Build (en_US) (pull_request) Successful in 2m18s
Test PR / Build (es_ES) (pull_request) Successful in 2m21s
Test PR / Build (ru_RU) (pull_request) Successful in 2m22s
Build system / Build (en_US) (push) Successful in 2m53s
Build system / Build (es_ES) (push) Successful in 2m56s
Build system / Build (ru_RU) (push) Successful in 3m0s
Build system / Publish Images (push) Successful in 4m58s
2026-09-11 18:51:30 +00:00
LeencyandClaude Opus 5 513af11464 kernel/net: raise the socket buffer size to 128 KiB
Summary: SOCKET_BUFFER_SIZE was 32 KiB, which caps a single TCP connection
at roughly 1 MB/s over a typical internet path regardless of the available
bandwidth.

Подробно:
The receive buffer size is the upper bound on the window a socket can
advertise, and a TCP connection cannot go faster than window / RTT. At the
old 4096*8 = 32 KiB, a path with a 32 ms round trip is limited to about
1 MB/s no matter how fast the link underneath is. Raising the buffer to
4096*32 = 128 KiB moves that ceiling to roughly 4 MB/s on the same path.

Nothing else needs adjusting: request_r_scale is derived from
SOCKET_BUFFER_SIZE in tcp_usreq, so the window scale we request grows with
the buffer automatically, and both tcp_output and tcp_respond clamp the
scaled value to the 16-bit header field. The constant keeps satisfying the
documented requirement of 4096*(power of two >= 8).

The cost is memory: each stream socket maps a send and a receive ring, so a
TCP socket now reserves 256 KiB of physical memory instead of 64 KiB (and
twice that in address space, since the rings are mirror-mapped). For a
browser holding a handful of connections open this is a few megabytes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 18:51:30 +00:00
Egor00f e0e8a35364 libc.obj: time.h using _ksys_get_clock, but this function not defined (#688)
Build system / Build (en_US) (push) Successful in 3m30s
Build system / Build (ru_RU) (push) Successful in 3m30s
Build system / Build (es_ES) (push) Successful in 3m38s
Build system / Publish Images (push) Successful in 3m13s
f2ea10c1cd/programs/develop/ktcc/libc.obj/include/time.h (L8)
Reviewed-on: #688
Co-authored-by: Egor00f <y.yarin@inbox.ru>
2026-09-08 20:41:45 +00:00
Matou1306 f2ea10c1cd fs/ext: Support INCOMPAT_EXTENTS, RO_COMPAT_DIR_NLINK, RO_COMPAT_HUGE_FILE. (#603)
Build system / Build (en_US) (push) Successful in 3m14s
Build system / Build (ru_RU) (push) Successful in 3m18s
Build system / Build (es_ES) (push) Successful in 3m23s
Build system / Publish Images (push) Successful in 3m40s
Extents writing support.
In addition, the file system can now write to file systems with dir_nlink, as long as the target directory doesn't have the index flag enabled (directories exceeding 64k subdirectories). It also supports huge_file, as long as the huge_file inode flag is not enabled on the file itself (files > 2TB).
This Pull Request depends on #584

What currently works:

- Merging a new allocation into the last extent when contiguous (.extentNext fast path)
- Adding a new extent entry into an existing leaf/root node that still has room (.addNewExtent)
- Creating the very first extent in an empty root (.newExtentRoot)
- Checksum maintenance via calc_extent_block_csum on writes to index/leaf blocks
- Truncation, including freeing leaves and collapsing an index entry back up the tree (.trim_tree/.trim_index), down to setting currentDepth = 0 when the whole tree empties
- Increasing the height of the tree and allocating new leaves.

Reviewed-on: #603
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Co-authored-by: Matou1306 <mathieubotros@gmail.com>
2026-09-07 11:41:41 +00:00
Leency 302bf7e221 board: toggle kernel/user log with Tab (#682)
Build system / Build (ru_RU) (push) Successful in 3m56s
Build system / Build (en_US) (push) Successful in 4m1s
Build system / Build (es_ES) (push) Successful in 4m3s
Build system / Publish Images (push) Successful in 4m22s
Reviewed-on: #682
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-07 11:20:29 +00:00
IgorA a3af661ed6 libs/libimg: added support for saving 8-bit images in PNG format (#599)
Build system / Build (ru_RU) (push) Successful in 4m7s
Build system / Build (en_US) (push) Successful in 4m15s
Build system / Build (es_ES) (push) Successful in 4m23s
Build system / Publish Images (push) Successful in 4m10s
Еxample of an 8-bit png image with a palette https://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/develop/libraries/TinyGL/asm_fork/examples/text_2.png

Reviewed-on: #599
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Co-authored-by: IgorA <aie85playm@gmail.com>
2026-09-07 11:14:21 +00:00
b00bl1k e74f989500 programs/system/terminal: switch to the serial driver (#638)
Build system / Build (es_ES) (push) Successful in 5m59s
Build system / Build (en_US) (push) Successful in 6m15s
Build system / Build (ru_RU) (push) Successful in 6m15s
Build system / Publish Images (push) Successful in 4m44s
Reworks Terminal to use the drivers/serial API instead of using UART registers directly, enabling virtual COM port (VCP) support in addition to physical ports.

- port field now accepts a numeric port id instead of a COMx name
- syscalls use `SF_*`/`SSF_*` named constants

Closes #604

Reviewed-on: #638
Reviewed-by: Burer <burer@kolibrios.org>
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Co-authored-by: Alexey Ryabov <alex@b00bl1k.ru>
2026-09-07 10:37:40 +00:00
Leency 4fe3987e39 drivers/usbstor: limit one SCSI transfer to 240 sectors (#686)
Build system / Build (es_ES) (push) Successful in 4m3s
Build system / Build (en_US) (push) Successful in 4m3s
Build system / Build (ru_RU) (push) Successful in 4m5s
Build system / Publish Images (push) Successful in 4m8s
max_sectors_at_time only bounded a slice by the 16-bit transfer length
field of READ(10)/WRITE(10), i.e. 32 MB, so whatever the caller asked
for went to the device as a single command. The kernel disk cache hands
the driver up to CACHE_MAX_ALLOC_SIZE (4 MB) at once, so reading any
file larger than 4 MB produced one 4 MB bulk transfer.

USB sticks do not see such commands from other systems and some of them
wedge their firmware on it: the queue halts with XactErr and an
exhausted error counter, the device stops answering, drops off the bus
and re-enumerates in the middle of the operation. Observed on two
different sticks, reproducible on every file over 4 MB.

Cap a slice at 240 sectors (120 KB), the limit Linux usb-storage uses
for the same reason. The splitting loop was already there.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
Reviewed-on: #686
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: leency <lipatov.kiril@gmail.com>
2026-09-07 07:45:25 +00:00
126 changed files with 15286 additions and 4966 deletions

No files matched your search

+24
View File
@@ -54,3 +54,27 @@
src: "{{ stable_artifact_path }}/"
dest: "{{ storage_path }}/../"
mode: preserve
# older builds shrink to compressed images and lose their unpacked tree; the newest few keep both
- name: Looking for zstd on the storage server
ansible.builtin.shell: command -v zstd
register: zstd_present
changed_when: false
failed_when: false
- name: Requiring zstd for compaction
ansible.builtin.assert:
that: zstd_present.rc == 0
fail_msg: >-
zstd is not installed on the storage server, so older builds cannot
be compacted. Install it and re-run this build.
- name: Compacting older builds
ansible.builtin.script:
cmd: >-
../../utils/compact-builds.sh
{{ storage_path | quote }}
{{ compact_keep | default(5) | int }}
{{ compact_max | default(10) | int }}
register: compaction
changed_when: "'compacted 0 of' not in compaction.stdout"
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: 2026 KolibriOS team
# Shrink older builds on the storage server: compress their images and drop
# their unpacked tree, which is rebuildable from the commit. sha256sums.txt
# keeps naming the bare images, so a compacted build has to be decompressed
# before it can be verified.
#
# Layout: <root>/<version>/<lang>/kolibrios-<descr>-<lang>.{img,iso,raw} -> .zst
# <root>/<version>/<lang>/data/ -> removed
#
# Usage: compact-builds.sh <storage-root> [keep] [max-per-run]
# DRY_RUN=1 walks the same selection and changes nothing
set -euo pipefail
root=${1:?storage root required}
# the build just published is always among these, so an upload in flight is safe
keep=${2:-5}
# a build is hundreds of MiB to re-compress: cap the first pass over the backlog
max=${3:-10}
dry=${DRY_RUN:-0}
verb=compacted
[ "$dry" = 1 ] && verb="would compact"
# --rm drops the source only once the archive is written; the box serves the
# site over NFS, so compaction yields to it
compress_image() {
nice -n 10 ionice -c3 zstd -12 -T1 -q --rm "$1"
}
export -f compress_image
leftovers() {
local build=$1
find "$build" -mindepth 2 -maxdepth 2 \
\( -type d -name data \
-o -type f \( -name '*.img' -o -name '*.iso' -o -name '*.raw' \) \) \
-print -quit
}
compacted=0
pending=0
while IFS= read -r version; do
dir="$root/$version"
[ -n "$(leftovers "$dir")" ] || continue
pending=$((pending + 1))
[ "$compacted" -lt "$max" ] || continue
if [ "$dry" = 1 ]; then
compacted=$((compacted + 1))
echo "$verb $version"
continue
fi
# a build holds nine images: one per core, each zstd kept to one thread so
# the two levels of parallelism do not fight. Archive before dropping the
# tree, so a failure here leaves the build merely uncompacted and the next
# run picks it up again
find "$dir" -mindepth 2 -maxdepth 2 -type f \
\( -name '*.img' -o -name '*.iso' -o -name '*.raw' \) -print0 \
| xargs -0 -r -P "$(nproc)" -I{} bash -c 'compress_image "$@"' _ {}
find "$dir" -mindepth 2 -maxdepth 2 -type d -name data -exec rm -rf {} +
compacted=$((compacted + 1))
echo "$verb $version"
# <tag>-<commit count>-g<sha>: order by the count, never by mtime
done < <(find "$root" -mindepth 1 -maxdepth 1 -type d -name '*-*-g*' -printf '%f\n' \
| sort -t- -k2,2n | head -n "-$keep")
echo "$verb $compacted of $pending older build(s), $((pending - compacted)) left for the next run"
+6 -1
View File
@@ -128,7 +128,8 @@ jobs:
fi
# cache restore resets ctimes; realign tup DB to skip a full rebuild,
# but keep files changed since the cache's commit dirty so tup rebuilds them
# but keep files changed since the cache's commit dirty so tup rebuilds them.
# A submodule bump diffs as a bare gitlink, so expand it to its whole subtree
- name: Sync tup DB with filesystem ctime
if: steps.check-tup-cache.outputs.cache_restored == 'true'
run: |
@@ -136,6 +137,10 @@ jobs:
BASE=$(cat .tup/build-commit 2>/dev/null || true)
if [ -n "$BASE" ] && git cat-file -e "${BASE}^{commit}" 2>/dev/null; then
git -c core.quotePath=false diff --name-only "$BASE" HEAD > "$DIRTY"
git diff --raw "$BASE" HEAD | awk '$2 == "160000" { print $NF }' |
while read -r sub; do
git -C "$sub" -c core.quotePath=false ls-files | sed "s|^|$sub/|"
done >> "$DIRTY"
echo "Cache built at $BASE; $(wc -l < "$DIRTY") changed files kept dirty"
python3 .gitea/utils/sync-tup-ctime.py .tup/db "$DIRTY"
else
+2 -1
View File
@@ -34,10 +34,11 @@ jobs:
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.BOT_TOKEN }}
- name: Bump ${{ matrix.name }} and open PR
env:
TOKEN: ${{ secrets.GITEA_TOKEN }}
TOKEN: ${{ secrets.BOT_TOKEN }}
API: ${{ github.api_url }}
REPO: ${{ github.repository }}
NAME: ${{ matrix.name }}
+22 -18
View File
@@ -41,10 +41,6 @@ img_files = {
{"LIB/KMENU.OBJ", "common/lib/kmenu.obj"},
{"LIB/PIXLIB.OBJ", "common/lib/pixlib.obj"},
{"MEDIA/AC97SND", "common/media/ac97snd"},
{"MEDIA/IMGF/IMGF", "common/media/ImgF/ImgF"},
{"MEDIA/IMGF/CEDG.OBJ", "common/media/ImgF/cEdg.obj"},
{"MEDIA/IMGF/DITHER.OBJ", "common/media/ImgF/dither.obj"},
{"MEDIA/IMGF/INVSOL.OBJ", "common/media/ImgF/invSol.obj"},
{"NETWORK/FTPC.INI", SRC_PROGS .. "/network/ftpc/ftpc.ini"},
{"NETWORK/FTPD.INI", "common/network/ftpd.ini"},
{"NETWORK/KNMAP", "common/network/knmap"},
@@ -58,8 +54,7 @@ img_files = {
{"SETTINGS/FB2READ.INI", "common/settings/fb2read.ini"},
{"SETTINGS/HA.CFG", SRC_PROGS .. "/other/ha/SETTINGS/HA.CFG"},
{"SETTINGS/ICON.INI", build_type .. "/settings/icon.ini"},
{"SETTINGS/KEYMAP.KEY", SRC_PROGS .. "/system/taskbar/KEYMAP.KEY"},
{"SETTINGS/KOLIBRI.LBL", build_type .. "/settings/kolibri.lbl"},
{"SETTINGS/KEYMAP.KEY", VAR_PROGS .. "/system/taskbar/keymap.key.kpack"},
{"SETTINGS/LANG.INI", build_type .. "/settings/lang.ini"},
{"SETTINGS/MENU.DAT", build_type .. "/settings/menu.dat"},
{"SETTINGS/NETWORK.INI", "common/settings/network.ini"},
@@ -273,6 +268,10 @@ extra_files = {
{"kolibrios/lib/i915_dri.drv", "common/lib/i915_dri.drv"},
{"kolibrios/media/fplay", "common/media/fplay"},
{"kolibrios/media/fplay_run", "common/media/fplay_run"},
{"kolibrios/media/ImgF/ImgF", "common/media/ImgF/ImgF"},
{"kolibrios/media/ImgF/cEdg.obj", "common/media/ImgF/cEdg.obj"},
{"kolibrios/media/ImgF/dither.obj", "common/media/ImgF/dither.obj"},
{"kolibrios/media/ImgF/invSol.obj", "common/media/ImgF/invSol.obj"},
{"kolibrios/media/minimp3", "common/media/minimp3"},
{"kolibrios/media/updf", SRC .. "/contrib/media/updf/build/uPDF"},
{"kolibrios/media/vttf", "common/media/vttf"},
@@ -487,11 +486,6 @@ tup.append_table(img_files, {
{"DEVELOP/MTDBG", VAR_PROGS .. "/develop/mtdbg/mtdbg"},
{"DEVELOP/MSTATE", VAR_PROGS .. "/develop/mstate/mstate"},
{"DEVELOP/SCANCODE", VAR_PROGS .. "/develop/scancode/scancode"},
{"DEVELOP/EXAMPLES/CIRCLE", VAR_PROGS .. "/develop/examples/circle/circle"},
{"DEVELOP/EXAMPLES/COLORREF", VAR_PROGS .. "/demos/colorref/colorref"},
{"DEVELOP/EXAMPLES/CONGET", VAR_PROGS .. "/develop/libraries/console_coff/examples/test_gets"},
{"DEVELOP/EXAMPLES/CSLIDE", VAR_PROGS .. "/demos/cslide/cslide"},
{"DEVELOP/EXAMPLES/THREAD", VAR_PROGS .. "/develop/examples/thread/thread"},
{"File Managers/KFAR", VAR_PROGS .. "/fs/kfar/kfar"},
{"File Managers/OPENDIAL", VAR_PROGS .. "/fs/opendial/opendial"},
{"LOD", VAR_PROGS .. "/fs/lod/lod"},
@@ -529,6 +523,7 @@ tup.append_table(img_files, {
{"LIB/RASTERWORKS.OBJ", VAR_PROGS .. "/develop/libraries/fontRasterWorks_unicode/RasterWorks.obj"},
{"LIB/SORT.OBJ", VAR_PROGS .. "/develop/libraries/sorter/sort.obj"},
{"LIB/TINYGL.OBJ", VAR_PROGS .. "/develop/libraries/TinyGL/asm_fork/tinygl.obj"},
{"LIB/XML.OBJ", VAR_PROGS .. "/develop/libraries/asm-xml/xml.obj"},
{"MEDIA/ANIMAGE", VAR_PROGS .. "/media/animage/animage"},
{"MEDIA/FILLSCR", VAR_PROGS .. "/media/FillScr/fillscr"},
{"MEDIA/KIV", VAR_PROGS .. "/media/kiv/kiv"},
@@ -598,6 +593,7 @@ tup.append_table(img_files, {
{"DRIVERS/VT823X.SYS", VAR_DRVS .. "/audio/vt823x.sys"},
{"DRIVERS/SIS.SYS", VAR_DRVS .. "/audio/sis.sys"},
{"DRIVERS/SDHCI.SYS", "../drivers/sdhci/sdhci.sys"},
{"DRIVERS/I2CHID.SYS", VAR_DRVS .. "/i2chid/i2chid.sys"},
})
tup.append_table(extra_files, {
{"HD_Load/9x2klbr/", VAR_PROGS .. "/hd_load/9x2klbr/9x2klbr.exe"},
@@ -651,20 +647,28 @@ tup.append_table(extra_files, {
{"kolibrios/3D/blocks/block.bin", VAR_PROGS .. "/bcc32/games/blocks/block.bin"},
{"kolibrios/develop/tcc/lib/crt0.o", VAR_PROGS .. "/develop/ktcc/bin/lib/crt0.o", group = "../programs/develop/ktcc/<crt0.o>"},
{"kolibrios/develop/tcc/lib/tiny.o", VAR_PROGS .. "/develop/ktcc/bin/lib/tiny.o", group = "../programs/develop/ktcc/<tiny.o>"},
{"kolibrios/develop/tcc/lib/libsound.a", VAR_PROGS .. "/develop/ktcc/bin/lib/libsound.a", group = "../programs/develop/ktcc/<libsound.a>"}
{"kolibrios/develop/tcc/lib/libsound.a", VAR_PROGS .. "/develop/ktcc/bin/lib/libsound.a", group = "../programs/develop/ktcc/<libsound.a>"},
{"kolibrios/develop/examples/circle", VAR_PROGS .. "/develop/examples/circle/circle"},
{"kolibrios/develop/examples/colorref", VAR_PROGS .. "/demos/colorref/colorref"},
{"kolibrios/develop/examples/conget", VAR_PROGS .. "/develop/libraries/console_coff/examples/test_gets"},
{"kolibrios/develop/examples/cslide", VAR_PROGS .. "/demos/cslide/cslide"},
{"kolibrios/develop/examples/thread", VAR_PROGS .. "/develop/examples/thread/thread"}
})
-- For russian build, add russian-only programs.
if build_type == "ru_RU" then tup.append_table(img_files, {
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
}) else tup.append_table(img_files, {
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
}) end
-- -- For russian build, add russian-only programs.
-- if build_type == "ru_RU" then tup.append_table(img_files, {
-- {"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
-- }) else tup.append_table(img_files, {
-- {"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
-- }) end
if build_type == "ru_RU" then tup.append_table(extra_files, {
{"kolibrios/develop/examples/testcon2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
{"kolibrios/utils/period", VAR_PROGS .. "/other/period/period"},
{"kolibrios/games/Dungeons/Dungeons", VAR_PROGS .. "/games/Dungeons/Dungeons"},
{"kolibrios/games/klavisha/klavisha", VAR_PROGS .. "/games/klavisha/klavisha"},
{"kolibrios/games/klavisha/basekurs.kla", "ru_RU/games/basekurs.kla"},
}) else tup.append_table(extra_files, {
{"kolibrios/develop/examples/testcon2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
}) end
end -- tup.getconfig('NO_FASM') ~= 'full'
+2 -1
View File
@@ -6,8 +6,9 @@
#/SYS/CROPFLAT "XS800 YS480" 1 # set limits of screen
#/SYS/LOADDRV COMMOUSE 1 # serial mouse driver
#/SYS/DEVELOP/BOARD "" 0 # Load DEBUG board
#/SYS/LOADDRV RDC 0 # videodriver for RDC M2010/M2012
/SYS/SETUP BOOT 0 # Load device settings
/SYS/LOADDRV RDC 0 # videodriver for RDC M2010/M2012
/SYS/LOADDRV I2CHID 0 # Start I2C touchpad driver
/SYS/@TASKBAR "" 0 # Start taskbar
/SYS/ESKIN "" 0 # Set style
/SYS/@ICON "" 0 # Multithread desktop icons
+16
View File
@@ -5,6 +5,22 @@ font smoothing=sbp
font height=9
speaker mute=off
[touchpad]
speed=100
; how far a finger must move before the pointer follows, in pad units;
; larger is steadier under a pressing finger, 0 turns the filter off
jitter=1
; the same, for a finger that landed on the button strip: it is pressing
; rather than steering there, so it needs a stricter margin
jitter_buttons=45
scroll_step=64
scroll_invert=0
tap_enable=1
tap_drag=1
right_click=1
button_zone=15
right_split=50
[mouse]
speed=4
acceleration=3
+1 -1
View File
@@ -40,7 +40,7 @@
06 zSea Image Viewer * |/kolibrios/media/zsea/zsea
38 Animage |media/animage
38 IconEdit |media/iconedit
40 Image Filtering |media/imgf/imgf
40 Image Filtering * |/kolibrios/media/ImgF/ImgF
52 Palitra |media/palitra
39 Pipet |develop/pipet
#4 **** MULTIMEDIA
+1 -1
View File
@@ -41,7 +41,7 @@
16 Image viewer KIV |media/kiv
16 Image viewer zSea * |/kolibrios/media/zsea/zsea
16 Animage |media/animage
16 Efectos de imаgenes |media/imgf/imgf
16 Efectos de imаgenes * |/kolibrios/media/ImgF/ImgF
16 Palitra |media/palitra
#4 **** MULTIMEDIA
16 Pixie Audioplayer |media/pixie
+1 -1
View File
@@ -41,7 +41,7 @@
06 Image viewer zSea * |/kolibrios/media/zsea/zsea
38 Animage |media/animage
38 IconEdit |media/iconedit
16 Image Filtering |media/imgf/imgf
16 Image Filtering * |/kolibrios/media/ImgF/ImgF
52 Palitra |media/palitra
39 Pipet |develop/pipet
#4 **** MULTIMEDIA ****
+1 -1
View File
@@ -41,7 +41,7 @@
06 Image viewer zSea * |/kolibrios/media/zsea/zsea
38 Animage |media/animage
38 IconEdit |media/iconedit
40 Image Filtering |media/imgf/imgf
40 Image Filtering * |/kolibrios/media/ImgF/ImgF
52 Palitra |media/palitra
39 Pipet |develop/pipet
#4 **** MULTIMEDIA
+1 -1
View File
@@ -40,7 +40,7 @@
06 Просмотр фото zSea |/kolibrios/media/zsea/zsea
38 Редактор Animage |media/animage
38 Редактор иконок |media/iconedit
40 Наложение фильтров |media/imgf/imgf
40 Наложение фильтров * |/kolibrios/media/ImgF/ImgF
52 Палитра |media/palitra
39 Пипетка |develop/pipet
#4 **** Звук и видео
+102 -17
View File
@@ -273,8 +273,8 @@ RIRB_INT_RESPONSE equ 0x01
RIRB_INT_OVERRUN equ 0x04
RIRB_INT_MASK equ 0x05
; STATESTS int mask: SD2,SD1,SD0
STATESTS_INT_MASK equ 0x07
; STATESTS int mask: SDIWAKE[14:0], a 16-bit register
STATESTS_INT_MASK equ 0x7FFF
AZX_MAX_CODECS equ 4
; SD_CTL bits
@@ -402,6 +402,7 @@ struc AC_CNTRL ;AC controller base class
.response_reset dd 0
.polling_mode db 0
.poll_count db 0
.no_irq db 0 ; no interrupt line: a thread runs hda_irq
.posbuf dd ?
.start_wallclk dd ? ; start + minimum wallclk
.period_wallclk dd ? ; wallclk for period
@@ -505,8 +506,6 @@ macro spin_unlock
pop ebx eax
}
data fixups
end data
include '../../struct.inc'
include '../../macros.inc'
@@ -607,9 +606,6 @@ if IRQ_REMAP
invoke SysMsgBoardStr
end if
mov ebx, [ctrl.int_line]
invoke AttachIntHandler, ebx, hda_irq, dword 0
;Asper This part is from "azx_probe" proc. [
call azx_codec_create
cmp eax, 0
@@ -858,13 +854,13 @@ end if
mov edx, ICH6_REG_SD_STS + SDO_OFS
call azx_readb
mov bl, al
mov cl, al
mov al, SD_INT_MASK
mov edx, ICH6_REG_SD_STS + SDO_OFS
call azx_writeb
test bl, SD_INT_COMPLETE
test cl, SD_INT_COMPLETE
jz @f
mov eax, [ctrl.civ_val]
@@ -901,13 +897,13 @@ end if
;if 0
; clear state status int
mov edx, ICH6_REG_STATESTS
call azx_readb
test al, 0x04
call azx_readw
and eax, STATESTS_INT_MASK
jz @f
mov al, 0x04
; ack all state-change bits, else the level IRQ line stays asserted
mov edx, ICH6_REG_STATESTS
call azx_writeb
call azx_writew
@@:
;end if
or eax, 1
@@ -915,6 +911,24 @@ end if
ret
endp
; Stand-in for the interrupt when no interrupt line is available. A thread,
; not a TimerHS callback: the kernel calls timer callbacks with the global
; timer list lock held, and hda_irq may stall and refill the audio buffer.
; hda_irq runs with interrupts off, as it would in IRQ context: it holds
; aspinlock, which azx_rirb_get_response waits for with interrupts off, so
; a holder that could be preempted would hang the machine.
proc hda_poll_thread
.loop:
pushfd
cli
call hda_irq
popfd
mov eax, 5 ; delay, sleeping instead of spinning
mov ebx, 1 ; 10 ms; a 16 KB period is ~85 ms at 48 kHz
int 0x40
jmp .loop
endp
align 4
proc create_primary_buff
@@ -1203,6 +1217,26 @@ end if
; allocate CORB/RIRB
call azx_alloc_cmd_io
; attach the IRQ handler BEFORE the controller may raise interrupts:
; azx_init_chip enables GIE/CIE and a codec state-change can fire
; right away; an unclaimed level IRQ makes the
; kernel poll foreign handlers and relink their IRQH nodes onto our
; line (see irq_serv .try_other_irqs), corrupting the dispatch list
; a warm reboot can leave GIE and a stale completion bit behind, and
; civ_val is never resynced, so silence the controller before attaching
call azx_int_disable
mov ebx, [ctrl.int_line]
invoke AttachIntHandler, ebx, hda_irq, dword 0
test eax, eax
jnz @f
; No usable interrupt line (INTLINE=0xFF on boards that route INTx only
; through ACPI _PRT or MSI, which the kernel does not parse). The
; controller still latches INTSTS/SD_STS, we only lose the wakeup - so
; poll the RIRB for codec replies and run the interrupt handler from a
; thread. A flag of its own: polling_mode is the timeout recovery state.
mov [ctrl.no_irq], 1
@@:
; initialize chip
call azx_init_pci
@@ -1210,6 +1244,32 @@ end if
call azx_init_chip
;] Asper
; no IRQ line: let a polling thread stand in for the interrupt.
; Started only now - earlier, hda_irq could ack STATESTS in the window
; before reset_controller reads it into codec_mask
cmp [ctrl.no_irq], 0
je @f
push esi edi ; CreateThread clobbers them, START needs esi
mov ebx, 1
mov ecx, hda_poll_thread
xor edx, edx
invoke CreateThread
pop edi esi
test eax, eax
jns .thread_ok
; nothing would ever complete a period and playback would stall,
; so fail the init rather than register a service that hangs
mov esi, msgNoIrqThread
invoke SysMsgBoardStr
xor eax, eax
ret
.thread_ok:
if DEBUG
mov esi, msgNoIrqPoll
invoke SysMsgBoardStr
end if
@@:
xor eax, eax
inc eax
ret
@@ -1243,7 +1303,7 @@ endl
; clear STATESTS
mov eax, STATESTS_INT_MASK
mov edx, ICH6_REG_STATESTS
call azx_writeb
call azx_writew
; reset controller
mov edx, ICH6_REG_GCTL
@@ -1454,6 +1514,12 @@ endp
proc azx_alloc_cmd_io
push eax ecx edx
; the unsolicited-event ring lives in reserved storage, so its
; pointers hold garbage until we clear them here - do it before
; reset_controller enables unsolicited responses in GCTL
mov [unsol_events.rp], 0
mov [unsol_events.wp], 0
; single page (at least 4096 bytes) must suffice for both ringbuffers
invoke KernelAlloc, 4096
mov [ctrl.rb], eax
@@ -1654,14 +1720,24 @@ endl
mov ecx, 1000;+1000
.next_try:
mov al, [ctrl.polling_mode]
test al, al
or al, [ctrl.no_irq]
jnz .poll
mov ah, [do_poll]
test ah, ah
jz @f
.poll:
spin_lock_irq
; take the lock hda_irq holds so two RIRB readers never overlap
push eax ebx
mov eax, aspinlock
.poll_lock:
mov ebx, SPINLOCK_BUSY
lock xchg [eax], ebx
cmp ebx, SPINLOCK_FREE
jnz .poll_lock
pop ebx eax
call azx_update_rirb
mov [aspinlock], SPINLOCK_FREE
spin_unlock_irq
@@:
mov eax, [ctrl.rirb_cmd]
@@ -1942,6 +2018,7 @@ proc azx_int_disable
mov ebx, ICH6_INT_CTRL_EN or ICH6_INT_GLOBAL_EN
xor ebx, -1
and eax, ebx
mov edx, ICH6_REG_INTCTL ; azx_readl turned edx into the absolute address
call azx_writel
pop edx ebx eax
ret
@@ -1957,9 +2034,9 @@ proc azx_int_clear
call azx_writeb
; clear STATESTS
mov al, STATESTS_INT_MASK
mov ax, STATESTS_INT_MASK
mov edx, ICH6_REG_STATESTS
call azx_writeb
call azx_writew
; clear rirb status
mov al, RIRB_INT_MASK
@@ -2696,6 +2773,7 @@ proc snd_hda_queue_unsol_event stdcall, res:dword, res_ex:dword
; only carries EBX across iterations and reloads the rest, and TimerHS
; preserves EBX too - so by using scratch regs only we need no saves.
mov eax, [unsol_events.wp]
and eax, HDA_UNSOL_QUEUE_SIZE - 1 ; never index the ring wild
lea edx, [eax+1]
and edx, HDA_UNSOL_QUEUE_SIZE - 1 ; next write pos (size must be 2^n)
cmp edx, [unsol_events.rp]
@@ -2998,6 +3076,7 @@ sz_sound_srv db 'SOUND',0
msgInit db 'detect hardware...',13,10,0
msgFail db 'device not found',13,10,0
msgNoIrqThread db 'no IRQ line: cannot create polling thread',13,10,0
msgAttchIRQ db 'IRQ line not supported', 13,10,0
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10,0
msgPlay db 'start play', 13,10,0
@@ -3067,6 +3146,7 @@ if DEBUG
msgTCSEL db 'PCI TCSEL ',0
msgTV db 'HDA test version ',TEST_VERSION_NUMBER,13,10,0
msgGCap db 'GCAP = ',0
msgNoIrqPoll db 'no IRQ line: polling thread',13,10,0
end if
if USE_SINGLE_MODE
@@ -3101,6 +3181,11 @@ end if
;] Asper
; relocation table lives after all code and initialized data: placed before the
; code its size feeds back into every relocation site and fasm may never converge
data fixups
end data
aspinlock dd SPINLOCK_FREE
codec CODEC
+100 -14
View File
@@ -130,6 +130,8 @@ RU_STATUS_IDLE = 0000b shl 2
RU_STATUS_SUSPENDED = 0001b shl 2
RU_STATUS_NO_RESOURCES = 0010b shl 2
RU_STATUS_READY = 0100b shl 2
SCB_STATUS_CUS = 11000000b ; CU Status
CU_STATUS_ACTIVE = 10b shl 6
SCB_STATUS_FCP = 1 shl 8 ; Flow Control Pause
SCB_STATUS_SWI = 1 shl 10 ; Software Interrupt
SCB_STATUS_MDI = 1 shl 11 ; MDI read/write complete
@@ -183,6 +185,8 @@ struct txfd
ends
TXFD_STATUS_C = 1 shl 15
TXFD_CMD_IA = 1 shl 0
TXFD_CMD_CFG = 1 shl 1
TXFD_CMD_TX = 1 shl 2
@@ -628,6 +632,9 @@ reset:
mov ax, CU_START or INT_MASK
out dx, ax
call cmd_wait
; cmd_wait only means the SCB accepted the command. The Configure below
; reuses confcmd, so a slow chip would read it instead of our MAC.
call confcmd_wait
;-------------
; Configure CU
@@ -652,6 +659,7 @@ reset:
mov ax, CU_START ; expect Interrupts from now on
out dx, ax
call cmd_wait
call confcmd_wait
; Start media check timer
mov [ebx + device.state], ETH_LINK_DOWN
@@ -678,6 +686,11 @@ init_rx_ring:
;---------------------
; build rxfd structure
cmp [ebx + device.rx_desc], 0 ; the RFD of an earlier reset
je @f
invoke NetFree, [ebx + device.rx_desc]
mov [ebx + device.rx_desc], 0
@@:
invoke NetAlloc, 2000
test eax, eax
jz .out_of_mem
@@ -689,6 +702,7 @@ init_rx_ring:
mov [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
mov [esi + sizeof.NET_BUFF + rxfd.link], eax
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
mov [esi + sizeof.NET_BUFF + rxfd.rx_buf_addr], 0xffffffff ; simplified mode, no RBD
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
ret
@@ -709,6 +723,15 @@ init_tx_ring:
invoke GetPhysAddr
mov ecx, TX_RING_SIZE
.next_desc:
; after a reset with frames still unreclaimed: free them, or transmit sees the
; descriptor busy (virt_addr) and reports TX overrun forever
cmp [esi + txfd.virt_addr], 0
je @f
push eax ecx
invoke NetFree, [esi + txfd.virt_addr]
pop ecx eax
mov [esi + txfd.virt_addr], 0
@@:
mov [esi + txfd.status], 0
mov [esi + txfd.command], 0
lea edx, [eax + txfd.buf_addr]
@@ -763,7 +786,7 @@ proc transmit stdcall bufferptr
lea edi, [ebx + device.tx_ring + eax]
; Check if current descriptor is free or still in use
cmp [edi + txfd.status], 0
cmp [edi + txfd.virt_addr], 0 ; buffer not reclaimed yet
jne .overrun
; Fill in status and command values
@@ -786,6 +809,22 @@ proc transmit stdcall bufferptr
mov eax, edi
invoke GetPhysAddr
set_io [ebx + device.io_addr], 0
; CU_START is only valid while the CU is idle or suspended:
; wait for the previous frame to leave (1.2 ms at 10 Mbit)
push eax ecx
set_io [ebx + device.io_addr], REG_SCB_STATUS
mov ecx, 100000
.cu_busy:
in al, dx
and al, SCB_STATUS_CUS
cmp al, CU_STATUS_ACTIVE
jne .cu_free
dec ecx
jnz .cu_busy
DEBUGF 2, "CU still active, starting anyway\n"
.cu_free:
pop ecx eax
set_io [ebx + device.io_addr], REG_SCB_PTR
out dx, eax
@@ -854,7 +893,7 @@ int_handler:
DEBUGF 1,"Status: %x\n", ax
test ax, SCB_STATUS_FR ; did we receive a frame?
test ax, SCB_STATUS_FR or SCB_STATUS_RNR ; frame received or receiver stopped?
jz .no_rx
push ax
@@ -901,6 +940,7 @@ int_handler:
mov [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
mov [esi + sizeof.NET_BUFF + rxfd.link], eax
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
mov [esi + sizeof.NET_BUFF + rxfd.rx_buf_addr], 0xffffffff ; simplified mode, no RBD
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
; restart RX
@@ -916,11 +956,22 @@ int_handler:
mov ax, RX_START
out dx, ax
call cmd_wait
.out_of_mem:
; Hand the frame over to the kernel
jmp [EthInput]
.out_of_mem:
; The buffer is still our only RFD: drop the frame and reuse it
mov esi, [esp] ; the buffer
mov ecx, [esi + NET_BUFF.length]
dec [ebx + device.packets_rx] ; counted above, before the allocation
sub dword [ebx + device.bytes_rx], ecx
sbb dword [ebx + device.bytes_rx + 4], 0
inc [ebx + device.packets_rx_drop]
add esp, 12 ; buffer, .rx_loop, ebx
mov esi, [ebx + device.rx_desc]
jmp .not_ok
.not_ok:
; Reset the FD
mov [esi + sizeof.NET_BUFF + rxfd.status], 0
@@ -945,6 +996,27 @@ int_handler:
.no_rx_:
DEBUGF 1, "no more data\n"
; With a single RFD the receiver sits in No Resources/Suspended whenever a
; frame arrived before we re-armed it. Nothing restarts it but us.
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], REG_SCB_STATUS
in al, dx
and al, SCB_STATUS_RUS
cmp al, RU_STATUS_READY
je .ru_ready
test byte[esp], 1 ; bit 0 of the saved status is reserved,
jnz .ru_ready ; we mark it: one restart per IRQ
or byte[esp], 1
movzx eax, al
DEBUGF 1, "Restarting receiver, RU status %x\n", eax:2
mov esi, [ebx + device.rx_desc]
push ebx
test [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_C
jnz .rx_loop ; a frame completed meanwhile
add esp, 4
jmp .not_ok ; re-arm the empty RFD
.ru_ready:
pop ax
.no_rx:
@@ -955,13 +1027,13 @@ int_handler:
push eax
.loop_tx:
mov edi, [ebx + device.last_tx]
mov eax, sizeof.txfd
mul eax
mov eax, [ebx + device.last_tx]
mov edx, sizeof.txfd
mul edx
lea edi, [ebx + device.tx_ring + eax]
cmp [edi + txfd.status], 0
je .tx_done
test [edi + txfd.status], TXFD_STATUS_C ; sent by the device?
jz .tx_done
cmp [edi + txfd.virt_addr], 0
je .tx_done
@@ -970,6 +1042,7 @@ int_handler:
push [edi + txfd.virt_addr]
mov [edi + txfd.virt_addr], 0
mov [edi + txfd.status], 0 ; free for transmit again
invoke NetFree
inc [ebx + device.last_tx]
@@ -980,12 +1053,6 @@ int_handler:
pop eax
.no_tx:
test ax, RU_STATUS_NO_RESOURCES
jz .not_out_of_resources
DEBUGF 2, "Out of resources!\n"
.not_out_of_resources:
pop edi esi ebx
xor eax, eax
inc eax
@@ -1079,6 +1146,25 @@ proc check_media_mii stdcall dev:dword
endp
; Wait (up to 1 s) until the device has executed the command in confcmd.
align 4
confcmd_wait:
mov ecx, 1000 ; udelay = Sleep(1), 1 ms
.loop:
test [ebx + device.confcmd.status], TXFD_STATUS_C
jnz .done
call udelay
dec ecx
jnz .loop
movzx eax, [ebx + device.confcmd.command]
DEBUGF 2, "Command 0x%x not completed\n", eax:4
ret
.done:
movzx eax, [ebx + device.confcmd.command]
movzx ecx, [ebx + device.confcmd.status]
DEBUGF 1, "Command 0x%x done, status 0x%x\n", eax:4, ecx:4
ret
align 4
cmd_wait:
File diff suppressed because it is too large. Load diff
-644
View File
@@ -1,644 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; sky2.inc - Marvell Yukon-2 (88E805x and friends) registers
;; for KolibriOS
;;
;; Minimal subset needed to probe the chip and read the permanent
;; MAC address. Expand later for rings, BMU, status LE, etc.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PCI Power Management (capability; standard offset when present)
; We poke the common location used by bge: config offset 0x4C is often PMCSR
; on these chips (capability linked). OpenBSD uses BGE_PCI_PWRMGMT_CMD.
PCI_PWRMGMT_CMD = 0x4C
PCI_PWR_D0 = 0x00
PCI_PWR_D3hot = 0x03
PCI_PWR_PME_ENABLE = 0x0100
;----------------------------------------------------------------------
; PCI vendor / device IDs (subset of the Yukon-2 family)
;----------------------------------------------------------------------
PCI_VENDOR_MARVELL = 0x11AB
; Common 88E805x / Yukon-2 device IDs
PCI_DEVICE_88E8021 = 0x4340
PCI_DEVICE_88E8022 = 0x4341
PCI_DEVICE_88E8035 = 0x4350
PCI_DEVICE_88E8036 = 0x4351
PCI_DEVICE_88E8038 = 0x4352
PCI_DEVICE_88E8039 = 0x4353
PCI_DEVICE_88E8040 = 0x4354
PCI_DEVICE_88E8040T = 0x4355
PCI_DEVICE_88E8052 = 0x4360
PCI_DEVICE_88E8053 = 0x4361
PCI_DEVICE_88E8055 = 0x4363 ; the one we care about first
PCI_DEVICE_88E8056 = 0x4364
PCI_DEVICE_88E8057 = 0x4362
PCI_DEVICE_88E8058 = 0x436A
PCI_DEVICE_88E8071 = 0x436B
PCI_DEVICE_88E8072 = 0x436C
PCI_DEVICE_88E8075 = 0x4370
;----------------------------------------------------------------------
; Control / Status registers (block 0)
;----------------------------------------------------------------------
B0_RAP = 0x0000
B0_CTST = 0x0004 ; Control/Status (16-bit)
B0_POWER_CTRL = 0x0007
B0_ISRC = 0x0008
B0_IMSK = 0x000C
B0_HWE_ISRC = 0x0010
B0_HWE_IMSK = 0x0014
; Yukon-2 special ISR registers
B0_Y2_SP_ISRC2 = 0x001C
B0_Y2_SP_ISRC3 = 0x0020
B0_Y2_SP_EISR = 0x0024
B0_Y2_SP_LISR = 0x0028
B0_Y2_SP_ICR = 0x002C
; CTST bits we care about for a minimal bring-up
CS_RST_SET = 0x0001
CS_RST_CLR = 0x0002
CS_MRST_SET = 0x0004
CS_MRST_CLR = 0x0008
CS_STOP_MASTER = 0x0020
CS_STOP_DONE = 0x0040
CS_SW_IRQ = 0x0200
CS_CL_SW_IRQ = 0x0100
;----------------------------------------------------------------------
; Block 2 – MAC addresses, chip ID, clocks
;----------------------------------------------------------------------
B2_MAC_1 = 0x0100 ; port 0 permanent MAC (6 bytes)
B2_MAC_2 = 0x0108 ; port 1 (if dual)
B2_MAC_3 = 0x0110
B2_CONN_TYP = 0x0118
B2_PMD_TYP = 0x0119
B2_MAC_CFG = 0x011A ; chip revision in bits 7:4
B2_CHIP_ID = 0x011B
B2_E_0 = 0x011C
B2_Y2_CLK_GATE = 0x011D
B2_Y2_HW_RES = 0x011E
B2_E_3 = 0x011F
B2_Y2_CLK_CTRL = 0x0120
; Chip ID values (read from B2_CHIP_ID)
CHIP_ID_YUKON_XL = 0xB3
CHIP_ID_YUKON_EC_U = 0xB4 ; 88E8055 is often this
CHIP_ID_YUKON_EX = 0xB5
CHIP_ID_YUKON_EC = 0xB6
CHIP_ID_YUKON_FE = 0xB7
CHIP_ID_YUKON_FE_P = 0xB8
CHIP_ID_YUKON_SUPR = 0xB9
CHIP_ID_YUKON_UL_2 = 0xBA
CHIP_ID_YUKON_OPT = 0xBC
CHIP_ID_YUKON_PRM = 0xBD
CHIP_ID_YUKON_OP_2 = 0xBE
; B2_MAC_CFG
CFG_CHIP_R_MSK = 0xF0 ; revision in bits 7:4
CFG_SNG_MAC = 0x01 ; 1 = single MAC
;----------------------------------------------------------------------
; ASF / test-control / RAM-interface (used during reset)
;----------------------------------------------------------------------
B28_Y2_ASF_STAT_CMD = 0x0E68 ; 32 bit ASF Status and Command Reg
Y2_ASF_RESET = 1 shl 3 ; ASF system in reset state
Y2_ASF_DISABLE = 1 shl 12 ; ASF unit disable (in B0_CTST)
B2_TST_CTRL1 = 0x0158 ; 8 bit Test Control Register 1
TST_CFG_WRITE_ON = 1 shl 1 ; Enable Config Reg WR
TST_CFG_WRITE_OFF = 1 shl 0 ; Disable Config Reg WR
; Standard PCI config space status register (offset 0x06) - sticky error bits,
; write-1-to-clear. Cleared during reset in case a previous driver load / BIOS
; left an error latched (matches Linux sky2_reset()).
PCI_STATUS_ERROR_BITS = 0xF900 ; PARITY | SIG_SYSERR | REC_MABORT |
; REC_TABORT | SIG_TABORT | DET_PARITY
Y2_CLK_DIV_DIS = 1 shl 0 ; disable core clock division (B2_Y2_CLK_CTRL)
Y2_LED_STAT_ON = 1 shl 9 ; "driver loaded" status LED on (B0_CTST)
;----------------------------------------------------------------------
; Block 8 / Tx Arbiter, GMAC control (SK_REG-style: stride 0x80/port)
;----------------------------------------------------------------------
GMAC_CTRL = 0x0F00 ; 32 bit GMAC Control Reg
GMAC_IRQ_MSK = 0x0F0C ; 8 bit GMAC Interrupt Mask Reg
GMAC_LINK_CTRL = 0x0F10 ; 16 bit GMAC Link Control Reg
GMLC_RST_CLR = 1 shl 1 ; Clear GMAC Link Reset
GMLC_RST_SET = 1 shl 0 ; Set GMAC Link Reset
; GMAC_CTRL bits (this is the GMAC core's OWN reset - distinct from
; GMAC_LINK_CTRL above, and from GPHY_CTRL below. All three are separate
; reset domains and Linux/OpenBSD both toggle all three during bring-up.
GMC_LOOP_OFF = 1 shl 4
GMC_PAUSE_ON = 1 shl 3
GMC_RST_CLR = 1 shl 1 ; Clear GMAC (core) Reset
GMC_RST_SET = 1 shl 0 ; Set GMAC (core) Reset
; GPHY_CTRL - the internal PHY block's own reset (separate register,
; offset 0xf04, SK_REG-style stride 0x80/port like GMAC_CTRL/LINK_CTRL).
; Missing this entirely is what left the PHY permanently unresponsive
; to MDIO on first bring-up - see field log from 2026-08-08.
GPHY_CTRL = 0x0F04
GPC_RST_CLR = 1 shl 1 ; Clear GPHY Reset
GPC_RST_SET = 1 shl 0 ; Set GPHY Reset
;----------------------------------------------------------------------
; MMIO-mirrored PCI config space. The chip exposes a window of its own
; PCI config space directly in MMIO (NOT the same thing as a real PCI
; config cycle via PciRead/PciWrite) - used for the per-chip "OUR_REG"
; power-control registers below. See sky2_pci_read32/if_msk.c
; SK_Y2_PCI_REG() in the reference drivers.
;----------------------------------------------------------------------
Y2_CFG_SPC = 0x1C00
PCI_DEV_REG1 = 0x40
PCI_DEV_REG2 = 0x44
PCI_DEV_REG3 = 0x80
PCI_DEV_REG4 = 0x84
PCI_DEV_REG5 = 0x88
PCI_CFG_REG_1 = 0x94
; PCI_DEV_REG2 bits
PCI_EN_DUMMY_RD = 1 shl 3 ; Enable dummy read
PCI_REV_DESC = 1 shl 2 ; Reverse descriptor bytes (BE CPUs only)
PCI_USEDATA64 = 1 shl 0 ; Use 64-bit data bus extension
; PCI_DEV_REG1 bits - per-port PHY power-down / "coma" mode. These must
; be CLEARED or the internal PHY stays powered down and MDIO will never
; respond, no matter how long you poll (matches the observed symptom).
PCI_Y2_PHY1_POWD = 1 shl 26
PCI_Y2_PHY2_POWD = 1 shl 27
PCI_Y2_PHY1_COMA = 1 shl 28
PCI_Y2_PHY2_COMA = 1 shl 29
; PCI_DEV_REG4 ASPM control bits, masked off during the EC-Ultra/EX/FE+
; "advanced power control" bring-up sequence (SKY2_HW_ADV_POWER_CTL)
P_FORCE_ASPM_REQUEST = 1 shl 15
P_ASPM_GPHY_LINK_DOWN = 1 shl 14
P_ASPM_INT_FIFO_EMPTY = 1 shl 13
P_ASPM_CLKRUN_REQUEST = 1 shl 12
P_ASPM_CONTROL_MSK = P_FORCE_ASPM_REQUEST or P_ASPM_GPHY_LINK_DOWN \
or P_ASPM_CLKRUN_REQUEST or P_ASPM_INT_FIFO_EMPTY
; PCI_DEV_REG5 Vmain_av timer bits, similarly masked
P_CTL_TIM_VMAIN_AV_MSK = 3 shl 27
B2_GP_IO = 0x015C
GLB_GPIO_STAT_RACE_DIS = 1 shl 13 ; workaround for dev 4.107 on EC-U/EX
Y2_HW_WOL_ON = 1 shl 15
;----------------------------------------------------------------------
; GMAC / PHY block (per-port, stride 0x1000, base 0x2800 for port 0)
;----------------------------------------------------------------------
BASE_GMAC_1 = 0x2800 ; port 0 GMAC/PHY register block
BASE_GMAC_2 = 0x3800 ; port 1 GMAC/PHY register block
; Offsets relative to the per-port GMAC block (add to BASE_GMAC_n)
GM_GP_STAT = 0x0000 ; 16 bit r/o General Purpose Status
GM_GP_CTRL = 0x0004 ; 16 bit r/w General Purpose Control
GM_TX_CTRL = 0x0008
GM_RX_CTRL = 0x000C
GM_SERIAL_MODE = 0x0018 ; 16 bit r/w Serial Mode Register
GM_MC_ADDR_H1 = 0x0034
GM_MC_ADDR_H2 = 0x0038
GM_MC_ADDR_H3 = 0x003C
GM_MC_ADDR_H4 = 0x0040
GM_SMI_CTRL = 0x0080 ; 16 bit r/w SMI (MDIO) Control
GM_SMI_DATA = 0x0084 ; 16 bit r/w SMI Data
GM_PHY_ADDR = 0x0088 ; 16 bit r/w GPHY Address
; GM_GP_STAT bits
GM_GPSR_SPEED = 1 shl 15 ; 1 = 100 Mbps (see GIG_SPEED for 1000)
GM_GPSR_DUPLEX = 1 shl 14 ; 1 = Full duplex
GM_GPSR_FC_TX_DIS = 1 shl 13
GM_GPSR_LINK_UP = 1 shl 12 ; Link Up Status
GM_GPSR_GIG_SPEED = 1 shl 4 ; 1 = 1000 Mbps
; GM_GP_CTRL bits
GM_GPCR_TX_ENA = 1 shl 12
GM_GPCR_RX_ENA = 1 shl 11
; GM_RX_CTRL bits
GM_RXCR_UCF_ENA = 1 shl 15 ; enable unicast filtering
GM_RXCR_MCF_ENA = 1 shl 14 ; enable multicast filtering
; GM_SMI_CTRL bits/fields
GM_SMI_CT_PHY_A_MSK = 0x1F shl 11
GM_SMI_CT_REG_A_MSK = 0x1F shl 6
GM_SMI_CT_OP_RD = 1 shl 5 ; opcode read (0 = write)
GM_SMI_CT_RD_VAL = 1 shl 4 ; read completed, data valid
GM_SMI_CT_BUSY = 1 shl 3 ; operation in progress
PHY_ADDR_MARV = 0 ; internal PHY is always MDIO addr 0
PHY_RETRIES = 20 ; MDIO poll retries; each retry sleeps
; ~1ms (Sleep() is ms, not centiseconds -
; confirmed empirically), so 20 = ~20ms
; worst-case before giving up
;----------------------------------------------------------------------
; Marvell internal PHY (88E1xxx) register numbers, via GM_SMI_*
;----------------------------------------------------------------------
PHY_MARV_CTRL = 0x00 ; PHY Control
PHY_MARV_AUNE_ADV = 0x04 ; Auto-Neg. Advertisement
PHY_MARV_1000T_CTRL = 0x09 ; 1000Base-T Control
PHY_MARV_PHY_CTRL = 0x10 ; PHY Specific Control
PHY_MARV_PHY_STAT = 0x11 ; PHY Specific Status
PHY_MARV_INT_MASK = 0x12 ; Interrupt Mask
PHY_MARV_INT_STAT = 0x13 ; Interrupt Status (r/o, clear-on-read)
PHY_MARV_EXT_CTRL = 0x14 ; Ext. PHY Specific Control
; PHY_MARV_CTRL bits
PHY_CT_RESET = 1 shl 15 ; (sc) reset all PHY regs
PHY_CT_SPS_LSB = 1 shl 13 ; speed select, low bit -> PHY_CT_SP100
PHY_CT_ANE = 1 shl 12 ; Auto-Negotiation Enabled
PHY_CT_RE_CFG = 1 shl 9 ; (sc) Restart Auto-Negotiation
PHY_CT_DUP_MD = 1 shl 8 ; Duplex Mode (forced)
PHY_CT_SPS_MSB = 1 shl 6 ; speed select, high bit -> PHY_CT_SP1000
PHY_CT_SP1000 = PHY_CT_SPS_MSB
PHY_CT_SP100 = PHY_CT_SPS_LSB
; PHY_MARV_AUNE_ADV bits
PHY_AN_CSMA = 1 shl 0 ; selector = IEEE 802.3 (always set)
PHY_M_AN_10_HD = 1 shl 5
PHY_M_AN_10_FD = 1 shl 6
PHY_M_AN_100_HD = 1 shl 7
PHY_M_AN_100_FD = 1 shl 8
; PHY_MARV_1000T_CTRL bits
PHY_M_1000C_AHD = 1 shl 8 ; advertise 1000Base-T half duplex
PHY_M_1000C_AFD = 1 shl 9 ; advertise 1000Base-T full duplex
; PHY_MARV_PHY_CTRL bits (copper, "newer PHY" variants incl. EC Ultra)
PHY_M_PC_MDIX_MSK = 3 shl 5
PHY_M_PC_ENA_AUTO = 3 ; enable automatic MDI/MDIX crossover
PHY_M_PC_EN_DET_MSK = 3 shl 8 ; energy detect mask
PHY_M_PC_DSC_MSK = 7 shl 12 ; downshift counter mask
PHY_M_PC_DOWN_S_ENA = 1 shl 11 ; downshift enable
; PHY_MARV_PHY_STAT bits
PHY_M_PS_SPEED_MSK = 3 shl 14
PHY_M_PS_SPEED_1000 = 1 shl 15
PHY_M_PS_SPEED_100 = 1 shl 14
PHY_M_PS_FULL_DUP = 1 shl 13
PHY_M_PS_LINK_UP = 1 shl 10
PHY_M_PS_MDI_X_STAT = 1 shl 6
; PHY_MARV_INT_MASK / PHY_MARV_INT_STAT bits. Reading INT_STAT clears the
; pending condition at the PHY - no separate ack is needed once this is
; serviced (confirmed against both reference drivers: neither writes
; back to INT_STAT, and the top-level B0_ISRC bit below is just a live
; passthrough of the PHY's own interrupt line).
PHY_M_IS_LSP_CHANGE = 1 shl 14 ; Link Speed Changed
PHY_M_IS_DUP_CHANGE = 1 shl 13 ; Duplex Mode Changed
PHY_M_IS_LST_CHANGE = 1 shl 10 ; Link Status Changed
PHY_M_DEF_MSK = PHY_M_IS_LSP_CHANGE or PHY_M_IS_DUP_CHANGE \
or PHY_M_IS_LST_CHANGE
;----------------------------------------------------------------------
; Chip-level (not per-port) interrupt status/mask. B0_ISRC/B0_IMSK are
; already declared above (block 0 registers); B0_ISRC is a live,
; read-only OR of every currently-asserting enabled source - nothing
; needs to be written back to it, only to the underlying source that
; set it (here, PHY_MARV_INT_STAT above).
;----------------------------------------------------------------------
Y2_IS_IRQ_PHY1 = 1 shl 4 ; interrupt from PHY on port 0
Y2_IS_STAT_BMU = 1 shl 30 ; status BMU (RX/TX completion) interrupt
;----------------------------------------------------------------------
; List-element (LE) descriptor rings. Yukon-2 uses a uniform 8-byte
; descriptor for TX, RX, AND the status/completion ring: addr(4),
; length(2), ctrl/css(1), opcode(1). Cross-checked byte-for-byte
; against OpenBSD's msk_tx_desc/msk_rx_desc (if_skreg.h) as well as
; Linux's sky2_tx_le/sky2_rx_le/sky2_status_le - full agreement.
;
; Deliberately out of scope for this pass: 64-bit DMA addressing
; (OP_ADDR64 - not needed, this is a 32-bit OS so every physical
; address already fits in the low 32 bits), scatter-gather/multi-
; fragment packets, VLAN tagging, checksum offload, RSS, jumbo
; frames, and TX/RX interrupt-coalescing timers (STAT_*_TIMER_INI -
; left at their power-on-reset default, which just means the status
; ring reports completions eagerly rather than batched).
;----------------------------------------------------------------------
OP_ADDR64 = 0x21
OP_BUFFER = 0x40
OP_PACKET = 0x41
OP_RXSTAT = 0x60
OP_TXINDEXLE = 0x68
HW_OWNER = 0x80 ; opcode-byte bit: entry owned by hardware
LE_EOP = 0x80 ; ctrl-byte bit: end of packet (TX only)
; Receive Frame Status bits (in a status-ring RX entry's "status" field)
GMR_FS_LEN = 0x7FFF shl 16
GMR_FS_RX_OK = 1 shl 8
GMR_FS_GOOD_FC = 1 shl 7
GMR_FS_BAD_FC = 1 shl 6
GMR_FS_MII_ERR = 1 shl 5
GMR_FS_LONG_ERR = 1 shl 4
GMR_FS_FRAGMENT = 1 shl 3
GMR_FS_CRC_ERR = 1 shl 1
GMR_FS_RX_FF_OV = 1 shl 0
GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV or GMR_FS_CRC_ERR or GMR_FS_FRAGMENT \
or GMR_FS_LONG_ERR or GMR_FS_MII_ERR or GMR_FS_BAD_FC
CSS_LINK_BIT = 1 shl 0 ; port number, within a status entry's css byte
;----------------------------------------------------------------------
; Queue block (Q_CSR/Q_WM/Q_AL/Q_TEST/Q_DONE) - stride B8_Q_REGS-based,
; one block per queue (RX1/RX2/sync-TX1/sync-TX2/async-TX1/async-TX2).
; We only ever use RX1 (port 0 receive) and async-TX1 (port 0 transmit).
;----------------------------------------------------------------------
B8_Q_REGS = 0x0400
Q_R1 = 0x0000 ; RX queue, port 0
Q_XS1 = 0x0200 ; sync TX queue, port 0 (kept disabled)
Q_XA1 = 0x0280 ; async TX queue, port 0 - the one we use
Q_DONE = 0x24 ; 16 bit - Done Index
Q_CSR = 0x34 ; 32 bit - BMU Control/Status
Q_TEST = 0x38 ; 32 bit - Test/Control
Q_WM = 0x40 ; 16 bit - FIFO Watermark
Q_AL = 0x42 ; 8 bit - FIFO Alignment
BMU_CLR_IRQ_PAR = 1 shl 11
BMU_CLR_IRQ_CHK = 1 shl 10
BMU_START = 1 shl 8
BMU_FIFO_ENA = 1 shl 5
BMU_FIFO_RST = 1 shl 4
BMU_OP_ON = 1 shl 3
BMU_OP_OFF = 1 shl 2
BMU_FIFO_OP_ON = 1 shl 7
BMU_RST_CLR = 1 shl 1
BMU_CLR_RESET = BMU_FIFO_RST or BMU_OP_OFF or BMU_RST_CLR
BMU_OPER_INIT = BMU_CLR_IRQ_PAR or BMU_CLR_IRQ_CHK or BMU_START \
or BMU_FIFO_ENA or BMU_OP_ON
BMU_WM_DEFAULT = 0x600
F_TX_CHK_AUTO_OFF = 1 shl 31 ; Q_TEST: disable TX descriptor auto-check
F_TX_CHK_AUTO_ON = 1 shl 30
F_M_RX_RAM_DIS = 1 shl 24 ; Q_TEST bit: MAC Rx RAM read port
; disabled - required on EC-Ultra
; chip_rev > A0 (ours is rev 3), see
; Linux sky2_rx_start()
CHIP_REV_YU_EC_U_A0 = 1
;----------------------------------------------------------------------
; Prefetch unit - the interface between the driver's LE ring and the
; hardware. Separate register block from Q_CSR above despite similar
; per-queue addressing (base + queue-offset + reg).
;----------------------------------------------------------------------
Y2_B8_PREF_REGS = 0x0450
PREF_UNIT_CTRL = 0x00 ; 32 bit
PREF_UNIT_LAST_IDX = 0x04 ; 16 bit
PREF_UNIT_ADDR_LO = 0x08 ; 32 bit
PREF_UNIT_ADDR_HI = 0x0C ; 32 bit
PREF_UNIT_GET_IDX = 0x10 ; 16 bit
PREF_UNIT_PUT_IDX = 0x14 ; 16 bit
PREF_UNIT_RST_SET = 1 shl 0
PREF_UNIT_RST_CLR = 1 shl 1
PREF_UNIT_OP_ON = 1 shl 3
;----------------------------------------------------------------------
; RAM buffer arbiter - per-queue FIFO sizing within the chip's internal
; RAM. Sizes are in "qwords" (8-byte units) per the hardware register
; definition; sky2_ramset-equivalent code below converts from KB.
;----------------------------------------------------------------------
B16_RAM_REGS = 0x0800
RB_START = 0x00 ; 32 bit
RB_END = 0x04 ; 32 bit
RB_WP = 0x08 ; 32 bit
RB_RP = 0x0C ; 32 bit
RB_RX_UTPP = 0x10 ; 32 bit - Rx upper thresh, pause pkt
RB_RX_LTPP = 0x14 ; 32 bit - Rx lower thresh, pause pkt
RB_RX_UTHP = 0x18 ; 32 bit - Rx upper thresh, high prio
RB_RX_LTHP = 0x1C ; 32 bit - Rx lower thresh, high prio
RB_CTRL = 0x28 ; 32 bit
RB_ENA_STFWD = 1 shl 5 ; enable store & forward (Tx queues)
RB_ENA_OP_MD = 1 shl 3
RB_DIS_OP_MD = 1 shl 2
RB_RST_CLR = 1 shl 1
RB_RST_SET = 1 shl 0
B2_E_0 = 0x011C ; 8 bit - internal RAM size, in 4K blocks
;----------------------------------------------------------------------
; TX arbiter - per-port, SK_REG-style addressing (stride 0x80/port,
; same block as GMAC_CTRL/GPHY_CTRL/GMAC_LINK_CTRL).
;----------------------------------------------------------------------
TXA_ITI_INI = 0x0200 ; 32 bit
TXA_LIM_INI = 0x0208 ; 32 bit
TXA_CTRL = 0x0210 ; 8 bit
TXA_ENA_FSYNC = 1 shl 7
TXA_DIS_FSYNC = 1 shl 6
TXA_ENA_ALLOC = 1 shl 5
TXA_DIS_ALLOC = 1 shl 4
TXA_START_RC = 1 shl 3
TXA_STOP_RC = 1 shl 2
TXA_ENA_ARB = 1 shl 1
TXA_DIS_ARB = 1 shl 0
;----------------------------------------------------------------------
; Status/completion ring (card-wide, not per-port). The BMU writes
; completion entries here as RX/TX work finishes; the driver polls
; each entry's HW_OWNER bit rather than tracking a separate hardware
; "put index" register, which keeps the interrupt handler simple and
; is exactly the same safety check Linux does per-entry regardless.
;----------------------------------------------------------------------
STAT_FIFO_ISR_WM= 0x0ead ; 8 bit Status FIFO ISR Watermark Reg
STAT_LEV_TIMER_INI = 0x0eb0 ; 32 bit Level Timer Init. Value Reg
STAT_LEV_TIMER_CTRL = 0x0eb8 ; 8 bit Level Timer Control Reg
STAT_CTRL = 0x0E80 ; 32 bit
STAT_LAST_IDX = 0x0E84 ; 16 bit
STAT_LIST_ADDR_LO = 0x0E88 ; 32 bit
STAT_LIST_ADDR_HI = 0x0E8C ; 32 bit
STAT_TX_IDX_TH = 0x0E98 ; 16 bit
STAT_PUT_IDX = 0x0E9C ; 16 bit
STAT_FIFO_WM = 0x0EAC ; 8 bit
STAT_TX_TIMER_INI = 0x0ec0 ; 32 bit Tx Timer Init. Value Reg
STAT_ISR_TIMER_CNT = 0x0ed4 ; 32 bit ISR Timer Counter Reg
STAT_ISR_TIMER_CTRL = 0x0ed8 ; 8 bit ISR Timer Control Reg
STAT_TX_TIMER_CTRL = 0x0ec8 ; 8 bit Tx Timer Control Reg
STAT_ISR_TIMER_INI = 0x0ed0 ; 32 bit ISR Timer Init. Value Reg
SC_STAT_OP_ON = 1 shl 3
SC_STAT_RST_CLR = 1 shl 1
SC_STAT_RST_SET = 1 shl 0
SC_STAT_CLR_IRQ = 1 shl 4
;----------------------------------------------------------------------
; Ring sizing. Both counts must be powers of two (ring-wrap uses a
; mask, not a divide). Kept modest and identical to what RTL8169/
; i8254x already use in this tree.
;----------------------------------------------------------------------
TX_LE_SIZE = 128 ; must be a power of 2, between 128 and 2048
RX_LE_SIZE = 128 ; must be a power of 2, between 128 and 2048
ST_RING_SIZE = 512 ; comfortably more than TX+RX combined
RX_BUF_SIZE = 1536 ; MTU 1500 + Ethernet header + slack
;----------------------------------------------------------------------
; Generic 8-byte list-element layout, shared by TX/RX/status rings
; (see the LE ring comment above for the cross-reference).
;----------------------------------------------------------------------
struct le
addr dd ?
length dw ?
ctrl db ? ; "css" on a status-ring entry
opcode db ?
ends
;----------------------------------------------------------------------
; Device structure (extends ETH_DEVICE)
;----------------------------------------------------------------------
struct device ETH_DEVICE
; PCI / MMIO
mmio_addr dd ?
pci_bus dd ?
pci_dev dd ?
irq_line db ?
rb 3
; Chip identification
chip_id db ? ; CHIP_ID_YUKON_*
chip_rev db ?
port db ? ; 0 for single-port cards
rb 1
chip_name dd ? ; pointer to ASCII name
; Link state, as last read from GM_GP_STAT (see link_status).
; device.state (in ETH_DEVICE, standard kernel-facing field) is
; kept in sync with these and is what NetLinkChanged reports.
link_up db ? ; 0 = down, 1 = up
link_duplex db ? ; 0 = half, 1 = full
link_speed dw ? ; Mbps: 10 / 100 / 1000 (0 if link down)
; ---- TX/RX/status rings. Embedded directly in the device
; struct, same pattern RTL8169 uses in this tree: the struct
; itself is allocated via allocate_and_clear, which guarantees
; physical contiguity up to 8 pages (32K) - our rings total
; well under 2K, so this is safe. Raw byte reservation (not a
; typed struct array) matching RTL8169's own tx_ring/rx_ring
; convention - this struct.inc doesn't support array-of-custom-
; struct fields, only single-instance nesting; per-entry access
; is done via sizeof.le * slot_index offset math instead.
rb 0x1000-($ and 0xfff) ; align 256
tx_le rb TX_LE_SIZE * sizeof.le
rb 0x1000-($ and 0xfff) ; align 256
rx_le rb RX_LE_SIZE * sizeof.le
rb 0x1000-($ and 0xfff) ; align 256
st_le rb ST_RING_SIZE * sizeof.le
; Software-only bookkeeping, parallel to the rings above but
; NOT hardware-visible - just our own buffer-pointer tracking.
; (NetAlloc'd pointer per slot; 0 = slot has no owned buffer.)
tx_buf rd TX_LE_SIZE
rx_buf rd RX_LE_SIZE
; Ring indices. All are plain 0-based slot numbers, wrapped
; with a power-of-two mask (SIZE-1), not divided.
tx_prod dw ? ; next free TX slot to fill
tx_cons dw ? ; oldest TX slot still in flight
rx_put dw ? ; next RX slot to (re)submit
rx_next dw ? ; oldest RX slot awaiting completion
st_idx dw ? ; next status-ring slot to read
ends
RX_GMF_CTRL_T = 0x0C48
TX_GMF_CTRL_T = 0x0D48
RX_GMF_LP_THR = 0x0C4A ; 8 bit Rx GMAC FIFO low pause threshold
RX_GMF_UP_THR = 0x0C4B ; 8 bit Rx GMAC FIFO upper pause threshold
GMF_RST_SET = 1 shl 0
GMF_RST_CLR = 1 shl 1
GMF_OPER_ON = 1 shl 3
GMF_RX_F_FL_ON = 1 shl 7
; TX GMF high bits (Yukon-EC Ultra) - store & forward required when no RAM
TX_STFW_DIS = 1 shl 31
TX_STFW_ENA = 1 shl 30
TX_JUMBO_ENA = 1 shl 23
TX_JUMBO_DIS = 1 shl 22
; RAM Interface (B3_*) - initialized during reset even when there is no
; external RAM. Still required for the internal FIFO/GMF data path.
B3_RI_WTO_R1 = 0x0190
B3_RI_WTO_XA1 = 0x0191
B3_RI_WTO_XS1 = 0x0192
B3_RI_RTO_R1 = 0x0193
B3_RI_RTO_XA1 = 0x0194
B3_RI_RTO_XS1 = 0x0195
B3_RI_WTO_R2 = 0x0196
B3_RI_WTO_XA2 = 0x0197
B3_RI_WTO_XS2 = 0x0198
B3_RI_RTO_R2 = 0x0199
B3_RI_RTO_XA2 = 0x019a
B3_RI_RTO_XS2 = 0x019b
B3_RI_CTRL = 0x01a0
RI_RST_CLR = 1 shl 1
RI_RST_SET = 1 shl 0
SK_RI_TO_53 = 36 ; Linux/OpenBSD default timeout value
; GM_GP_CTRL extra bits (speed/duplex force)
GM_GPCR_GIGS_ENA = 1 shl 7
GM_GPCR_DUP_FULL = 1 shl 5
GM_GPCR_SPEED_100 = 1 shl 3
GM_GPCR_SPEED_1000 = (GM_GPCR_GIGS_ENA or GM_GPCR_SPEED_100)
GM_GPCR_AU_DUP_DIS = 1 shl 2
GM_GPCR_AU_FCT_DIS = 1 shl 1
GM_GPCR_AU_SPD_DIS = 1 shl 0
TIM_START = 1 shl 2 ; ; Start Timer
TIM_STOP = 1 shl 1 ; ; Stop Timer
TIM_CLR_IRQ = 1 shl 0 ; ; Clear Timer IRQ (!IRQM)
GM_SRC_ADDR_1L = 0x001c;, ; 16 bit r/w Source Address 1 (low)
GM_SRC_ADDR_1M = 0x0020;, ; 16 bit r/w Source Address 1 (middle)
GM_SRC_ADDR_1H = 0x0024;, ; 16 bit r/w Source Address 1 (high)
GM_SRC_ADDR_2L = 0x0028;, ; 16 bit r/w Source Address 2 (low)
GM_SRC_ADDR_2M = 0x002c;, ; 16 bit r/w Source Address 2 (middle)
GM_SRC_ADDR_2H = 0x0030;, ; 16 bit r/w Source Address 2 (high)
Y2_IS_HW_ERR = 1 shl 31 ; Interrupt HW Error
Y2_IS_STAT_BMU = 1 shl 30 ; Status BMU Interrupt
Y2_IS_ASF = 1 shl 29 ; ASF subsystem Interrupt
Y2_IS_CPU_TO = 1 shl 28 ; CPU Timeout
Y2_IS_POLL_CHK = 1 shl 27 ; Check IRQ from polling unit
Y2_IS_TWSI_RDY = 1 shl 26 ; IRQ on end of TWSI Tx
Y2_IS_IRQ_SW = 1 shl 25 ; SW forced IRQ
Y2_IS_TIMINT = 1 shl 24 ; IRQ from Timer
Y2_IS_IRQ_PHY2 = 1 shl 12 ; Interrupt from PHY 2
Y2_IS_IRQ_MAC2 = 1 shl 11 ; Interrupt from MAC 2
Y2_IS_CHK_RX2 = 1 shl 10 ; Descriptor error Rx 2
Y2_IS_CHK_TXS2 = 1 shl 9 ; Descriptor error TXS 2
Y2_IS_CHK_TXA2 = 1 shl 8 ; Descriptor error TXA 2
Y2_IS_PSM_ACK = 1 shl 7 ; PSM Acknowledge (Yukon-Optima only)
Y2_IS_PTP_TIST = 1 shl 6 ; PTP Time Stamp (Yukon-Optima only)
Y2_IS_PHY_QLNK = 1 shl 5 ; PHY Quick Link (Yukon-Optima only)
Y2_IS_IRQ_PHY1 = 1 shl 4 ; Interrupt from PHY 1
Y2_IS_IRQ_MAC1 = 1 shl 3 ; Interrupt from MAC 1
Y2_IS_CHK_RX1 = 1 shl 2 ; Descriptor error Rx 1
Y2_IS_CHK_TXS1 = 1 shl 1 ; Descriptor error TXS 1
Y2_IS_CHK_TXA1 = 1 shl 0 ; Descriptor error TXA 1
+3
View File
@@ -0,0 +1,3 @@
if tup.getconfig("NO_FASM") ~= "" then return end
ROOT = "../.."
tup.rule("i2chid.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
+438
View File
@@ -0,0 +1,438 @@
; Synopsys DesignWare I2C master, polled (PIO) mode only.
; This is the controller inside Intel LPSS blocks (Skylake and newer, plus
; Atom-derived SoCs); the same IP is used by many other vendors.
;
; The register file is always accessed as dwords. The controller must be
; disabled to change IC_TAR, so every transfer disables it, programs the
; target address, enables it back and feeds the TX FIFO by hand.
; ------------------------------ Registers ------------------------------------
DwIcCon = 0x00
DwIcTar = 0x04
DwIcDataCmd = 0x10
DwIcSsSclHcnt = 0x14
DwIcSsSclLcnt = 0x18
DwIcFsSclHcnt = 0x1C
DwIcFsSclLcnt = 0x20
DwIcIntrStat = 0x2C
DwIcIntrMask = 0x30
DwIcRawIntrStat = 0x34
DwIcRxTl = 0x38
DwIcTxTl = 0x3C
DwIcClrIntr = 0x40
DwIcClrTxAbrt = 0x54
DwIcEnable = 0x6C
DwIcStatus = 0x70
DwIcTxflr = 0x74
DwIcRxflr = 0x78
DwIcSdaHold = 0x7C
DwIcTxAbrtSource = 0x80
DwIcEnableStatus = 0x9C
DwIcCompParam1 = 0xF4
DwIcCompVersion = 0xF8
DwIcCompType = 0xFC
; "DW_apb_i2c" component signature ('DW' + 0x0140).
DW_COMP_TYPE_VALUE = 0x44570140
; IC_CON: master, standard speed (100 kHz), restarts allowed, slave disabled.
DW_CON_MASTER = 1 shl 0
DW_CON_SPEED_STD = 1 shl 1
DW_CON_SPEED_FAST = 2 shl 1
DW_CON_RESTART_EN = 1 shl 5
DW_CON_SLAVE_DIS = 1 shl 6
; IC_DATA_CMD bits above the data byte.
DW_CMD_READ = 1 shl 8
DW_CMD_STOP = 1 shl 9
DW_CMD_RESTART = 1 shl 10
; IC_STATUS bits
DW_STAT_TFNF = 1 shl 1 ; TX FIFO not full
DW_STAT_TFE = 1 shl 2 ; TX FIFO empty
DW_STAT_RFNE = 1 shl 3 ; RX FIFO not empty
DW_STAT_MST_ACT = 1 shl 5 ; master FSM busy
; IC_RAW_INTR_STAT bits
DW_INT_TX_ABRT = 1 shl 6
; SCL timing for standard mode. The LPSS input clock is 100 MHz on the PCH
; parts and 133 MHz on the Atom-derived SoCs (Apollo Lake, Gemini Lake), and
; nothing in PCI config space says which one this is, so the counts are
; picked to satisfy the fast-mode minimums at the fastest of them: at
; 133 MHz that is tHIGH = 0.98 us and tLOW = 1.5 us, 400 kHz. On a 100 MHz
; part the same counts run the bus at 300 kHz, which is just as legal.
; Fast mode rather than standard: HID over I2C requires every device to
; support it, that is what Windows drives them at, and a polled host pays
; for every byte with busy-waiting - at 100 kHz a 64-byte input read costs
; 6 ms, more than a fast pad takes to produce the next report, and the
; backlog that builds up plays back as the cursor coasting after the finger
; has stopped. SDA hold stays well below tLOW.
DW_FS_HCNT = 130
DW_FS_LCNT = 200
DW_SDA_HOLD = 28
; The AMD FCH feeds its DesignWare masters from a 150 MHz reference, so
; the same minimums need more counts there: 145/225 give tHIGH = 0.97 us,
; tLOW = 1.5 us, again 400 kHz; SDA hold 45 = 300 ns.
DW_AMD_FS_HCNT = 145
DW_AMD_FS_LCNT = 225
DW_AMD_SDA_HOLD = 45
; A transfer gives up after [XferTimeout] hundredths of a second. The init
; value must cover a full report descriptor read: descriptors run up to 2 KB
; and the bus may be as slow as 77 kHz, so at 9 SCL cycles per byte a single
; transfer takes ~240 ms of wall-clock time. Polling is generous too now that it runs in its own thread
; rather than in a timer callback - a wedged bus costs this thread its slice
; and nothing else.
DW_TIMEOUT_INIT = 60
DW_TIMEOUT_POLL = 20
; Disables the controller and waits until it reports itself disabled.
; in: ebx = MMIO base. Clobbers eax, ecx.
proc dw_ctrl_disable
mov dword [ebx+DwIcEnable], 0
mov ecx, 100000
@@:
test dword [ebx+DwIcEnableStatus], 1
jz .done
pause
loop @b
.done:
ret
endp
; Aborts a stuck transfer cleanly: the ABORT bit makes the master issue STOP,
; flush the TX FIFO and raise TX_ABRT, which releases a slave that is holding
; the bus (a clock-stretching touchpad, for instance). Simply disabling the
; controller in the middle of a byte would leave SDA held low and every
; following transfer would time out too. Older cores without the ABORT bit
; just ignore the write and fall through after the wait.
; in: ebx = MMIO base. Clobbers eax, ecx.
proc dw_ctrl_abort
mov dword [ebx+DwIcEnable], 3
mov ecx, 100000
@@:
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
jnz @f
pause
loop @b
@@:
mov eax, [ebx+DwIcClrTxAbrt]
call dw_ctrl_disable
ret
endp
; One idle step of a transfer wait loop.
; A healthy transfer is over within a few milliseconds, well inside the
; first two timer ticks, and spins through them: a transfer that yields
; its slice is at the scheduler's mercy for the rest of it. Past that the
; bus is stuck or crawling, and the wait gives up the CPU a tick at a time
; instead of burning a core until XferTimeout.
; in: eax = ticks elapsed since the transfer began. Preserves all but eax.
DW_SPIN_TICKS = 2
proc dw_wait_step
cmp eax, DW_SPIN_TICKS
jae .yield
pause
ret
.yield:
push ebx
movi ebx, 1
invoke Delay ; preserves every register
pop ebx
ret
endp
; One-time controller setup after mapping.
; in: ebx = MMIO base.
proc dw_ctrl_init
push eax ecx
call dw_ctrl_disable
mov dword [ebx+DwIcCon], DW_CON_MASTER + DW_CON_SPEED_FAST + \
DW_CON_RESTART_EN + DW_CON_SLAVE_DIS
; The counts come from variables: they depend on the reference clock, which
; is decided by whoever found the controller (PCI LPSS or AMD FCH). The
; standard-mode registers get the same values scaled up so that they are
; sane should anything ever switch the speed bits back.
mov eax, [DwHcnt]
mov [ebx+DwIcFsSclHcnt], eax
lea eax, [eax*4]
mov [ebx+DwIcSsSclHcnt], eax
mov eax, [DwLcnt]
mov [ebx+DwIcFsSclLcnt], eax
lea eax, [eax*4]
mov [ebx+DwIcSsSclLcnt], eax
mov eax, [DwSdaHold]
mov [ebx+DwIcSdaHold], eax
mov dword [ebx+DwIcIntrMask], 0
mov dword [ebx+DwIcRxTl], 0
mov dword [ebx+DwIcTxTl], 0
mov eax, [ebx+DwIcClrIntr]
pop ecx eax
ret
endp
; One combined I2C transaction: optional write phase, then optional read phase
; with a repeated START between them. Fully polled.
; out: eax = 0 on success, IC_TX_ABRT_SOURCE value on NAK/abort, -1 on timeout.
proc dw_xfer stdcall uses ebx esi edi, addr:dword, wbuf:dword, wlen:dword, \
rbuf:dword, rlen:dword
locals
wsent dd ?
rqueued dd ?
rgot dd ?
t0 dd ?
endl
mov ebx, [I2cMmio]
call dw_ctrl_disable
mov eax, [addr]
mov [ebx+DwIcTar], eax
mov eax, [ebx+DwIcClrIntr]
mov dword [ebx+DwIcEnable], 1
xor eax, eax
mov [wsent], eax
mov [rqueued], eax
mov [rgot], eax
invoke GetTimerTicks
mov [t0], eax
.loop:
; Abort (NAK and friends) ends the transfer immediately.
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
jnz .abort
; Drain the RX FIFO first so it can never overflow.
test dword [ebx+DwIcStatus], DW_STAT_RFNE
jz .no_rx
mov edx, [rgot]
cmp edx, [rlen]
jae .no_rx
mov eax, [ebx+DwIcDataCmd]
mov edi, [rbuf]
mov [edi+edx], al
inc edx
mov [rgot], edx
jmp .loop
.no_rx:
; Feed the write phase.
mov eax, [wsent]
cmp eax, [wlen]
jae .push_reads
test dword [ebx+DwIcStatus], DW_STAT_TFNF
jz .check_done
mov esi, [wbuf]
movzx edx, byte [esi+eax]
inc eax
cmp eax, [wlen]
jne @f
cmp [rlen], 0
jne @f
or edx, DW_CMD_STOP ; last byte of a write-only transfer
@@:
mov [ebx+DwIcDataCmd], edx
mov [wsent], eax
jmp .loop
.push_reads:
; Feed read commands, at most 8 outstanding so the RX FIFO keeps up.
mov eax, [rqueued]
cmp eax, [rlen]
jae .check_done
mov edx, eax
sub edx, [rgot]
cmp edx, 8
jae .check_done
test dword [ebx+DwIcStatus], DW_STAT_TFNF
jz .check_done
mov edx, DW_CMD_READ
test eax, eax
jnz @f
cmp [wlen], 0
je @f
or edx, DW_CMD_RESTART ; repeated START after the write phase
@@:
mov ecx, [rlen]
dec ecx
cmp eax, ecx
jne @f
or edx, DW_CMD_STOP
@@:
mov [ebx+DwIcDataCmd], edx
inc eax
mov [rqueued], eax
jmp .loop
.check_done:
mov eax, [rgot]
cmp eax, [rlen]
jne .not_done
mov eax, [wsent]
cmp eax, [wlen]
jne .not_done
mov eax, [ebx+DwIcStatus]
test eax, DW_STAT_TFE
jz .not_done
test eax, DW_STAT_MST_ACT
jnz .not_done
call dw_ctrl_disable
xor eax, eax
ret
.not_done:
invoke GetTimerTicks
sub eax, [t0]
cmp eax, [XferTimeout]
jae .timeout
call dw_wait_step
jmp .loop
.abort:
mov esi, [ebx+DwIcTxAbrtSource]
mov eax, [ebx+DwIcClrTxAbrt]
call dw_ctrl_disable
mov eax, esi
test eax, eax
jnz @f
or eax, 0x80000000
@@:
ret
.timeout:
call dw_ctrl_abort
or eax, -1
ret
endp
; Reads one HID input report as a single continuous bus transaction, the way
; interrupt-driven hosts (Windows, Linux) do it: the optional register-address
; write and every read command are queued into the TX FIFO before the bytes
; start flowing, so nothing on the wire depends on how fast the host loop
; runs. The previous adaptive read (fetch 2 length bytes, decide, fetch the
; rest, stop short) was cut down on the wire to 3 bytes for an empty poll -
; and the SIPODEV/Hantick touchpad firmwares are exactly the kind of thing
; that wedges when an input read is shorter than the frame they prepared.
; rlen should not exceed the TX FIFO depth (IC_COMP_PARAM_1 bits 23:16, plus
; one) or the queue loop degrades to feeding the FIFO on the fly, which
; reintroduces pauses.
; in: addr = slave, wlen bytes at wbuf written first (0 = plain read),
; rlen bytes read into buf.
; out: eax = 0 ok, IC_TX_ABRT_SOURCE on NAK/abort, -1 on timeout.
; Timeout check for the dw_read_block wait spots; expands inside the proc so
; [t0] and [XferTimeout] resolve in the caller's own frame.
macro BLOCK_TICK fail_label {
invoke GetTimerTicks
sub eax, [t0]
cmp eax, [XferTimeout]
jae fail_label
call dw_wait_step
}
proc dw_read_block stdcall uses ebx esi edi, addr:dword, wbuf:dword, wlen:dword, buf:dword, rlen:dword
locals
rgot dd ?
t0 dd ?
endl
mov ebx, [I2cMmio]
call dw_ctrl_disable
mov eax, [addr]
mov [ebx+DwIcTar], eax
mov eax, [ebx+DwIcClrIntr]
mov dword [ebx+DwIcEnable], 1
invoke GetTimerTicks
mov [t0], eax
mov [rgot], 0
; Write phase: the register address bytes, no STOP - the read continues the
; same transaction after a repeated START.
xor ecx, ecx
.wr:
cmp ecx, [wlen]
jae .queue_reads
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
jnz .abort
test dword [ebx+DwIcStatus], DW_STAT_TFNF
jz .wr_wait
mov esi, [wbuf]
movzx edx, byte [esi+ecx]
mov [ebx+DwIcDataCmd], edx
inc ecx
jmp .wr
.wr_wait:
BLOCK_TICK .timeout
jmp .wr
.queue_reads:
xor ecx, ecx
.rq:
cmp ecx, [rlen]
jae .drain
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
jnz .abort
test dword [ebx+DwIcStatus], DW_STAT_TFNF
jz .rq_wait
mov edx, DW_CMD_READ
test ecx, ecx
jnz .not_first
cmp [wlen], 0
je .not_first
or edx, DW_CMD_RESTART
.not_first:
mov eax, [rlen]
dec eax
cmp ecx, eax
jne @f
or edx, DW_CMD_STOP
@@:
mov [ebx+DwIcDataCmd], edx
inc ecx
; Drain opportunistically so a FIFO shallower than rlen cannot deadlock the
; queue loop (the RX side fills while the TX side is full).
test dword [ebx+DwIcStatus], DW_STAT_RFNE
jz .rq
call .take_byte
jmp .rq
.rq_wait:
BLOCK_TICK .timeout
jmp .rq
.drain:
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
jnz .abort
test dword [ebx+DwIcStatus], DW_STAT_RFNE
jz .chk
call .take_byte
jmp .drain
; Moves one byte from the RX FIFO into the caller's buffer. Exactly rlen
; reads are queued into freshly flushed FIFOs, so a byte beyond rlen should
; never arrive; if one does anyway it is still taken off the FIFO, so the
; drain loop cannot stall on it, but it is dropped rather than written
; past the end of the buffer.
.take_byte:
mov edx, [rgot]
mov eax, [ebx+DwIcDataCmd]
cmp edx, [rlen]
jae @f
mov edi, [buf]
mov [edi+edx], al
inc edx
mov [rgot], edx
@@:
retn
.chk:
mov eax, [rgot]
cmp eax, [rlen]
jne .wait
test dword [ebx+DwIcStatus], DW_STAT_MST_ACT
jnz .wait
call dw_ctrl_disable
xor eax, eax
ret
.wait:
BLOCK_TICK .timeout
jmp .drain
.abort:
mov esi, [ebx+DwIcTxAbrtSource]
mov eax, [ebx+DwIcClrTxAbrt]
call dw_ctrl_disable
mov eax, esi
test eax, eax
jnz @f
or eax, 0x80000000
@@:
ret
.timeout:
call dw_ctrl_abort
or eax, -1
ret
endp
+646
View File
@@ -0,0 +1,646 @@
; Minimal HID report descriptor parser.
;
; The goal is not a full HID implementation: the parser walks the descriptor
; once and remembers the bit layout of the first input report that contains
; relative X and relative Y (Generic Desktop / X, Y) - i.e. the mouse
; compatibility collection that every I2C mouse and every Windows Precision
; Touchpad exposes. Buttons (Usage Page 9) and a relative wheel found in the
; same report are picked up too. Absolute (digitizer) reports are advanced
; over but otherwise ignored.
;
; Report IDs are honoured: bit positions are counted separately per report ID
; and the chosen ID is checked in every incoming packet.
;
; Alongside the mouse report, the parser also maps the touchpad (Windows
; Precision Touchpad) report: the report that carries Tip Switch usages.
; Each Tip Switch opens a new finger block; the absolute X and Y that follow
; it belong to that finger; Contact Count and the Button-page fields of the
; same report are recorded too. Once the pad is switched into touchpad mode
; those offsets are what the frame decoder reads - every vendor lays the
; frame out differently, and only the descriptor knows how.
HID_MAX_FINGERS = 5
HID_MAX_USAGES = 16
HID_MAX_REPIDS = 16
; Returns the pointer to the input bit counter of the current report ID,
; allocating a new slot on first use.
; out: ebx -> dword bit counter. Clobbers eax, ecx.
proc hid_get_bits_slot
mov eax, [p_report_id]
xor ecx, ecx
.scan:
cmp ecx, [p_idcnt]
jae .add
cmp eax, [p_ids+ecx*4]
jz .found
inc ecx
jmp .scan
.add:
cmp ecx, HID_MAX_REPIDS
jb @f
dec ecx ; table full: reuse the last slot
jmp .found
@@:
mov [p_ids+ecx*4], eax
mov dword [p_bits+ecx*4], 0
mov dword [p_fbits+ecx*4], 0
inc [p_idcnt]
.found:
lea ebx, [p_bits+ecx*4]
ret
endp
; Handles one Input main item. v_flags = item data (bit 2 = relative).
proc hid_process_input
push eax ebx ecx edx
call hid_get_bits_slot
mov eax, [ebx]
mov [v_base], eax
; Advance the counter over this field right away.
mov eax, [p_report_size]
imul eax, [p_report_count]
add [ebx], eax
; Remember the largest logical maximum ever attached to Generic Desktop X
; and Y. The mouse collection declares a tiny relative range there while
; the touchpad collection declares the real surface extents, so the
; maximum over the whole descriptor is the size of the pad - which is what
; the button zones are measured against, and it differs per model.
cmp [p_usage_cnt], 0
je .no_extent
xor ecx, ecx
.ext_loop:
cmp ecx, [p_usage_cnt]
jae .no_extent
mov eax, [p_usages+ecx*4]
cmp eax, 0x00010030
jne .ext_y
mov eax, [p_log_max]
cmp eax, [t_padmaxx]
jbe .ext_next
mov [t_padmaxx], eax
jmp .ext_next
.ext_y:
cmp eax, 0x00010031
jne .ext_next
mov eax, [p_log_max]
cmp eax, [t_padmaxy]
jbe .ext_next
mov [t_padmaxy], eax
.ext_next:
inc ecx
jmp .ext_loop
.no_extent:
; Button-style field: Usage Minimum/Maximum on the Button page.
cmp [p_usage_min], -1
je .not_buttons
cmp [p_usage_max], -1
je .not_buttons
cmp [p_usage_page], 9
jne .not_buttons
cmp [p_report_size], 1 ; buttons are always 1-bit fields
jne .done
mov eax, [v_base]
mov ecx, [p_report_count]
call hid_note_buttons
jmp .done
.not_buttons:
cmp [p_usage_cnt], 0
je .done
call hid_note_touchpad
; Usage-list field: look for GD/X, GD/Y, GD/Wheel among the usages.
test [v_flags], 4 ; only relative fields are interesting
jz .done
xor ecx, ecx
.usage_loop:
cmp ecx, [p_report_count]
jae .done
; usage index = min(field index, usage count - 1): a short usage list
; applies its last usage to the remaining fields.
mov edx, [p_usage_cnt]
dec edx
mov eax, ecx
cmp eax, edx
jbe @f
mov eax, edx
@@:
mov eax, [p_usages+eax*4]
cmp eax, 0x00010030
je .is_x
cmp eax, 0x00010031
je .is_y
cmp eax, 0x00010038
je .is_wheel
.next_usage:
inc ecx
jmp .usage_loop
.is_x:
test [t_have], 1
jnz .next_usage
call hid_claim_report_id
jc .next_usage
call hid_field_offset
mov [t_xoff], eax
mov eax, [p_report_size]
mov [t_xsize], eax
or [t_have], 1
jmp .next_usage
.is_y:
test [t_have], 2
jnz .next_usage
call hid_claim_report_id
jc .next_usage
call hid_field_offset
mov [t_yoff], eax
mov eax, [p_report_size]
mov [t_ysize], eax
or [t_have], 2
jmp .next_usage
.is_wheel:
test [t_have], 8
jnz .next_usage
mov eax, [t_id]
cmp eax, -1 ; wheel never claims a report on its own
je .next_usage
cmp eax, [p_report_id]
jne .next_usage
call hid_field_offset
mov [t_woff], eax
mov eax, [p_report_size]
mov [t_wsize], eax
or [t_have], 8
jmp .next_usage
.done:
pop edx ecx ebx eax
ret
endp
; Records a run of 1-bit Button-page fields starting at bit eax, ecx of them.
; The mouse decoder wants the buttons of ITS report: an item from some other
; report is kept only until a better one turns up, and .eof drops it if it
; still does not match. The touchpad report keeps its own copy.
proc hid_note_buttons
push eax ecx edx
cmp ecx, 8
jbe @f
mov ecx, 8
@@:
mov edx, [p_report_id]
cmp edx, [t_ptp_id]
jne .mouse
cmp [t_pbtn_cnt], 0
jne .mouse
mov [t_pbtn_off], eax
mov [t_pbtn_cnt], ecx
.mouse:
cmp [t_btncnt], 0
je .take
mov edx, [t_btnid]
cmp edx, [t_id] ; already the chosen report's: keep
je .done
mov edx, [p_report_id]
cmp edx, [t_btnid] ; a second run in the same report: keep the first
je .done
.take:
mov [t_btnoff], eax
mov [t_btncnt], ecx
mov eax, [p_report_id]
mov [t_btnid], eax
.done:
pop edx ecx eax
ret
endp
; Walks the usages of the current input item looking for the touchpad
; fields. Field k takes usage min(k, count-1), as in the mouse search.
proc hid_note_touchpad
push eax ebx ecx edx
xor ecx, ecx
.field:
cmp ecx, [p_report_count]
jae .done
mov edx, [p_usage_cnt]
dec edx
mov eax, ecx
cmp eax, edx
jbe @f
mov eax, edx
@@:
mov ebx, [p_usages+eax*4] ; ebx = usage of field ecx
call hid_field_offset ; eax = its bit offset
cmp ebx, 0x000D0042 ; Tip Switch: a new finger
je .tip
cmp ebx, 0x000D0054 ; Contact Count
je .count
cmp ebx, 0x000D0051 ; Contact Identifier
je .cid
cmp ebx, 0x00010030
je .x
cmp ebx, 0x00010031
je .y
shr ebx, 16
cmp ebx, 9 ; buttons written as a usage list
jne .next
push ecx
neg ecx
add ecx, [p_report_count] ; the fields from here to the end
call hid_note_buttons
pop ecx
jmp .done ; one run per item is enough
.tip:
cmp [t_ptp_id], -1
jne @f
mov edx, [p_report_id]
mov [t_ptp_id], edx ; the first report with fingers is the one
@@:
call hid_in_ptp
jne .next
mov edx, [t_fcount]
cmp edx, HID_MAX_FINGERS
jae .next
mov [t_ftip+edx*4], eax
mov dword [t_fxs+edx*4], 0
mov dword [t_fys+edx*4], 0
mov dword [t_fcids+edx*4], 0
inc [t_fcount]
jmp .next
.cid:
call hid_in_ptp
jne .next
mov edx, [t_fcount]
test edx, edx
jz .next
dec edx
cmp dword [t_fcids+edx*4], 0
jne .next
mov [t_fcid+edx*4], eax
mov eax, [p_report_size]
mov [t_fcids+edx*4], eax
jmp .next
.count:
call hid_in_ptp
jne .next
mov [t_ccnt_off], eax
mov eax, [p_report_size]
mov [t_ccnt_size], eax
jmp .next
.x:
test [v_flags], 4 ; absolute only; relative is the mouse
jnz .next
call hid_in_ptp
jne .next
mov edx, [t_fcount]
test edx, edx
jz .next
dec edx
cmp dword [t_fxs+edx*4], 0
jne .next
mov [t_fx+edx*4], eax
mov eax, [p_report_size]
mov [t_fxs+edx*4], eax
jmp .next
.y:
test [v_flags], 4
jnz .next
call hid_in_ptp
jne .next
mov edx, [t_fcount]
test edx, edx
jz .next
dec edx
cmp dword [t_fys+edx*4], 0
jne .next
mov [t_fy+edx*4], eax
mov eax, [p_report_size]
mov [t_fys+edx*4], eax
.next:
inc ecx
jmp .field
.done:
pop edx ecx ebx eax
ret
endp
; ZF set when the current item belongs to the touchpad report.
proc hid_in_ptp
push eax
mov eax, [p_report_id]
cmp eax, [t_ptp_id]
pop eax
ret
endp
; Size in bytes of the feature report with id eax; 0 when the descriptor
; never mentioned one.
proc hid_feature_bytes
push ecx
xor ecx, ecx
@@:
cmp ecx, [p_idcnt]
jae .none
cmp eax, [p_ids+ecx*4]
je .found
inc ecx
jmp @b
.found:
mov eax, [p_fbits+ecx*4]
add eax, 7
shr eax, 3
pop ecx
ret
.none:
xor eax, eax
pop ecx
ret
endp
; Locks the candidate report ID to the current one, or fails (CF=1) when a
; different report already holds X/Y.
proc hid_claim_report_id
mov eax, [t_id]
cmp eax, -1
jne @f
mov eax, [p_report_id]
mov [t_id], eax
clc
ret
@@:
cmp eax, [p_report_id]
jne .taken
clc
ret
.taken:
stc
ret
endp
; Bit offset of field #ecx of the current item.
; in: ecx = field index. out: eax = v_base + ecx * report_size.
proc hid_field_offset
mov eax, [p_report_size]
imul eax, ecx
add eax, [v_base]
ret
endp
; Parses the report descriptor.
; in: esi -> descriptor, ecx = length.
; out: eax = 1 and f_* variables filled if a usable report was found.
proc hid_parse_report_desc uses ebx esi edi
lea edi, [esi+ecx]
xor eax, eax
mov [p_usage_page], eax
mov [p_report_size], eax
mov [p_report_count], eax
mov [p_report_id], eax
mov [p_uses_repid], eax
mov [p_usage_cnt], eax
mov [p_idcnt], eax
mov [p_log_max], eax
mov [t_padmaxx], eax
mov [t_padmaxy], eax
mov [t_have], eax
mov [t_btncnt], eax
mov [t_wsize], eax
mov [p_usage_min], -1
mov [p_usage_max], -1
mov [t_id], -1
mov [t_btnid], -2
mov [t_ptp_id], -1
mov [t_fcount], eax
mov [t_ccnt_size], eax
mov [t_pbtn_cnt], eax
mov [t_ptp_bytes], eax
.loop:
cmp esi, edi
jae .eof
movzx eax, byte [esi]
inc esi
cmp al, 0xFE
je .long_item
mov ecx, eax
and ecx, 3
cmp ecx, 3
jne @f
inc ecx ; size code 3 means 4 bytes
@@:
lea ebx, [esi+ecx]
cmp ebx, edi
ja .eof
xor edx, edx
jecxz .no_data
cmp ecx, 1
jne @f
movzx edx, byte [esi]
jmp .have_data
@@:
cmp ecx, 2
jne @f
movzx edx, word [esi]
jmp .have_data
@@:
mov edx, [esi]
.have_data:
add esi, ecx
.no_data:
and eax, 0xFC
; Global items
cmp al, 0x04
je .g_usage_page
cmp al, 0x84
je .g_report_id
cmp al, 0x74
je .g_report_size
cmp al, 0x94
je .g_report_count
cmp al, 0x24
je .g_log_max
; Local items
cmp al, 0x08
je .l_usage
cmp al, 0x18
je .l_usage_min
cmp al, 0x28
je .l_usage_max
; Main items
cmp al, 0x80
je .m_input
cmp al, 0x90
je .m_clear_locals
cmp al, 0xB0
je .m_feature
cmp al, 0xA0
je .m_clear_locals
cmp al, 0xC0
je .m_clear_locals
jmp .loop
.g_usage_page:
and edx, 0xFFFF
mov [p_usage_page], edx
jmp .loop
.g_report_id:
mov [p_report_id], edx
mov [p_uses_repid], 1
jmp .loop
.g_report_size:
mov [p_report_size], edx
jmp .loop
.g_report_count:
mov [p_report_count], edx
jmp .loop
.g_log_max:
mov [p_log_max], edx
jmp .loop
.l_usage:
mov ebx, [p_usage_cnt]
cmp ebx, HID_MAX_USAGES
jae .loop
cmp ecx, 4 ; 4-byte usage carries its own page
je @f
mov eax, [p_usage_page]
shl eax, 16
or edx, eax
@@:
mov [p_usages+ebx*4], edx
inc [p_usage_cnt]
jmp .loop
.l_usage_min:
mov [p_usage_min], edx
jmp .loop
.l_usage_max:
mov [p_usage_max], edx
jmp .loop
.m_input:
mov [v_flags], edx
call hid_process_input
jmp .m_clear_locals ; input bits are not feature bits
.m_feature:
; Feature reports are only ever written, never decoded, but writing one
; needs its exact size: a SET_REPORT shorter than the report is ignored by
; some firmwares (the Elan Input Mode report has two bytes, mode and the
; selective-reporting switches - one byte does nothing there).
call hid_get_bits_slot
mov eax, [p_report_size]
imul eax, [p_report_count]
add [p_fbits+ecx*4], eax
.m_clear_locals:
xor eax, eax
mov [p_usage_cnt], eax
mov [p_usage_min], -1
mov [p_usage_max], -1
jmp .loop
.long_item:
cmp esi, edi
jae .eof
movzx ecx, byte [esi]
lea esi, [esi+ecx+2]
jmp .loop
.eof:
; Size of the touchpad report, when there is one.
mov eax, [t_ptp_id]
cmp eax, -1
je .no_ptp
xor ecx, ecx
@@:
cmp ecx, [p_idcnt]
jae .no_ptp
cmp eax, [p_ids+ecx*4]
je @f
inc ecx
jmp @b
@@:
mov eax, [p_bits+ecx*4]
add eax, 7
shr eax, 3
mov [t_ptp_bytes], eax
.no_ptp:
; Success needs relative X and Y in the same report - or, failing that, a
; touchpad report with at least one complete finger, which is then the only
; thing the device will be driven through.
mov eax, [t_have]
and eax, 3
cmp eax, 3
je .have_mouse
cmp [t_fcount], 0
je .fail
cmp dword [t_fxs], 0
je .fail
cmp dword [t_fys], 0
je .fail
mov [f_repid], -1 ; no mouse report to match
mov [f_bytes], 0
mov [t_btncnt], 0
movi eax, 1
ret
.have_mouse:
; Keep buttons/wheel only when they live in the chosen report.
mov eax, [t_btnid]
cmp eax, [t_id]
je @f
mov [t_btncnt], 0
@@:
; Final layout.
mov eax, [t_id]
mov [f_repid], eax
xor ecx, ecx
@@:
cmp ecx, [p_idcnt]
jae .no_bits
cmp eax, [p_ids+ecx*4]
je .got_bits
inc ecx
jmp @b
.got_bits:
mov eax, [p_bits+ecx*4]
add eax, 7
shr eax, 3
mov [f_bytes], eax
movi eax, 1
ret
.no_bits:
.fail:
xor eax, eax
ret
endp
; Extracts an unsigned field from an input report.
; in: esi -> report data, eax = bit offset, ecx = bit count (1..24).
; out: eax = value.
proc hid_extract_u
push ebx ecx edx
mov edx, eax
shr edx, 3
mov ebx, [esi+edx] ; buffer has spare bytes at the end
and eax, 7
push ecx
mov ecx, eax
shr ebx, cl
pop ecx
neg ecx
add ecx, 32
shl ebx, cl
shr ebx, cl
mov eax, ebx
pop edx ecx ebx
ret
endp
; Same, sign-extended.
proc hid_extract_s
push ebx ecx edx
mov edx, eax
shr edx, 3
mov ebx, [esi+edx]
and eax, 7
push ecx
mov ecx, eax
shr ebx, cl
pop ecx
neg ecx
add ecx, 32
shl ebx, cl
sar ebx, cl
mov eax, ebx
pop edx ecx ebx
ret
endp
File diff suppressed because it is too large. Load diff
+26
View File
@@ -0,0 +1,26 @@
[touchpad]
; pointer speed in percent of the driver's default (on top of the [mouse]
; speed above; pads differ in resolution)
speed=100
; how far a finger must move before the pointer follows, in pad units;
; larger is steadier under a pressing finger, 0 turns the filter off
jitter=1
; the same, for a finger that landed on the button strip: it is pressing
; rather than steering there, so it needs a stricter margin
jitter_buttons=45
; pad units of two-finger travel per wheel step, and the direction
scroll_step=64
scroll_invert=0
; turn a short, still touch into a click: one finger left, two right,
; three middle
tap_enable=1
; tap, then touch again at once and move: the button stays down for that
; second touch - this is how text is selected and how one draws
tap_drag=1
; right click: 0 never, 1 bottom-right corner, 2 by finger count (two
; fingers right, three middle), 3 either
right_click=1
; button strip along the bottom edge, in percent of the surface: its
; height, and where its left half ends
button_zone=15
right_split=50
+72
View File
@@ -0,0 +1,72 @@
; Asks the I2C touchpad driver to read its settings again.
;
; The driver takes everything it can be tuned with from the [touchpad] section
; of /sys/settings/system.ini, and it reads that file once while loading. This
; tells it to read the file again, so editing a setting takes effect straight
; away instead of at the next boot.
;
; There is no window: the outcome goes to the debug board, the way the driver
; reports everything else.
format binary as ""
use32
db 'MENUET01'
dd 1, start, i_end, mem, mem, 0, 0
include '../../programs/macros.inc'
SRV_RELOAD_CONF = 1
start:
; 1. Find the driver's service by name.
mcall 68, 16, srv_name
test eax, eax
jz .no_driver
mov [ioctl.handle], eax
; 2. Ask it to reload. No data travels either way: the driver reads the file
; itself, so the settings file stays the only place they are written down.
mcall 68, 17, ioctl
test eax, eax
jnz .refused
mov esi, msg_ok
jmp .say
.no_driver:
mov esi, msg_no_driver
jmp .say
.refused:
mov esi, msg_refused
.say:
call board_str
or eax, -1
mcall
; Writes a zero-terminated string to the debug board.
; in: esi -> string
board_str:
lodsb
test al, al
jz .done
mov cl, al
mcall 63, 1
jmp board_str
.done:
ret
srv_name db 'I2CHID', 0
align 4
ioctl:
.handle dd 0
.io_code dd SRV_RELOAD_CONF
.input dd 0
.inp_size dd 0
.output dd 0
.out_size dd 0
msg_ok db 'tpreload: touchpad settings reloaded', 13, 10, 0
msg_no_driver db 'tpreload: the I2C touchpad driver is not loaded', 13, 10, 0
msg_refused db 'tpreload: the driver refused the request', 13, 10, 0
i_end:
rb 1024
mem:
+1
View File
@@ -139,6 +139,7 @@ import core,\
RegKeyboard,\
DelKeyboard,\
Sleep,\
Delay,\
GetTimerTicks,\
\
strncat,\
+8 -2
View File
@@ -1754,8 +1754,14 @@ proc disk_read_write stdcall uses ebx esi edi, \
mov eax, [numsectors]
mov eax, [eax]
; 2. The transfer length for SCSI_{READ,WRITE}10 commands can not be greater
; than 0xFFFF, so split the request to slices with <= 0xFFFF sectors.
max_sectors_at_time = 0xFFFF
; than 0xFFFF sectors, but that is not the practical limit: the field size is
; the only thing the standard bounds, while real sticks hang their firmware on
; multi-megabyte single commands. The kernel disk cache asks for as much as
; CACHE_MAX_ALLOC_SIZE (4 MB) in one call, i.e. 8192 sectors, and that is
; exactly where such sticks stop answering and re-enumerate. Linux caps
; usb-storage at 240 sectors (120 KB) for the same reason; do the same and
; split larger requests into slices.
max_sectors_at_time = 240
.split:
push eax ; .length_rest
cmp eax, max_sectors_at_time
File diff suppressed because it is too large. Load diff
+1 -2
View File
@@ -842,8 +842,7 @@ disk_scan_partitions:
cmp ebx, mbr_buffer
jz .release_partition_buffer
; 15b. If we have allocated it, free it.
xchg eax, ebx
call free
stdcall kernel_free, ebx
jmp .nothing
; 15c. Otherwise, release reference.
.release_partition_buffer:
+6 -1
View File
@@ -183,6 +183,8 @@ EFLAGS_ID = 0x200000 ; id flag
IRQ_PIC = 0
IRQ_APIC = 1
IO_MAP_SIZE = 65536/8 ; 8192 or 2 PAGE_SIZE
struct TSS
_back rw 2
_esp0 rd 1
@@ -290,6 +292,9 @@ sys_proc = OS_BASE + 0x008E000
SLOT_BASE = OS_BASE + 0x0090000
APPDATA_IDLE_THREAD = SLOT_BASE + sizeof.APPDATA*1 ; poiner to IDLE thread
APPDATA_OS_THREAD = SLOT_BASE + sizeof.APPDATA*2 ; poiner to OS thread
VGABasePtr = OS_BASE + 0x00A0000
virtual at OS_BASE + 0x05FFF80
@@ -570,7 +575,7 @@ struct APPDATA
ipc_start dd ? ;+160
ipc_size dd ? ;+164
occurred_events dd ? ;+168 ; mask which accumulates occurred events
debugger_slot dd ? ;+172 ; index in SLOT_BASE array
debugger_thread dd ? ;+172 ; pointer to APPDATA or 0
terminate_protection dd ? ;+176
keyboard_mode db ? ;+180
rb 3
+41 -77
View File
@@ -8,8 +8,8 @@
; diamond, 2006
sys_debug_services:
cmp ebx, 9
ja @f
cmp ebx, sys_debug_services_table.count
jae @f
jmp dword [sys_debug_services_table + ebx*4]
@@:
ret
@@ -26,7 +26,9 @@ sys_debug_services_table:
dd debug_write_process_memory
dd debug_terminate
dd debug_set_drx
.count = ($ - sys_debug_services_table)/4
endg
debug_set_event_data:
; in: ecx = pointer
; destroys eax
@@ -34,22 +36,20 @@ debug_set_event_data:
mov [eax + APPDATA.dbg_event_mem], ecx
ret
get_debuggee_slot:
get_debuggee_thread:
; in: ecx=PID
; out: CF=1 if error
; CF=0 and eax=slot*0x20 if ok
; CF=0 and eax = pointer to APPDATA if ok
; out: interrupts disabled
cli
mov eax, ecx
call pid_to_slot
;call pid_to_appdata
call pid_to_thread
test eax, eax
jz .ret_bad
shl eax, BSF sizeof.APPDATA
push ebx
mov ebx, [current_slot_idx]
cmp [SLOT_BASE + eax + APPDATA.debugger_slot], ebx
;cmp [eax + APPDATA.debugger_slot], ebx
mov ebx, [current_slot]
cmp [eax + APPDATA.debugger_thread], ebx
pop ebx
jnz .ret_bad
; clc ; automatically
@@ -61,10 +61,9 @@ get_debuggee_slot:
debug_detach:
; in: ecx=pid
; destroys eax,ebx
call get_debuggee_slot
call get_debuggee_thread
jc .ret
and dword [eax + SLOT_BASE + APPDATA.debugger_slot], 0
;and dword [eax + APPDATA.debugger_slot], 0
and dword [eax + APPDATA.debugger_thread], 0
call do_resume
.ret:
sti
@@ -72,40 +71,27 @@ debug_detach:
debug_terminate:
; in: ecx=pid
call get_debuggee_slot
call get_debuggee_thread
jc debug_detach.ret
mov ecx, eax
shr ecx, BSF sizeof.APPDATA
;movzx ecx, ch ; del when sysfn_term... will using APPDATA
; push 2
; pop ebx
mov edx, esi ; what?
movzx ecx, ch ; del when sysfn_term... will using APPDATA
jmp sysfn_terminate
debug_suspend:
; in: ecx=pid
; destroys eax,ecx
; { Patch by Coldy (rev. 7125), reason: http://board.kolibrios.org/viewtopic.php?f=1&t=1712&p=75957#p75957
; cli
; mov eax, ecx
; call pid_to_slot
; shl eax, 5
; jz .ret
call get_debuggee_slot
call get_debuggee_thread
jc .ret
; } End patch
mov cl, [SLOT_BASE + eax + APPDATA.state] ; process state
;mov cl, [eax + APPDATA.state] ; process state
mov cl, [eax + APPDATA.state] ; process state
test cl, cl
jz .1
cmp cl, TSTATE_WAITING
jnz .ret
mov cl, TSTATE_WAIT_SUSPENDED
.2:
mov [SLOT_BASE + eax + APPDATA.state], cl
;mov [eax + APPDATA.state], cl
mov [eax + APPDATA.state], cl
.ret:
sti
ret
@@ -114,16 +100,14 @@ debug_suspend:
jmp .2
do_resume:
mov cl, [SLOT_BASE + eax + APPDATA.state]
;mov cl, [eax + APPDATA.state]
mov cl, [eax + APPDATA.state]
cmp cl, TSTATE_RUN_SUSPENDED
jz .1
cmp cl, TSTATE_WAIT_SUSPENDED
jnz .ret
mov cl, TSTATE_WAITING
.2:
mov [SLOT_BASE + eax + APPDATA.state], cl
;mov [eax + APPDATA.state], cl
mov [eax + APPDATA.state], cl
.ret:
ret
.1:
@@ -133,11 +117,9 @@ do_resume:
debug_resume:
; in: ecx=pid
; destroys eax,ebx
cli
mov eax, ecx
call pid_to_slot
shl eax, BSF sizeof.APPDATA
jz .ret
call get_debuggee_thread
jc .ret
call do_resume
.ret:
sti
@@ -160,21 +142,15 @@ debug_getcontext:
inc ebx ; 1 - get sse context
; TODO legacy 32-bit FPU/MMX context
.std_ctx:
call get_debuggee_slot
call get_debuggee_thread
jc .ret
shr eax, BSF sizeof.APPDATA
;movzx ebp, ah
cmp eax, [fpu_owner]
;cmp ebp, [fpu_owner]
jne @f
inc bh ; set swap context flag
@@:
shl eax, BSF sizeof.APPDATA
mov edi, esi
mov eax, [SLOT_BASE + eax + APPDATA.pl0_stack]
;mov eax, [eax + APPDATA.pl0_stack]
mov eax, [eax + APPDATA.pl0_stack]
lea esi, [eax + RING0_STACK_SIZE]
.ring0:
@@ -240,11 +216,10 @@ debug_setcontext:
cmp edx, 28h
jnz .ret
call get_debuggee_slot
call get_debuggee_thread
jc .stiret
; mov esi, edx
mov eax, [eax + SLOT_BASE+APPDATA.pl0_stack]
;mov eax, [eax + APPDATA.pl0_stack]
mov eax, [eax + APPDATA.pl0_stack]
lea edi, [eax + RING0_STACK_SIZE]
.ring0:
@@ -277,15 +252,16 @@ debug_setcontext:
ret
debug_set_drx:
call get_debuggee_slot
call get_debuggee_thread
jc .errret
mov ebp, eax
lea eax, [eax + SLOT_BASE + APPDATA.dbg_regs]
;lea eax, [eax + APPDATA.dbg_regs]
lea eax, [eax + APPDATA.dbg_regs]
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3
; [eax+10]=dr7
cmp esi, OS_BASE
jae .errret
cmp dl, 3
ja .errret
mov ecx, dr7
@@ -306,10 +282,7 @@ debug_set_drx:
btr dword [eax + 10h], edx ; clear L<i> bit
test byte [eax + 10h], 55h
jnz .okret
; imul eax, ebp, tss_step/32
; and byte [eax + tss_data + TSS._trap], not 1
and [SLOT_BASE + ebp + APPDATA.dbg_state], not 1
;and [ebp + APPDATA.dbg_state], not 1
and [ebp + APPDATA.dbg_state], not 1
.okret:
and dword [esp + SYSCALL_STACK.eax], 0
sti
@@ -354,10 +327,7 @@ debug_set_drx:
not ebx
and [eax + 10h+2], bx
or [eax + 10h+2], dx ; set R/W and LEN fields
; imul eax, ebp, tss_step/32
; or byte [eax + tss_data + TSS._trap], 1
or [SLOT_BASE + ebp + APPDATA.dbg_state], 1
;or [ebp + APPDATA.dbg_state], 1
or [ebp + APPDATA.dbg_state], 1
jmp .okret
debug_read_process_memory:
@@ -368,10 +338,9 @@ debug_read_process_memory:
; esi=address in debuggee
; out: [esp+36]=sizeof(read)
; destroys all
call get_debuggee_slot
call get_debuggee_thread
jc .err
shr eax, BSF sizeof.APPDATA
;movzx eax,ah
mov ecx, edi
call read_process_memory
sti
@@ -389,10 +358,9 @@ debug_write_process_memory:
; esi=address in debuggee
; out: [esp+36]=sizeof(write)
; destroys all
call get_debuggee_slot
call get_debuggee_thread
jc debug_read_process_memory.err
shr eax, BSF sizeof.APPDATA
;movzx eax,ah
mov ecx, edi
call write_process_memory
sti
@@ -400,7 +368,7 @@ debug_write_process_memory:
ret
debugger_notify:
; in: eax=debugger slot
; in: eax=debugger thread
; ecx=size of debug message
; [esp+4]..[esp+4+ecx]=message
; interrupts must be disabled!
@@ -410,9 +378,7 @@ debugger_notify:
mov edi, [timer_ticks]
add edi, 500 ; 5 sec timeout
.1:
mov eax, ebp
shl eax, BSF sizeof.APPDATA
mov esi, [SLOT_BASE + eax + APPDATA.dbg_event_mem]
mov esi, [ebp + APPDATA.dbg_event_mem]
test esi, esi
jz .ret
; read buffer header
@@ -466,8 +432,6 @@ debugger_notify:
pop edx
call write_process_memory
; new debug event
mov eax, ebp
shl eax, BSF sizeof.APPDATA
or [SLOT_BASE + eax + APPDATA.occurred_events], EVENT_DEBUG
or [ebp + APPDATA.occurred_events], EVENT_DEBUG
.ret:
ret
+49 -37
View File
@@ -150,10 +150,10 @@ init_avx512:
ret
; param
; eax= 512 bytes memory area aligned on a 16-byte boundary
align 4
; @brief Export function - Save FPU context in buffer
; @param eax - 512 bytes memory area aligned on a 16-byte boundary
; @return not return
fpu_save:
push ecx
push esi
@@ -166,7 +166,7 @@ fpu_save:
mov edi, eax
mov ecx, [fpu_owner]
mov esi, [current_slot_idx]
mov esi, [current_slot]
cmp ecx, esi
jne .save
@@ -175,14 +175,11 @@ fpu_save:
.save:
mov [fpu_owner], esi
shl ecx, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + ecx + APPDATA.fpu_state]
mov eax, [ecx + APPDATA.fpu_state]
call save_context
; first 512 bytes of XSAVE area have the same format as FXSAVE
shl esi, BSF sizeof.APPDATA
mov esi, [SLOT_BASE + esi + APPDATA.fpu_state]
mov esi, [esi + APPDATA.fpu_state]
mov ecx, 512/4
cld
rep movsd
@@ -194,14 +191,16 @@ fpu_save:
pop ecx
ret
; @brief Export function - Get size from AVX context
; @return size of buffer
avx_save_size:
mov eax, [xsave_area_size]
ret
; param
; eax= avx_save_size() bytes memory area aligned on a 64-byte boundary
align 4
; @brief Export function - Save AVX context in buffer
; @param eax - avx_save_size() bytes memory area aligned on a 64-byte boundary
; @return not return
avx_save:
push ecx
push esi
@@ -214,7 +213,7 @@ avx_save:
mov edi, eax
mov ecx, [fpu_owner]
mov esi, [current_slot_idx]
mov esi, [current_slot]
cmp ecx, esi
jne .save
@@ -223,13 +222,10 @@ avx_save:
.save:
mov [fpu_owner], esi
shl ecx, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + ecx + APPDATA.fpu_state]
mov eax, [ecx + APPDATA.fpu_state]
call save_context
shl esi, BSF sizeof.APPDATA
mov esi, [SLOT_BASE + esi + APPDATA.fpu_state]
mov esi, [esi + APPDATA.fpu_state]
mov ecx, [xsave_area_size]
add ecx, 3
shr ecx, 2
@@ -264,9 +260,13 @@ save_fpu_context:
align 4
; @brief Export function - Restore FPU context
; @param eax - 512 bytes memory area aligned on a 16-byte boundary
; @return not return
fpu_restore:
push ecx
push esi
push edi
mov esi, eax
@@ -274,7 +274,7 @@ fpu_restore:
cli
mov ecx, [fpu_owner]
mov eax, [current_slot_idx]
mov eax, [current_slot]
cmp ecx, eax
jne .copy
@@ -284,6 +284,8 @@ fpu_restore:
fxrstor [esi]
popfd
pop edi
pop esi
pop ecx
ret
@@ -291,24 +293,31 @@ fpu_restore:
fnclex ;fix possible problems
frstor [esi]
popfd
pop edi
pop esi
pop ecx
ret
.copy:
shl eax, BSF sizeof.APPDATA
mov edi, [SLOT_BASE + eax + APPDATA.fpu_state]
mov edi, [eax + APPDATA.fpu_state]
mov ecx, 512/4
cld
rep movsd
popfd
pop edi
pop esi
pop ecx
ret
align 4
; @brief Export function - Restore AVX context
; @param eax - avx_save_size() bytes memory area aligned on a 64-byte boundary
; @return not return
avx_restore:
push ecx
push esi
push edi
mov esi, eax
@@ -316,7 +325,7 @@ avx_restore:
cli
mov ecx, [fpu_owner]
mov eax, [current_slot_idx]
mov eax, [current_slot]
cmp ecx, eax
jne .copy
@@ -329,6 +338,8 @@ avx_restore:
xrstor [esi]
pop edx
popfd
pop edi
pop esi
pop ecx
ret
@@ -338,6 +349,8 @@ avx_restore:
fxrstor [esi]
popfd
pop edi
pop esi
pop ecx
ret
@@ -345,18 +358,21 @@ avx_restore:
fnclex ;fix possible problems
frstor [esi]
popfd
pop edi
pop esi
pop ecx
ret
.copy:
shl eax, BSF sizeof.APPDATA
mov edi, [SLOT_BASE + eax + APPDATA.fpu_state]
mov edi, [eax + APPDATA.fpu_state]
mov ecx, [xsave_area_size]
add ecx, 3
shr ecx, 2
cld
rep movsd
popfd
pop edi
pop esi
pop ecx
ret
@@ -370,21 +386,19 @@ except_7: ;#NM exception handler
mov es, ax
mov ebx, [fpu_owner]
cmp ebx, [current_slot_idx]
cmp ebx, [current_slot]
je .exit
shl ebx, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + ebx + APPDATA.fpu_state]
mov eax, [ebx + APPDATA.fpu_state]
bt [cpu_caps + (CAPS_OSXSAVE/32)*4], CAPS_OSXSAVE mod 32
jnc .no_xsave
mov ecx, eax
mov eax, [xsave_eax]
mov edx, [xsave_edx]
xsave [ecx]
mov ebx, [current_slot_idx]
mov ebx, [current_slot]
mov [fpu_owner], ebx
shl ebx, BSF sizeof.APPDATA
mov ecx, [SLOT_BASE + ebx + APPDATA.fpu_state]
mov ecx, [ebx + APPDATA.fpu_state]
xrstor [ecx]
.exit:
restore_ring3_context
@@ -394,24 +408,22 @@ except_7: ;#NM exception handler
jnc .no_SSE
fxsave [eax]
mov ebx, [current_slot_idx]
mov ebx, [current_slot]
mov [fpu_owner], ebx
shl ebx, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + ebx + APPDATA.fpu_state]
mov eax, [ebx + APPDATA.fpu_state]
fxrstor [eax]
restore_ring3_context
iret
.no_SSE:
fnsave [eax]
mov ebx, [current_slot_idx]
mov ebx, [current_slot]
mov [fpu_owner], ebx
shl ebx, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + ebx + APPDATA.fpu_state]
mov eax, [ebx + APPDATA.fpu_state]
frstor [eax]
restore_ring3_context
iret
iglobal
fpu_owner dd 2
fpu_owner dd APPDATA_OS_THREAD
endg
+20 -26
View File
@@ -605,7 +605,7 @@ proc page_fault_handler
mov edi, [.err_addr]
and edi, -PAGE_SIZE
mov ecx, 1024
mov ecx, PAGE_SIZE/4
xor eax, eax
;cld ;caller is duty for this
rep stosd
@@ -664,7 +664,7 @@ proc page_fault_handler
cmp ebx, tss._io_map_0
jb .fail
cmp ebx, tss._io_map_0+8192
cmp ebx, tss._io_map_0 + IO_MAP_SIZE
jae .fail
; io permission map
@@ -695,7 +695,7 @@ proc page_fault_handler
endp
; returns number of mapped bytes
proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
proc map_mem_ipc stdcall, lin_addr:dword,thread:dword,\
ofs:dword,buf_size:dword,req_access:dword
locals
count dd ?
@@ -706,9 +706,8 @@ proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
cmp [buf_size], 0
jz .exit
mov eax, [slot]
shl eax, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + eax + APPDATA.process]
mov eax, [thread]
mov eax, [eax + APPDATA.process]
test eax, eax
jz .exit
@@ -732,7 +731,7 @@ proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
shr edx, 12
and edx, 0x3FF
.map:
stdcall safe_map_page, [slot], [req_access], [ofs]
stdcall safe_map_page, [process], [req_access], [ofs]
jnc .exit
add [count], PAGE_SIZE
add [ofs], PAGE_SIZE
@@ -758,7 +757,7 @@ proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
ret
endp
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
proc map_memEx stdcall, lin_addr:dword,thread:dword,\
ofs:dword,buf_size:dword,req_access:dword
locals
count dd ?
@@ -769,9 +768,8 @@ proc map_memEx stdcall, lin_addr:dword,slot:dword,\
cmp [buf_size], 0
jz .exit
mov eax, [slot]
shl eax, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + eax + APPDATA.process]
mov eax, [thread]
mov eax, [eax + APPDATA.process]
test eax, eax
jz .exit
@@ -795,7 +793,7 @@ proc map_memEx stdcall, lin_addr:dword,slot:dword,\
shr edx, 12
and edx, 0x3FF
.map:
stdcall safe_map_page, [slot], [req_access], [ofs]
stdcall safe_map_page, [process], [req_access], [ofs]
jnc .exit
add [count], PAGE_SIZE
add [ofs], PAGE_SIZE
@@ -826,7 +824,7 @@ endp
; in: edi = linear address to map
; out: CF cleared <=> failed
; destroys: only eax
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
proc safe_map_page stdcall, process:dword, req_access:dword, ofs:dword
mov eax, [esi + edx*4]
test al, PG_READ
jz .not_present
@@ -861,9 +859,7 @@ proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
cli
cld
push ebx ecx
mov eax, [slot]
shl eax, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + eax + APPDATA.process]
mov eax, [process]
mov eax, [eax + PROC.dlls_list_ptr]
test eax, eax
jz .no_hdll
@@ -953,7 +949,7 @@ sys_IPC:
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
locals
dst_slot dd ?
dst_thread dd ?
dst_offset dd ?
buf_size dd ?
used_buf dd ?
@@ -963,13 +959,12 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
cli
mov eax, [PID]
call pid_to_slot
call pid_to_thread
test eax, eax
jz .no_pid
mov [dst_slot], eax
shl eax, BSF sizeof.APPDATA
mov edi, [SLOT_BASE + eax + APPDATA.ipc_start] ;is ipc area defined?
mov [dst_thread], eax
mov edi, [eax + APPDATA.ipc_start] ;is ipc area defined?
test edi, edi
jz .no_ipc_area
@@ -977,7 +972,7 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
and ebx, 0xFFF
mov [dst_offset], ebx
mov esi, [SLOT_BASE + eax + APPDATA.ipc_size]
mov esi, [eax + APPDATA.ipc_size]
mov [buf_size], esi
mov ecx, [ipc_tmp]
@@ -990,7 +985,7 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
pop edi esi
@@:
mov [used_buf], ecx
stdcall map_mem_ipc, ecx, [dst_slot], \
stdcall map_mem_ipc, ecx, [dst_thread], \
edi, esi, PG_SWR
mov edi, [dst_offset]
@@ -1039,9 +1034,8 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
mov [page_tabs + ebx*4], eax
invlpg [edx]
mov eax, [dst_slot]
shl eax, BSF sizeof.APPDATA
or [SLOT_BASE + eax + APPDATA.occurred_events], EVENT_IPC
mov eax, [dst_thread]
or [eax + APPDATA.occurred_events], EVENT_IPC
push 0
jmp .ret
.no_pid:
+2 -3
View File
@@ -139,14 +139,13 @@ do_change_task:
mov eax, [xsave_eax]
mov edx, [xsave_edx]
xsave [ecx]
mov ecx, [current_slot_idx]
mov [fpu_owner], ecx
mov ecx, [current_slot]
mov [fpu_owner], ecx
mov ecx, [ecx + APPDATA.fpu_state]
xrstor [ecx]
.no_xsave:
; set CR0.TS
cmp bh, byte[fpu_owner] ;bh == incoming task (new)
cmp ebx, [fpu_owner] ;ebx == incoming task (new)
clts ;clear a task switch flag
je @f
mov eax, cr0 ;and set it again if the owner
+19 -16
View File
@@ -165,7 +165,7 @@ exc_c: ; exceptions (all but 7th - #NM)
jnz IRetToUserHook
@@:
cli
mov eax, [esi + APPDATA.debugger_slot]
mov eax, [esi + APPDATA.debugger_thread]
test eax, eax
jnz .debug
; not debuggee => say error and terminate
@@ -514,28 +514,30 @@ destroy_thread:
@@:
mov eax, [esi + APPOBJ.fd]
test eax, eax
jz @F
jz @f
cmp eax, esi
je @F
je @f
push esi
call [eax + APPOBJ.destroy]
DEBUGF 1,"%s",msg_obj_destroy
pop esi
jmp @B
jmp @b
@@:
mov esi, [.slot]
shl esi, BSF sizeof.APPDATA
add esi, SLOT_BASE
cmp [fpu_owner], esi ; if user fpu last -> fpu user = 2
jne @F
jne @f
mov [fpu_owner], 2
mov eax, [SLOT_BASE + sizeof.APPDATA*2 + APPDATA.fpu_state]
mov [fpu_owner], APPDATA_OS_THREAD
mov eax, [APPDATA_OS_THREAD + APPDATA.fpu_state]
clts
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
fxrstor [eax]
jmp @F
jmp @f
.no_SSE:
fnclex
frstor [eax]
@@ -544,8 +546,8 @@ destroy_thread:
mov [KEY_COUNT], byte 0 ; empty keyboard buffer
mov [BTN_COUNT], byte 0 ; empty button buffer
; remove defined hotkeys
mov esi, [.slot]
mov eax, hotkey_list
.loop:
cmp [eax+8], esi
@@ -638,7 +640,7 @@ destroy_thread:
pushad
mov edi, esi
shl edi, BSF sizeof.APPDATA
mov eax, [SLOT_BASE + edi + APPDATA.debugger_slot]
mov eax, [SLOT_BASE + edi + APPDATA.debugger_thread]
test eax, eax
jz .nodebug
movi ecx, 8
@@ -666,12 +668,12 @@ destroy_thread:
add edi, SLOT_BASE
mov eax, [edi + APPDATA.io_map]
cmp eax, [SLOT_BASE + sizeof.APPDATA+APPDATA.io_map]
cmp eax, [APPDATA_IDLE_THREAD + APPDATA.io_map]
je @F
call free_page
@@:
mov eax, [edi+APPDATA.io_map+4]
cmp eax, [SLOT_BASE+sizeof.APPDATA+APPDATA.io_map+4]
cmp eax, [APPDATA_IDLE_THREAD + APPDATA.io_map+4]
je @F
call free_page
@@:
@@ -712,12 +714,12 @@ destroy_thread:
call free_cd_channel
and [cd_status], 0
@@:
pop esi
cmp [bgrlockpid], esi
jnz @f
and [bgrlockpid], 0
and [bgrlock], 0
@@:
pop esi
pusha ; remove all port reservations
mov edx, esi
@@ -778,14 +780,15 @@ destroy_thread:
mov edi, esi ; do not run this process slot
shl edi, BSF sizeof.APPDATA
mov [SLOT_BASE + edi + APPDATA.state], TSTATE_FREE
add edi, SLOT_BASE
mov [edi + APPDATA.state], TSTATE_FREE
; debugger test - terminate all debuggees
mov eax, 2
mov ecx, SLOT_BASE + 2*sizeof.APPDATA + APPDATA.debugger_slot
mov ecx, APPDATA_OS_THREAD + APPDATA.debugger_thread
.xd0:
cmp eax, [thread_count]
ja .xd1
cmp dword [ecx], esi
cmp dword [ecx], edi
jnz @f
and dword [ecx], 0
pushad
+19 -22
View File
@@ -537,21 +537,21 @@ pid_to_slot:
align 4
proc read_process_memory
;Input:
; eax - process slot
; eax - process thread
; ecx - buffer address
; edx - buffer size
; esi - start address in other process
;Output:
; eax - number of bytes read.
locals
slot dd ?
thread dd ?
buff dd ?
r_count dd ?
offset dd ?
tmp_r_cnt dd ?
endl
mov [slot], eax
mov [thread], eax
mov [buff], ecx
and [r_count], 0
mov [tmp_r_cnt], edx
@@ -577,7 +577,7 @@ proc read_process_memory
push ecx
stdcall map_memEx, [proc_mem_map], \
[slot], ebx, ecx, PG_READ
[thread], ebx, ecx, PG_READ
pop ecx
mov esi, [offset]
@@ -607,7 +607,7 @@ endp
align 4
proc write_process_memory
;Input:
; eax - process slot
; eax - process thread
; ecx - buffer address
; edx - buffer size
; esi - start address in other process
@@ -615,14 +615,14 @@ proc write_process_memory
; eax - number of bytes written
locals
slot dd ?
thread dd ?
buff dd ?
w_count dd ?
offset dd ?
tmp_w_cnt dd ?
endl
mov [slot], eax
mov [thread], eax
mov [buff], ecx
and [w_count], 0
mov [tmp_w_cnt], edx
@@ -647,7 +647,7 @@ proc write_process_memory
mov ebx, [offset]
push ecx
stdcall map_memEx, [proc_mem_map], \
[slot], ebx, ecx, PG_SWR
[thread], ebx, ecx, PG_SWR
pop ecx
mov edi, [offset]
@@ -906,7 +906,7 @@ common_app_entry:
stdcall free_kernel_space, [ebp+APP_HDR.img_base]
stdcall kernel_free, ebp
mov ebx, [current_slot]
cmp [ebx + APPDATA.debugger_slot], 0
cmp [ebx + APPDATA.debugger_thread], 0
je .exit
mov [ebx + APPDATA.state], TSTATE_RUN_SUSPENDED
mov [ebx + APPDATA.state], TSTATE_RUN_SUSPENDED
@@ -1054,8 +1054,8 @@ proc set_app_params stdcall,slot:dword, params:dword, flags:dword
; set if debuggee
test byte [flags], 1
jz .no_debug
mov eax, [current_slot_idx]
mov [SLOT_BASE + ebx + APPDATA.debugger_slot], eax
mov eax, [current_slot]
mov [SLOT_BASE + ebx + APPDATA.debugger_thread], eax
.no_debug:
mov [SLOT_BASE + ebx + APPDATA.state], dl
lea edx, [SLOT_BASE + ebx]
@@ -1074,27 +1074,24 @@ get_curr_slot:
mov eax, [current_slot]
ret
pid_to_appdata:
;Input:
; eax - pid of process
;Output:
; eax - 0 - not found or pointer on APPDATA
; @brief Get pointer to APPDATA by PID
; @param eax - TID of thread
; @return eax - 0 - not found or pointer on APPDATA
pid_to_thread:
push ebx
push ecx
mov ebx, [thread_count]
shl ebx, BSF sizeof.APPDATA ; multiply by size
; skip first process in the task table
mov ecx, SLOT_BASE
add ebx, ecx
mov ecx, APPDATA_IDLE_THREAD
.loop:
add ecx, sizeof.APPDATA
cmp [ecx + APPDATA.state], TSTATE_FREE
jz @f ;skip empty slots
cmp [ecx + APPDATA.tid], eax
jz .pid_found
@@:
cmp ecx, ebx
jb .loop
add ecx, sizeof.APPDATA
dec ebx
jnz .loop
pop ecx
pop ebx
+1 -1
View File
@@ -48,7 +48,7 @@ endg
; This internal function acquires the lock for the global list.
lock_timer_list:
mov edx, [current_slot_idx]
mov edx, [current_slot]
@@:
xor eax, eax
lock cmpxchg [timer_list_owner], edx
+1
View File
@@ -4148,6 +4148,7 @@ Structure of block of data for folder entry (BDFE):
and after archiving this bit is cleared - it can be useful
for automatically creating of backup-archives as at writing
this bit is usually set
* bit 6 (mask 0x40): this is a symbolic link (currently only set by the ext driver).
* +4: dword: encoding, equals to field +8 in the information structure
* +8: 4*byte: time of file creation
* +12 = +0xC: 4*byte: date of file creation
+749 -49
View File
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -2405,11 +2405,12 @@ fat_Write:
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
; First two cases are fatal errors, in third case we may write some data
cmp al, ERROR_DISK_FULL
jnz @f
jnz .noWrite
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
.noWrite:
push 0
.ret:
pop eax eax eax ecx ecx
+4 -2
View File
@@ -193,7 +193,8 @@ align 4
;--------------------------------------
align 4
@@:
mov eax, [current_slot_idx]
mov eax, [current_slot]
mov eax, [eax + APPDATA.tid]
mov [bgrlockpid], eax
cmp [img_background], static_background_data
jz .nomem
@@ -241,7 +242,8 @@ nosb6:
jnz nosb7
cmp [bgrlock], 0
jz .err
mov eax, [current_slot_idx]
mov eax, [current_slot]
mov eax, [eax + APPDATA.tid]
cmp [bgrlockpid], eax
jnz .err
mov eax, ecx
+2
View File
@@ -1997,6 +1997,8 @@ align 4
; esi - slot
push eax ecx edx esi
xchg eax, esi
shl eax, BSF sizeof.APPDATA
add eax, SLOT_BASE
lea ecx, [esp + 12]
mov edx, 1
call read_process_memory
+17 -18
View File
@@ -55,7 +55,6 @@ launcher_start db 1
endg
max_processes = 255
tss_step = 128 + 8192 ; tss & i/o - 65535 ports, * 256=557056*4
os_stack = os_data_l - gdts ; GDTs
os_code = os_code_l - gdts
@@ -389,7 +388,7 @@ high_code:
mov edi, tss._io_map_0
xor eax, eax
not eax
mov ecx, 8192/4
mov ecx, IO_MAP_SIZE/4
rep stosd ; access to 4096*8=65536 ports
mov ax, tss0
@@ -410,7 +409,7 @@ high_code:
stdcall alloc_kernel_space, 0x50000 ; FIXME check size
mov [default_io_map], eax
add eax, 0x2000
add eax, IO_MAP_SIZE
mov [ipc_tmp], eax
mov ebx, 0x1000
@@ -535,7 +534,7 @@ high_code:
dec ecx
jns @b
mov edx, SLOT_BASE + sizeof.APPDATA*1
mov edx, APPDATA_IDLE_THREAD
mov ebx, [os_stack_seg]
add ebx, RING0_STACK_SIZE
add ebx, [xsave_area_size]
@@ -547,7 +546,7 @@ high_code:
mov ecx, IDLE_PRIORITY
call scheduler_add_thread
mov edx, SLOT_BASE + sizeof.APPDATA*2
mov edx, APPDATA_OS_THREAD
mov ebx, [os_stack_seg]
call setup_os_slot
mov dword [edx], 'OS'
@@ -556,7 +555,7 @@ high_code:
mov [current_slot_idx], 2
mov [thread_count], 2
mov [current_slot], SLOT_BASE + sizeof.APPDATA*2
mov [current_slot], APPDATA_OS_THREAD
; Move other CPUs to deep sleep, if it is useful
uglobal
@@ -848,15 +847,15 @@ include "detect/vortex86.inc" ; Vortex86 SoC detection code
call reserve_irqs_ports
mov [SLOT_BASE + APPDATA.window], window_data
mov [SLOT_BASE + sizeof.APPDATA + APPDATA.window], window_data + sizeof.WDATA
mov [SLOT_BASE + sizeof.APPDATA*2 + APPDATA.window], window_data + sizeof.WDATA*2
mov [APPDATA_IDLE_THREAD + APPDATA.window], background_window
mov [APPDATA_OS_THREAD + APPDATA.window], window_data + sizeof.WDATA*2
mov [window_data + WDATA.thread], SLOT_BASE
mov [window_data + sizeof.WDATA + WDATA.thread], SLOT_BASE + sizeof.APPDATA
mov [window_data + sizeof.WDATA*2 + WDATA.thread], SLOT_BASE + sizeof.APPDATA*2
mov [background_window + WDATA.thread], APPDATA_IDLE_THREAD
mov [window_data + sizeof.WDATA*2 + WDATA.thread], APPDATA_OS_THREAD
call init_display
mov eax, [def_cursor]
mov [window_data + sizeof.WDATA + WDATA.cursor], eax
mov [background_window + WDATA.cursor], eax
mov [window_data + sizeof.WDATA*2 + WDATA.cursor], eax
; PRINT CPU FREQUENCY
@@ -953,14 +952,14 @@ include "detect/vortex86.inc" ; Vortex86 SoC detection code
; Protect I/O permission map
mov esi, [default_io_map]
stdcall map_page, esi, [SLOT_BASE + sizeof.APPDATA + APPDATA.io_map], PG_READ
stdcall map_page, esi, [APPDATA_IDLE_THREAD + APPDATA.io_map], PG_READ
add esi, 0x1000
stdcall map_page, esi, [SLOT_BASE + sizeof.APPDATA + APPDATA.io_map + 4], PG_READ
stdcall map_page, esi, [APPDATA_IDLE_THREAD + APPDATA.io_map + 4], PG_READ
stdcall map_page, tss._io_map_0, \
[SLOT_BASE + sizeof.APPDATA + APPDATA.io_map], PG_READ
[APPDATA_IDLE_THREAD + APPDATA.io_map], PG_READ
stdcall map_page, tss._io_map_1, \
[SLOT_BASE + sizeof.APPDATA + APPDATA.io_map + 4], PG_READ
[APPDATA_IDLE_THREAD + APPDATA.io_map + 4], PG_READ
; SET KEYBOARD PARAMETERS
mov al, 0xf6 ; reset keyboard, scan enabled
@@ -1865,7 +1864,7 @@ sysfn_shutdown: ; 18.9 = system shutdown
; out: Z/z -- is/not kernel thread
is_kernel_thread:
mov eax, [eax + APPDATA.process]
cmp eax, [SLOT_BASE + 2*sizeof.APPDATA + APPDATA.process] ; OS
cmp eax, [APPDATA_OS_THREAD + APPDATA.process] ; OS
ret
;------------------------------------------------------------------------------
sysfn_terminate: ; 18.2 = TERMINATE
@@ -2065,7 +2064,7 @@ sysfn_zmodif:
;------------------------------------------------------------------------------
sysfn_getidletime: ; 18.4 = GET IDLETIME
mov eax, [SLOT_BASE + sizeof.APPDATA + APPDATA.cpu_usage]
mov eax, [APPDATA_IDLE_THREAD + APPDATA.cpu_usage]
mov [esp + SYSCALL_STACK.eax], eax
ret
;------------------------------------------------------------------------------
@@ -2825,7 +2824,7 @@ no_mark_system_shutdown:
align 4
noshutdown:
mov eax, [thread_count] ; termination
mov ebx, SLOT_BASE + sizeof.APPDATA + APPDATA.state
mov ebx, APPDATA_IDLE_THREAD + APPDATA.state
mov esi, 1
;--------------------------------------
align 4
+28
View File
@@ -83,6 +83,31 @@ macro arp_init {
}
;-----------------------------------------------------------------;
; ;
; arp_clear_device: Empty the ARP table and counters of a removed ;
; device. ;
; ;
; IN: edi = device number * 4 ;
; ;
;-----------------------------------------------------------------;
macro arp_clear_device {
xor eax, eax
mov [ARP_entries + edi], eax
mov [ARP_packets_tx + edi], eax
mov [ARP_packets_rx + edi], eax
mov [ARP_conflicts + edi], eax
push edi
imul edi, (ARP_TABLE_SIZE * sizeof.ARP_entry)/4
add edi, ARP_table
mov ecx, (ARP_TABLE_SIZE * sizeof.ARP_entry)/2
rep stosw
pop edi
}
;-----------------------------------------------------------------;
; ;
; arp_decrease_entry_ttls ;
@@ -313,6 +338,9 @@ arp_output_request:
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: ip=%u.%u.%u.%u device=0x%x\n",\
[esp]:1, [esp + 1]:1, [esp + 2]:1, [esp + 3]:1, ebx
test ebx, ebx ; device is gone
jz .exit
mov ax, ETHER_PROTO_ARP
mov ecx, sizeof.ARP_header
mov edx, ETH_BROADCAST ; broadcast mac
+40 -1
View File
@@ -105,6 +105,29 @@ macro ipv4_init {
}
;-----------------------------------------------------------------;
; ;
; ipv4_clear_device: Reset the IPv4 settings of a removed device, ;
; so no route points to it anymore. ;
; ;
; IN: edi = device number * 4 ;
; ;
;-----------------------------------------------------------------;
macro ipv4_clear_device {
xor eax, eax
mov [IPv4_address + edi], eax
mov [IPv4_subnet + edi], eax
mov [IPv4_nameserver + edi], eax
mov [IPv4_gateway + edi], eax
mov [IPv4_broadcast + edi], eax
mov [IPv4_packets_tx + edi], eax
mov [IPv4_packets_rx + edi], eax
mov [IPv4_packets_dumped + edi], eax
}
;-----------------------------------------------------------------;
; ;
; Decrease TimeToLive of all fragment slots ;
@@ -757,6 +780,8 @@ ipv4_output_raw:
push esi eax
call ipv4_route
test eax, eax
jz .arp_error
call arp_ip_to_mac
test eax, 0xffff0000 ; error bits
@@ -967,6 +992,8 @@ ipv4_route:
; Check for on-link
xor edi, edi
.loop:
cmp [net_device_list + edi], 0 ; skip slots without a device
je .next
mov ebx, [IPv4_address + edi]
and ebx, [IPv4_subnet + edi]
jz .next
@@ -983,7 +1010,10 @@ ipv4_route:
mov edi, 4 ; skip loopback device
.loop_gw:
cmp [IPv4_gateway + edi], 0
je .next_gw
cmp [net_device_list + edi], 0
jne .found_gw
.next_gw:
add edi, 4
cmp edi, 4*NET_DEVICES_MAX
jb .loop_gw
@@ -1049,14 +1079,23 @@ ipv4_route:
cmp eax, 0xffffffff
je @f
; An interface without an address (DHCP not done yet, or the lease
; dropped when the link went down) can send nothing but broadcasts: with
; address and mask both zero every destination compared as on-link, and
; the stack went asking ARP for internet addresses on behalf of 0.0.0.0.
test edx, edx
jz .fail
; Check if we should route to gateway or not
mov ebx, [IPv4_address + edi]
mov ebx, edx
and ebx, [IPv4_subnet + edi]
mov ecx, eax
and ecx, [IPv4_subnet + edi]
cmp ecx, ebx
je @f
mov eax, [IPv4_gateway + edi]
test eax, eax
jz .fail ; off-link and no gateway
@@:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
ret
+44 -1
View File
@@ -61,6 +61,41 @@ macro eth_init {
}
;-----------------------------------------------------------------;
; ;
; eth_clear_device: Drop the frames of a removed device that are ;
; still waiting in the input queue, their ;
; NET_BUFF.device will not be valid anymore. ;
; ;
; IN: ebx = device ptr ;
; ;
;-----------------------------------------------------------------;
macro eth_clear_device {
local .loop, .done
spin_lock_irqsave
mov esi, [ETH_frame_head]
.loop:
cmp esi, ETH_frame_head
je .done
mov eax, esi
mov esi, [esi + NET_BUFF.NextPtr]
cmp [eax + NET_BUFF.device], ebx
jne .loop
; unlink it, ETH_frame_head/tail double as the NextPtr/PrevPtr of the list head
mov ecx, [eax + NET_BUFF.PrevPtr]
mov [ecx + NET_BUFF.NextPtr], esi
mov [esi + NET_BUFF.PrevPtr], ecx
dec [ETH_frame_queued]
stdcall net_buff_free, eax
jmp .loop
.done:
spin_unlock_irqrestore
}
align 4
; This function is called by ethernet drivers.
; Push the received ethernet packet onto the ethernet input queue.
@@ -245,6 +280,9 @@ eth_output:
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx
test ebx, ebx
jz .no_device
cmp ecx, [ebx + ETH_DEVICE.mtu]
ja .too_large
@@ -295,11 +333,16 @@ eth_output:
ret
.too_large:
inc [eax + NET_DEVICE.packets_tx_err]
inc [ebx + NET_DEVICE.packets_tx_err]
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: Packet too large!\n"
xor eax, eax
ret
.no_device:
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: no device!\n"
xor eax, eax
ret
;-----------------------------------------------------------------;
+11 -1
View File
@@ -118,7 +118,7 @@ SS_MORETOCOME = 0x4000
SS_BLOCKED = 0x8000
SOCKET_BUFFER_SIZE = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
SOCKET_BUFFER_SIZE = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
MAX_backlog = 20 ; maximum backlog for stream sockets
; Error Codes
@@ -597,6 +597,16 @@ net_remove_device:
mov dword [edi-4], eax
dec [net_device_count]
;-----------------------------------------------------------------
; Forget everything the protocols still know about this interface.
; Otherwise its IP address keeps matching in ipv4_route, and output
; ends up calling through the now empty net_device_list slot.
sub edi, net_device_list + 4 ; device number * 4
ipv4_clear_device
arp_clear_device
eth_clear_device
call net_send_event
xor eax, eax
+6 -2
View File
@@ -1422,10 +1422,14 @@ endl
test [edx + TCP_header.Flags], TH_ACK
jz .drop
mov eax, ebx
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
mov ebx, ECONNREFUSED
call tcp_drop
jmp .drop
jmp .drop_no_socket
@@:
;-----------------------------------------------------------------------------------
+8 -6
View File
@@ -234,23 +234,25 @@ endl
mov ebx, TCP_max_win
shl ebx, cl
pop ecx
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
add ebx, [eax + TCP_SOCKET.RCV_NXT]
; Clamp to available window first, then subtract what the peer already knows (as in BSD)
cmp ebx, ecx
jl @f
jbe @f
mov ebx, ecx
@@:
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
add ebx, [eax + TCP_SOCKET.RCV_NXT]
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: we can increase window by %d bytes\n", ebx
mov edi, [eax + TCP_SOCKET.t_maxseg]
shl edi, 1
cmp ebx, edi
jae .send
cmp ebx, edi ; signed: may be negative if window shrank
jge .send
cmp ebx, SOCKET_BUFFER_SIZE/2
jae .send
jge .send
.no_window:
+4
View File
@@ -180,6 +180,8 @@ tcp_connect:
.nomem:
pop edx eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
xor eax, eax
dec eax
mov ebx, ENOMEM
@@ -194,6 +196,8 @@ tcp_connect:
.enoroute:
pop eax
popa
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
xor eax, eax
dec eax
mov ebx, EADDRNOTAVAIL
+2 -1
View File
@@ -148,9 +148,10 @@ ReadNoteByte:
push esi
mov eax, [pidProcessNote]
call pid_to_slot
call pid_to_thread
test eax, eax
jz .failed
lea ecx, [esp+12]
mov edx, 1
mov esi, [memAdrNote]
-4
View File
@@ -238,7 +238,6 @@ BEGIN
m.active := FALSE;
resetTimer;
m.tid := 0;
G.destroy(m.canvas);
K.Exit
END exit;
@@ -250,7 +249,6 @@ BEGIN
resetTimer
END;
m.tid := 0;
G.destroy(m.canvas);
K.Exit
END escape;
@@ -356,7 +354,6 @@ BEGIN
END;
temp := m.tid;
m.tid := 0;
G.destroy(m.canvas);
K.ExitID(temp);
m.active := FALSE
END
@@ -512,7 +509,6 @@ BEGIN
IF m.parent # NIL THEN
temp := m.parent.tid;
m.parent.tid := 0;
G.destroy(m.parent.canvas);
K.ExitID(temp)
END;
exit(m)
+1
View File
@@ -181,6 +181,7 @@ con_cls
con_get_cursor_pos
con_set_cursor_pos
;____TIME____
clock
mktime
time
localtime
@@ -1,6 +1,6 @@
#include <shell_api.h>
char shell_getc()
int shell_getc()
{
__shell_init();
@@ -9,7 +9,7 @@ char shell_getc()
__shell_shm->cmd = SHELL_GETC;
__SHELL_WAIT();
return __shell_shm->data[0];
return *((int*)__shell_shm->data);
}
else
{
@@ -1,15 +1,28 @@
#include <shell_api.h>
#include <stdio.h>
#include <string.h>
void shell_gets(char *str, int n)
char *shell_gets(char *str, int n)
{
__shell_init();
char *ptr = NULL;
if (__shell_is_init == __SHELL_INIT_OK)
{
__shell_shm->cmd = SHELL_GETS;
__SHELL_WAIT();
strncpy(str, __shell_shm->data, n);
if (__shell_shm->return_value.str == EOF || !__shell_shm->return_value.str)
{
ptr = __shell_shm->return_value.str;
}
else
{
ptr = str;
}
}
return ptr;
}
@@ -1,12 +1,13 @@
#include <shell_api.h>
#include <stdio.h>
void shell_printf(const char *format, ...)
int shell_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsnprintf(__shell_shm->data, sizeof(__shell_shm->data), format, ap);
int val = vsnprintf(__shell_shm->data, sizeof(__shell_shm->data), format, ap);
__shell_shm->cmd = SHELL_PUTS;
va_end(ap);
__SHELL_WAIT();
return val;
}
@@ -1,7 +1,7 @@
#include <shell_api.h>
#include <string.h>
void shell_puts(const char *str)
size_t shell_puts(const char *str)
{
shell_write_string(str, strlen(str));
return shell_write_string(str, strlen(str));
}
@@ -1,22 +1,27 @@
#include <shell_api.h>
#include <string.h>
void shell_write_string(const char *s, size_t len)
size_t shell_write_string(const char *s, size_t len)
{
__shell_init();
if (__shell_is_init == __SHELL_INIT_OK)
{
size_t written_bytes = 0;
if (len > sizeof(__shell_shm->data) - 1)
{
shell_write_string(s, sizeof(__shell_shm->data) - 1); // Outputs as much as it can.
shell_write_string(s + (sizeof(__shell_shm->data) - 1), len - (sizeof(__shell_shm->data) - 1)); // Outputs the rest.
written_bytes += shell_write_string(s, sizeof(__shell_shm->data) - 1); // Outputs as much as it can.
written_bytes += shell_write_string(s + (sizeof(__shell_shm->data) - 1), len - (sizeof(__shell_shm->data) - 1)); // Outputs the rest.
}
else
{
memset(__shell_shm->data, 0, sizeof(__shell_shm->data)); // without int shell show \t, \n, lose chars and other trash
memcpy(__shell_shm->data, s, len);
memset(__shell_shm->data, 0, sizeof(__shell_shm->data)); // without int shell show \t, \n, lose chars and other trash
memcpy(__shell_shm->data, s, len);
__shell_shm->cmd = SHELL_PUTS;
__SHELL_WAIT();
written_bytes += __shell_shm->return_value.written_bytes;
}
return written_bytes;
}
return 0;
}
@@ -31,9 +31,15 @@ enum __SHELL_INIT_STATE {
};
#pragma pack(push, 1)
struct return_value {
size_t written_bytes;
char* str;
};
struct shell_shm_buffer {
uint8_t cmd;
char data[SHELL_SHM_MAX - sizeof(((struct shell_shm_buffer*)NULL)->cmd)];
char data[SHELL_SHM_MAX - sizeof(((struct shell_shm_buffer*)NULL)->cmd) - sizeof(struct return_value)];
struct return_value return_value;
};
#pragma pack(pop)
@@ -51,14 +57,14 @@ __EXTERN int shell_ping();
__EXTERN unsigned shell_get_pid();
__EXTERN void shell_exit();
__EXTERN char shell_getc();
__EXTERN void shell_gets(char* str, int n);
__EXTERN int shell_getc();
__EXTERN char* shell_gets(char* str, int n);
__EXTERN void shell_putc(char c);
__EXTERN void shell_puts(const char* str);
__EXTERN void shell_printf(const char* format, ...);
__EXTERN size_t shell_puts(const char* str);
__EXTERN int shell_printf(const char* format, ...);
__EXTERN void shell_write_string(const char* s, size_t len);
__EXTERN size_t shell_write_string(const char* s, size_t len);
__EXTERN void shell_cls();
+15 -5
View File
@@ -34,6 +34,8 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
DLLAPI int puts(const char* str);
DLLAPI int printf(const char* format, ...);
@@ -50,15 +52,23 @@ typedef size_t fpos_t;
#define _FILEMODE_R 1 << 0 // Read
#define _FILEMODE_W 1 << 1 // Write
#define _FILEMODE_A 1 << 2 // Append
#define _FILEMODE_PLUS 1 << 3 // Plus
#define _FILEFLAG_ERR 1 << 3 // Error
#define _FILEFLAG_EOF 1 << 4 // EOF
typedef struct FILE_s {
char* name;
fpos_t position;
int error;
int eof;
int mode; // flags _FILEMODE_*
int __ungetc_emu_buff; // Uses __ungetc_emu (temporary solution!)
union {
struct {
bool read : 1;
bool write : 1;
bool append : 1;
bool error : 1;
bool eof : 1;
};
uint32_t val; // exist just because tcc won't optimize bitfields
} flags;
} FILE;
#define _IOFBF 0
@@ -82,7 +92,7 @@ typedef struct FILE_s {
#define TMP_MAX FOPEN_MAX
#define stderr (FILE*)3
#define stdin (FILE*)1
#define stdin (FILE*)1
#define stdout (FILE*)2
DLLAPI int fgetc(FILE*);
@@ -1,11 +1,10 @@
#ifndef _TIME_H_
#define _TIME_H_
#include <sys/ksys.h>
#include <stddef.h>
typedef unsigned long int clock_t;
typedef unsigned long int time_t;
#define clock() _ksys_get_clock()
#define CLOCKS_PER_SEC 100
#pragma pack(push, 1)
@@ -22,6 +21,7 @@ struct tm {
};
#pragma pack(pop)
DLLAPI clock_t clock(void);
DLLAPI time_t mktime(struct tm* timeptr);
DLLAPI time_t time(time_t* timer);
DLLAPI struct tm* localtime(const time_t* timer);
@@ -61,6 +61,8 @@
/* strntold() is used by vsscanf() below; include its definition first */
#include "stdlib/strntold.c"
#include "stdio/vsscanf.c"
#include "stdio/fclose_r.c"
#include "stdio/fopen_r.c"
#include "string/memccpy.c"
#include "string/memchr.c"
@@ -119,6 +121,7 @@
#include "math/sinh.c"
#include "math/tanh.c"
#include "time/clock.c"
#include "time/asctime.c"
#include "time/difftime.c"
#include "time/localtime.c"
@@ -338,6 +341,7 @@ ksys_dll_t EXPORTS[] = {
{ "con_cls", &con_cls },
{ "con_get_cursor_pos", &con_get_cursor_pos },
{ "con_set_cursor_pos", &con_set_cursor_pos },
{ "clock", &clock },
{ "mktime", &mktime },
{ "time", &time },
{ "localtime", &localtime },
@@ -0,0 +1,9 @@
#ifndef __LIBC_STDIO_H
#define __LIBC_STDIO_H
#include <stdio.h>
int fclose_r(FILE* stream);
FILE* fopen_r(const char* restrict name, const char* restrict mode, FILE* restrict stream);
#endif // __LIBC_STDIO_H
@@ -1,6 +1,6 @@
#include <stdio.h>
void clearerr(FILE *stream) {
stream->error = 0;
stream->eof = 0;
void clearerr(FILE* stream)
{
stream->flags.val &= ~(_FILEFLAG_ERR | _FILEFLAG_EOF);
}
@@ -1,8 +1,15 @@
#include "stddef.h"
#include "_stdio.h"
#include <stdio.h>
#include <stdlib.h>
int fclose(FILE *stream) {
int fclose(FILE* stream)
{
int err = fclose_r(stream);
if (err) {
return err;
}
free(stream);
stream = NULL;
return 0;
@@ -0,0 +1,10 @@
#include "_stdio.h"
int fclose_r(FILE* stream)
{
if (stream->name) {
free(stream->name);
}
return 0;
}
@@ -1,5 +1,6 @@
#include <stdio.h>
int feof(FILE *stream) {
return stream->eof;
int feof(FILE* stream)
{
return stream->flags.eof;
}
@@ -1,5 +1,6 @@
#include <stdio.h>
int ferror(FILE *stream) {
return stream->error;
int ferror(FILE* stream)
{
return stream->flags.error;
}
@@ -1,7 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "_stdio.h"
FILE *fopen(const char *restrict _name, const char *restrict _mode) {
FILE *out = malloc(sizeof(FILE));
return freopen(_name, _mode, out);
FILE* fopen(const char* restrict _name, const char* restrict _mode)
{
FILE* stream = malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM;
return NULL;
}
FILE* out = fopen_r(_name, _mode, stream);
if (out == NULL) {
free(stream);
}
return out;
}
@@ -0,0 +1,81 @@
#include "_stdio.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ksys.h>
#include <sys/dirent.h>
/*
Open new file
*/
FILE* fopen_r(const char* restrict _name, const char* restrict _mode, FILE* restrict out)
{
if (!_name || !_mode || !out) {
errno = EINVAL;
return NULL;
}
bool file_not_exits = false;
ksys_bdfe_t info;
{
int err = _ksys_file_get_info(_name, &info);
switch (err) {
case KSYS_FS_ERR_SUCCESS:
if (info.attributes & IS_FOLDER) {
errno = EISDIR;
return NULL;
}
break;
case KSYS_FS_ERR_5:
file_not_exits = true;
break;
default:
errno = err;
return NULL;
break;
}
}
out->flags.val = 0;
out->position = 0;
out->name = strdup(_name);
if (strchr(_mode, 'r')) {
out->flags.read = true;
if (file_not_exits) {
errno = ENOENT;
free(out->name);
return NULL;
}
}
if (strchr(_mode, 'w')) {
out->flags.write = true;
}
if (strchr(_mode, 'a')) {
out->flags.val |= _FILEMODE_W | _FILEMODE_A;
}
if (strchr(_mode, '+')) {
out->flags.val |= _FILEMODE_R | _FILEMODE_W;
}
if (out->flags.write) {
if (file_not_exits) {
int err = _ksys_file_create(_name);
if (err != KSYS_FS_ERR_SUCCESS) {
errno = err;
free(out->name);
return NULL;
}
}
}
if (out->flags.append) {
out->position = info.size;
}
return out;
}
@@ -14,7 +14,7 @@ size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict strea
if(size<=0 || nmemb<=0){
errno = EINVAL;
stream->error=errno;
stream->flags.error = true;
return 0;
}
@@ -23,7 +23,7 @@ size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict strea
return nmemb;
}
if(stream->mode != _FILEMODE_W && stream->mode != _FILEMODE_A){
if(stream->flags.read){
if(!stream->__ungetc_emu_buff){
((char*) ptr)[0]=(char)stream->__ungetc_emu_buff;
//debug_printf("Ungetc: %x\n", ((char*) ptr)[0]);
@@ -31,10 +31,10 @@ size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict strea
unsigned status = _ksys_file_read_file(stream->name, stream->position, bytes_count, ptr , &bytes_read);
if (status != KSYS_FS_ERR_SUCCESS) {
if(status == KSYS_FS_ERR_EOF){
stream->eof=1;
stream->flags.eof = true;
}else{
errno = EIO;
stream->error = errno;
stream->flags.error = true;
return 0;
}
}
@@ -1,62 +1,14 @@
#include <stddef.h>
#include <sys/ksys.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/dirent.h>
#include "_stdio.h"
FILE* freopen(const char* restrict _name, const char* restrict _mode, FILE* restrict out)
{
fclose_r(out);
static FILE* _set_errno(FILE *out, int err){
errno = err;
if(out){
free(out->name);
free(out);
if (_name == NULL) {
_name = out->name;
}
out = NULL;
return out;
return fopen_r(_name, _mode, out);
}
static void _create_file(char *name, FILE *out){
if(_ksys_file_create(name)){
_set_errno(out, EIO);
}
}
FILE *freopen(const char *restrict _name, const char *restrict _mode, FILE *restrict out) {
if(!_name || !_mode || !out){
return _set_errno(out, EINVAL);
}
ksys_bdfe_t info;
int no_file = _ksys_file_get_info(_name, &info);
if(!no_file && info.attributes & IS_FOLDER){
return _set_errno(out, EISDIR);
}
out->eof=0;
out->error=0;
out->position=0;
out->name = strdup(_name);
if (strchr(_mode, 'r')) { out->mode = _FILEMODE_R; }
if (strchr(_mode, 'w')) { out->mode = _FILEMODE_W; }
if (strchr(_mode, 'a')) { out->mode = _FILEMODE_A; }
if (strchr(_mode, '+')) { out->mode |= _FILEMODE_PLUS; }
if(out->mode & _FILEMODE_A){
if(no_file){
_create_file(out->name, out);
}
out->position = info.size;
}else if(out->mode & _FILEMODE_W){
_create_file(out->name, out);
}else if((out->mode & _FILEMODE_R)){
if(no_file){
_set_errno(out, ENOENT);
}
}else{
_set_errno(out, EINVAL);
}
return out;
}
@@ -1,18 +1,19 @@
#include <stdio.h>
#include <sys/ksys.h>
int fseek(FILE *stream, long int offset, int whence) {
if (whence == SEEK_SET) {
stream->position = offset;
} else if (whence == SEEK_CUR) {
stream->position += offset;
} else if (whence == SEEK_END) {
ksys_bdfe_t info;
if (_ksys_file_get_info(stream->name, &info)) {
return -1;
}
stream->position = info.size + offset;
}
stream->eof = 0;
int fseek(FILE* stream, long int offset, int whence)
{
if (whence == SEEK_SET) {
stream->position = offset;
} else if (whence == SEEK_CUR) {
stream->position += offset;
} else if (whence == SEEK_END) {
ksys_bdfe_t info;
if (_ksys_file_get_info(stream->name, &info)) {
return -1;
}
stream->position = info.size + offset;
}
stream->flags.eof = false;
return 0;
}
@@ -1,7 +1,8 @@
#include <stdio.h>
int fsetpos(FILE *stream, const fpos_t *pos) {
int fsetpos(FILE* stream, const fpos_t* pos)
{
stream->position = *pos;
stream->eof = 0;
stream->flags.eof = false;
return 0;
}
@@ -16,7 +16,7 @@ size_t fwrite(const void* restrict ptr, size_t size, size_t nmemb, FILE* restric
if (size <= 0 || nmemb <= 0) {
errno = EINVAL;
stream->error = errno;
stream->flags.error = true;
return 0;
}
@@ -33,11 +33,11 @@ size_t fwrite(const void* restrict ptr, size_t size, size_t nmemb, FILE* restric
return nmemb;
}
if (stream->mode != _FILEMODE_R) {
if (stream->flags.write) {
unsigned status = _ksys_file_write_file(stream->name, stream->position, bytes_count, ptr, &bytes_written);
if (status != KSYS_FS_ERR_SUCCESS) {
errno = EIO;
stream->error = errno;
stream->flags.error = true;
return 0;
}
stream->position += bytes_written;
@@ -6,22 +6,21 @@ int ungetc(int c, FILE* file)
{
int res;
if(!file){
errno = EBADF;
return EOF;
}
if (file->mode != _FILEMODE_R){
errno = EACCES;
return EOF;
}
if (file->position == 0 || c == EOF)
{
errno = EOF;
if (!file) {
errno = EBADF;
return EOF;
}
if (!file->flags.read) {
errno = EACCES;
return EOF;
}
if (file->position == 0 || c == EOF) {
errno = EOF;
return EOF;
}
file->__ungetc_emu_buff = c;
file->position--;
return c;
@@ -0,0 +1,7 @@
#include <time.h>
#include <sys/ksys.h>
clock_t clock(void)
{
return _ksys_get_tick_count();
}
@@ -0,0 +1,25 @@
Copyright (c) 2007-2012, Marc Kerbiquet
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of AsmXml nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,2 @@
if tup.getconfig("NO_FASM") ~= "" then return end
tup.rule("xml.asm", "fasm %f %o " .. tup.getconfig("KPACK_CMD"), "xml.obj")
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,59 @@
; SPDX-License-Identifier: GPL-2.0-only
;
; xml.obj - AsmXml parser as a KolibriOS library
; Copyright (C) KolibriOS team 2026
;
; asm-xml.asm and LICENSE.txt are the unmodified AsmXml 1.4 release
; by Marc Kerbiquet (BSD 3-clause), https://tibleiz.net/asm-xml/
format MS COFF
public EXPORTS
section '.flat' code readable align 16
; AsmXml calls malloc/free as cdecl, the heap functions given to lib_init
; are stdcall: the caller pops the argument they have already taken
lib_init:
mov [mem.alloc], eax
mov [mem.free], ebx
mov eax, malloc
mov ebx, free
jmp initialize
malloc:
push dword [esp + 4]
call [mem.alloc]
ret
free:
push dword [esp + 4]
call [mem.free]
ret
align 4
mem.alloc dd ?
mem.free dd ?
align 16
EXPORTS:
dd sz_lib_init, lib_init
dd sz_initializeParser, _initializeParser
dd sz_releaseParser, _releaseParser
dd sz_parse, _parse
dd sz_initializeClassParser, _initializeClassParser
dd sz_releaseClassParser, _releaseClassParser
dd sz_classFromElement, _classFromElement
dd sz_classFromString, _classFromString
dd 0, 0
sz_lib_init db 'lib_init', 0
sz_initializeParser db 'ax_initializeParser', 0
sz_releaseParser db 'ax_releaseParser', 0
sz_parse db 'ax_parse', 0
sz_initializeClassParser db 'ax_initializeClassParser', 0
sz_releaseClassParser db 'ax_releaseClassParser', 0
sz_classFromElement db 'ax_classFromElement', 0
sz_classFromString db 'ax_classFromString', 0
include 'asm-xml.asm'
+5 -3
View File
@@ -1618,21 +1618,23 @@ endl
; Open a new TCP socket
mcall socket, AF_INET4, SOCK_STREAM, 0
test eax, eax
jz .error3
cmp eax, -1
je .error3
mov [socketnum], eax
DEBUGF 1, "Socket: 0x%x\n", eax
; Connect to the server
mcall connect, [socketnum], [sockaddr], 18
test eax, eax
jnz .error3
jnz .error4
DEBUGF 1, "Socket is now connected.\n"
invoke freeaddrinfo ; Free allocated memory
mov eax, [socketnum]
ret
.error4:
mcall close, [socketnum]
.error3:
DEBUGF 2, "Could not connect to the remote server\n"
invoke freeaddrinfo ; Free allocated memory
@@ -501,7 +501,8 @@ img.decode.jpg:
jnz .no_create_palette
push ecx edi
mov edi, [eax + Image.Palette]
xor eax, eax
mov eax, 0xFF000000 ; opaque, like the palettes of the other decoders:
; converted to 32 bpp, alpha 0 made the picture invisible
mov ecx, 256
@@:
stosd
@@ -1178,17 +1178,18 @@ proc png_colorspace_set_gamma, png_ptr:dword, colorspace:dword, gAMA:dword
; In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
; handling code, which only required the value to be >0.
png_debug 1, 'in png_colorspace_set_gamma'
; charp errmsg;
; if (gAMA < 16 || gAMA > 625000000)
; errmsg = "gamma value out of range";
;# ifdef PNG_READ_gAMA_SUPPORTED
if PNG_READ_gAMA_SUPPORTED eq 1
; Allow the application to set the gamma value more than once
; else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
; (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
; errmsg = "duplicate";
;# endif
end if
; Do nothing if the colorspace is already invalid
; else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
@@ -161,8 +161,7 @@ proc png_set_gAMA_fixed uses eax edi esi, png_ptr:dword, info_ptr:dword, file_ga
or esi,esi
jz .end_f ;if (..== 0 || ..== 0) return
mov eax,esi
add eax,png_info_def.colorspace
lea eax,[esi+png_info_def.colorspace]
stdcall png_colorspace_set_gamma, edi, eax, [file_gamma]
stdcall png_colorspace_sync_info, edi, esi
.end_f:
@@ -593,8 +592,10 @@ endp
;void (png_structrp png_ptr, png_inforp info_ptr, png_colorp palette, int num_palette)
align 4
proc png_set_PLTE uses eax edi esi, png_ptr:dword, info_ptr:dword, palette:dword, num_palette:dword
; uint_32 max_palette_length;
proc png_set_PLTE uses eax ecx edi esi, png_ptr:dword, info_ptr:dword, palette:dword, num_palette:dword
locals
max_palette_length rd 1 ;uint_32
endl
png_debug1 1, 'in %s storage function', 'PLTE'
@@ -605,31 +606,53 @@ proc png_set_PLTE uses eax edi esi, png_ptr:dword, info_ptr:dword, palette:dword
or esi,esi
jz .end_f ;if (..==0 || ..==0) return
; max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
; (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
;max_palette_length = (..==..) ? .. : ..
cmp byte[esi+png_info_def.color_type],PNG_COLOR_TYPE_PALETTE
jne @f
xor eax,eax
inc eax
movzx ecx,byte[esi+png_info_def.bit_depth]
shl eax,cl
mov [max_palette_length],eax
jmp .end0
@@:
mov [max_palette_length],PNG_MAX_PALETTE_LENGTH
.end0:
; if (num_palette < 0 || num_palette > (int) max_palette_length)
; {
; if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
; png_error(png_ptr, "Invalid palette length");
;if (..<0 || ..>..)
cmp [num_palette],0
jl @f
mov eax,[max_palette_length]
cmp [num_palette],eax
jle .end1
@@:
cmp byte[edi+png_struct.color_type],PNG_COLOR_TYPE_PALETTE ;if (..==..)
jne @f
png_error edi, 'Invalid palette length'
jmp .end1
@@: ;else
png_warning edi, 'Invalid palette length'
jmp .end_f
.end1:
; else
; {
; png_warning(png_ptr, "Invalid palette length");
; return;
; }
; }
; if ((num_palette > 0 && palette == NULL) ||
; (num_palette == 0
cmp [num_palette],0
jle @f
cmp [palette],0
je .end2
@@:
cmp [num_palette],0
jne .end3
;if ((..>0 && ..==0) || (..==0
if PNG_MNG_FEATURES_SUPPORTED eq 1
; && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
; && (.. & PNG_FLAG_MNG_EMPTY_PLTE) == 0
mov eax,[edi+png_struct.mng_features_permitted]
and eax,PNG_FLAG_MNG_EMPTY_PLTE
jnz .end3
end if
; ))
; {
; png_error(png_ptr, "Invalid palette");
; }
;))
.end2:
png_error edi, 'Invalid palette'
.end3:
; It may not actually be necessary to set png_ptr->palette here;
; we do it for backward compatibility with the way the png_handle_tRNS
@@ -644,14 +667,26 @@ end if
; of num_palette entries, in case of an invalid PNG file or incorrect
; call to png_set_PLTE() with too-large sample values.
; png_ptr->palette = png_calloc(png_ptr,
; PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)));
stdcall png_calloc, edi, PNG_MAX_PALETTE_LENGTH*sizeof.png_color
mov [edi+png_struct.palette],eax
; if (num_palette > 0)
; memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
;if (..>0)
cmp [num_palette],0
jle @f
push esi edi
mov ecx,[num_palette]
imul ecx,sizeof.png_color
mov esi,[palette]
mov edi,eax
rep movsb ;memcpy(png_ptr->palette, palette, ...
pop edi esi
@@:
mov eax,[edi+png_struct.palette]
mov [esi+png_info_def.palette],eax
; info_ptr->num_palette = png_ptr->num_palette = (uint_16)num_palette;
mov eax,[num_palette]
mov [edi+png_struct.num_palette],ax
mov [esi+png_info_def.num_palette],ax
or dword[esi+png_info_def.free_me], PNG_FREE_PLTE
or dword[esi+png_info_def.valid], PNG_INFO_PLTE
@@ -1925,6 +1925,7 @@ locals
aindex dd 0 ;int ;= 0
y dd ? ;uint_32 ;= image->height
endl
png_debug 1, 'in png_write_image_16bit'
mov ebx,[argument]
mov [display],ebx
mov edx,[ebx+png_image_write_control.image]
@@ -2118,6 +2119,7 @@ locals
y dd ? ;uint_32 ;= image->height
component dd ? ;uint_32
endl
png_debug 1, 'in png_write_image_8bit'
mov ebx,[argument]
mov [display],ebx
mov edx,[ebx+png_image_write_control.image]
@@ -2257,9 +2259,11 @@ locals
afirst dd 0
bgr dd 0
num_trans dd 0
i dd ?
palette rb 256*sizeof.png_color
tRNS rb 256 ;byte[]
endl
png_debug 1, 'in png_image_set_PLTE'
pushad
mov edx,[display]
mov ebx,[edx+png_image_write_control.image]
@@ -2296,30 +2300,33 @@ if PNG_FORMAT_BGR_SUPPORTED eq 1
@@:
end if
; int i;
xor eax,eax
mov ecx,(256*sizeof.png_color)/4
mov edi,ebp
sub edi,256+256*sizeof.png_color
lea edi,[ebp-256-256*sizeof.png_color]
rep stosd ;memset(palette, 0, ...
not eax
mov ecx,256/4
;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment
;;sub edi,256
;lea edi,[ebp-256] ;if 'tRNS' after 'palette' this code can be comment
rep stosd ;memset(tRNS, 255, ...
; for (i=num_trans=0; i<entries; ++i)
; {
mov [i],0
lea edx,[ebp-256] ;edx=&tRNS
lea edi,[edx-256*sizeof.png_color]
align 4
.cycle0: ;for (i=num_trans=0; i<entries; ++i)
; This gets automatically converted to sRGB with reversal of the
; pre-multiplication if the color-map has an alpha channel.
; if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
; {
; png_const_uint_16p entry = cmap;
; entry += i * channels;
;if ((..&..) != 0)
mov eax,[format]
and eax,PNG_FORMAT_FLAG_LINEAR
or eax,eax
jz .end0
mov esi,[cmap] ;esi=entry uint_16p
mov eax,[channels]
mov ecx,eax
imul eax,[i]
add esi,eax ;+=i*channels;
; if ((channels & 1) != 0) /* no alpha */
; {
@@ -2369,46 +2376,86 @@ end if
; palette[i].blue = palette[i].red = palette[i].green =
; png_unpremultiply(entry[afirst], alpha, reciprocal);
; }
; }
jmp .end1
.end0: ;else Color-map has sRGB values
mov esi,[cmap] ;esi=entry
mov eax,[channels]
mov ecx,eax
imul eax,[i]
add esi,eax ;+=i*channels;
; else /* Color-map has sRGB values */
; {
; bytep entry = cmap;
;switch (channels)
cmp ecx,4
jne .end2
mov eax,[afirst]
or eax,eax
jz @f
xor eax,eax
jmp .end3
@@:
mov eax,3
.end3:
mov al,byte[esi+eax]
mov byte[edx],al ;tRNS[i] = entry[afirst ? 0 : 3]
cmp al,255 ;if (..<..)
je @f
mov eax,[i]
inc eax
mov [num_trans],eax
@@:
dec ecx ; FALL THROUGH
.end2:
cmp ecx,3
jne @f
add esi,[afirst]
mov eax,[bgr]
xor eax,2
lea eax,[esi+eax]
mov al,byte[eax]
stosb ;palette[i].blue
; entry += i * channels;
lea eax,[esi+1]
mov al,byte[eax]
stosb ;palette[i].green
; switch (channels)
; {
; case 4:
; tRNS[i] = entry[afirst ? 0 : 3];
; if (tRNS[i] < 255)
; num_trans = i+1;
; /* FALL THROUGH */
; case 3:
; palette[i].blue = entry[afirst + (2 ^ bgr)];
; palette[i].green = entry[afirst + 1];
; palette[i].red = entry[afirst + bgr];
; break;
; case 2:
; tRNS[i] = entry[1 ^ afirst];
; if (tRNS[i] < 255)
; num_trans = i+1;
; /* FALL THROUGH */
; case 1:
; palette[i].blue = palette[i].red = palette[i].green =
; entry[afirst];
; break;
; default:
; break;
; }
; }
; }
mov eax,[bgr]
lea eax,[esi+eax]
mov al,byte[eax]
stosb ;palette[i].red
jmp .end1
@@:
cmp ecx,2
jne @f
xor eax,eax
inc eax
xor eax,[afirst]
mov al,byte[esi+eax]
mov byte[edx],al ;tRNS[i] = entry[1 ^ afirst]
cmp al,255 ;if (..<..)
je @f
mov eax,[i]
inc eax
mov [num_trans],eax
@@:
dec ecx; FALL THROUGH
@@:
cmp ecx,1
jne .end1
mov eax,[afirst]
mov al,byte[esi+eax]
stosb
stosb
stosb
.end1:
inc edx
mov eax,[entries]
inc [i]
cmp [i],eax
jl .cycle0
.cycle0end:
mov ecx,[ebx+png_image.opaque]
mov eax,ebp
sub eax,256+256*sizeof.png_color
lea eax,[ebp-256-256*sizeof.png_color]
stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries]
cmp dword[num_trans],0
@@ -2820,9 +2867,26 @@ png_debug1 2, 'IDAT compress all len = %d', [len]
mov edi,[buf_f]
mov esi,[buf]
cmp eax,PNG_COLOR_TYPE_PALETTE
je .cycle7
cmp eax,PNG_COLOR_TYPE_RGB
je .cycle0
cmp eax,PNG_COLOR_TYPE_RGB_ALPHA
je .cycle5
.cycle7: ;8 bit image palette
cmp edx,1
jl .cycle0end
mov ecx,ebx
xor al,al
stosb ;insert filter (0 - none)
align 4
rep movsb
dec edx
jmp .cycle7
.cycle7end:
jmp .cycle5end
.cycle0: ;24 bit image
cmp edx,1
jl .cycle0end
@@ -1063,8 +1063,8 @@ align 4
proc png_write_PLTE, png_ptr:dword, palette:dword, num_pal:dword
locals
;max_palette_length dd ? ;uint_32
i dd ?
pal_ptr dd ? ;png_const_colorp
;i dd ?
;pal_ptr dd ? ;png_const_colorp
buf rb 3 ;byte[3]
endl
png_debug 1, 'in png_write_PLTE'
@@ -1085,16 +1085,16 @@ pushad
;mov [max_palette_length],eax
.end0:
if PNG_MNG_FEATURES_SUPPORTED eq 1
cmp [num_pal],eax
jg @f
if PNG_MNG_FEATURES_SUPPORTED eq 1
mov eax,[edi+png_struct.mng_features_permitted]
and eax,PNG_FLAG_MNG_EMPTY_PLTE
jnz .end1
end if
cmp [num_pal],0
jne .end1
@@:
end if
cmp byte[edi+png_struct.color_type],PNG_COLOR_TYPE_PALETTE ;if (..==..)
jne @f
@@ -1118,31 +1118,24 @@ end if
imul eax,3
stdcall png_write_chunk_header, edi, png_PLTE, eax
if PNG_POINTER_INDEXING_SUPPORTED eq 1
; for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
; {
; buf[0] = pal_ptr->red;
; buf[1] = pal_ptr->green;
; buf[2] = pal_ptr->blue;
; png_write_chunk_data(png_ptr, buf, (png_size_t)3);
; }
mov ecx,[num_pal]
or ecx,ecx
jz .cycle0end
mov esi,[palette]
lea ebx,[ebp-3] ;ebx = &buf
align 4
.cycle0: ;for (;;)
lodsb
mov [ebx],al
lodsb
mov [ebx+1],al
lodsb
mov [ebx+2],al
stdcall png_write_chunk_data, edi, ebx, 3
loop .cycle0
.cycle0end:
else
; This is a little slower but some buggy compilers need to do this
; instead
; pal_ptr=palette;
; for (i = 0; i < num_pal; i++)
; {
; buf[0] = pal_ptr[i].red;
; buf[1] = pal_ptr[i].green;
; buf[2] = pal_ptr[i].blue;
; png_write_chunk_data(png_ptr, buf, (png_size_t)3);
; }
end if
stdcall png_write_chunk_end, edi
or dword[edi+png_struct.mode], PNG_HAVE_PLTE
.end_f:
@@ -1163,7 +1163,7 @@ local .l1
;;================================================================================================;;
align 4
proc img.encode.png uses ebx edx, _img:dword, _common:dword, _specific:dword
proc img.encode.png uses ebx edx edi, _img:dword, _common:dword, _specific:dword
;;------------------------------------------------------------------------------------------------;;
;? Encode image into raw data in png format ;;
;;------------------------------------------------------------------------------------------------;;
@@ -1175,12 +1175,15 @@ proc img.encode.png uses ebx edx, _img:dword, _common:dword, _specific:dword
;< ecx = error code / the size of encoded data ;;
;;================================================================================================;;
locals
colormap dd 0
encoded_file rd 1
encoded_file_size rd 1
simag png_image
endl
mov ebx,[_img]
mov eax,[ebx+Image.Type]
cmp eax,Image.bpp8i
je @f
cmp eax,Image.bpp24
je @f
cmp eax,Image.bpp32
@@ -1192,16 +1195,27 @@ endl
mov dword[edx+png_image.version],PNG_IMAGE_VERSION
mov ecx,[ebx+Image.Width]
mov [edx+png_image.width],ecx ;Image width in pixels (columns)
cmp eax,Image.bpp8i
jne @f
mov dword[edx+png_image.format],PNG_FORMAT_RGBA_COLORMAP
mov eax,ecx
imul eax,[ebx+Image.Height]
add eax,[ebx+Image.Data]
add [colormap],eax
stdcall get_pallete_colors,eax
mov dword[edx+png_image.colormap_entries],eax
jmp .init
@@:
cmp eax,Image.bpp24
jne @f
mov dword[edx+png_image.format],PNG_FORMAT_RGB
imul ecx,3
@@:
cmp eax,Image.bpp32
jne @f
jne .init
mov dword[edx+png_image.format],PNG_FORMAT_RGBA
shl ecx,2
@@:
.init:
mov eax,[ebx+Image.Height]
mov [edx+png_image.height],eax ;Image height in pixels (rows)
;mov dword[edx+png_image.flags],PNG_IMAGE_FLAG_???
@@ -1221,7 +1235,7 @@ endl
@@:
mov [encoded_file],eax
lea edi,[edx-4]
stdcall png_image_write_to_memory, edx,eax,edi,0,[ebx+Image.Data],ecx,0
stdcall png_image_write_to_memory, edx,eax,edi,0,[ebx+Image.Data],ecx,[colormap]
mov eax,[encoded_file]
mov ecx,[encoded_file_size]
jmp .quit
@@ -1231,3 +1245,31 @@ endl
.quit:
ret
endp
;;================================================================================================;;
align 4
proc get_pallete_colors uses ecx edi, palette:dword
;;------------------------------------------------------------------------------------------------;;
;? Determine the palette size. Locate two adjacent zero-value colors; ;;
;? this marks the end of the palette. ;;
;;------------------------------------------------------------------------------------------------;;
mov ecx,256-1
mov edi,[palette]
xor eax,eax
@@:
repne scasd
or ecx,ecx
jz .max_pal
cmp [edi],eax ;second color check
jne @b ;find again
sub edi,[palette]
shr edi,2
mov eax,edi
jmp @f
.max_pal:
mov eax,256
@@:
ret
endp
+45 -42
View File
@@ -3,6 +3,7 @@ public EXPORTS
section '.flat' code readable align 16
include '../../../macros.inc'
include '../../../KOSfuncs.inc'
include 'strlen.inc'
MB_FIRST_BUT_ID equ 3 ;идентификатор 1-й кнопки на сообщении
@@ -18,14 +19,8 @@ MB_TEXT_OFFSET equ 2 ;ᬥ饭
align 4
start:
mov eax,48
mov ebx,3
mov ecx,sc
mov edx,sizeof.system_colors
mcall
mov eax,40
mov ebx,0x27
mcall
mcall SF_STYLE_SETTINGS,SSF_GET_COLORS,sc,sizeof.system_colors
mcall SF_SET_EVENTS_MASK, EVM_MOUSE + EVM_BUTTON + EVM_KEY + EVM_REDRAW
;-- clear id pressed button ---
mov ebx,[mb_text]
@@ -39,9 +34,7 @@ start:
align 4
red_win:
mov eax,12
mov ebx,1
mcall
mcall SF_REDRAW,SSF_BEGIN_DRAW
xor eax,eax
mov bx,word[mb_left]
@@ -56,7 +49,7 @@ red_win:
add edi,MB_TEXT_OFFSET ;Caption
mcall
mcall 9,mb_procinfo,-1
mcall SF_THREAD_INFO,mb_procinfo,-1
mov eax,dword[mb_procinfo.client_box.width]
sub eax,[but_width]
@@ -64,7 +57,6 @@ red_win:
add eax,MB_BUT_OTX_1
mov [ot_left],eax
mov eax,4 ;рисование текста
mov bx,MB_BUT_OTX_1
shl ebx,16
mov bx,MB_BUT_OTY_1
@@ -76,13 +68,12 @@ red_win:
call strlen
call linlen
cmp eax,0
je @f
or eax,eax
jz @f
mov esi,eax
push eax
mov eax,4
int 0x40
mcall SF_DRAW_TEXT
pop eax
add edx,eax
@@ -95,25 +86,24 @@ red_win:
@@:
call MsgBoxDrawAllBut
mcall 12,2
mcall SF_REDRAW,SSF_END_DRAW
align 4
still:
mov eax,10
mcall
mcall SF_WAIT_EVENT
cmp al,1 ;изм. положение окна
cmp al,EV_REDRAW
jz red_win
cmp al,2
cmp al,EV_KEY
jz key
cmp al,3
cmp al,EV_BUTTON
jz button
jmp still
align 4
key:
mcall 2
mcall SF_GET_KEY
cmp ah,13
jne @f
mov ah,[mb_key_foc]
@@ -153,7 +143,7 @@ key:
align 4
button:
mcall 17 ;получить код нажатой кнопки
mcall SF_GET_BUTTON
cmp ah,MB_FIRST_BUT_ID
jge close
cmp ah,1
@@ -169,8 +159,8 @@ close:
mov byte[ebx],ah
;*** call msgbox functions ***
cmp ah,0
je @f
or ah,ah
jz @f
cmp dword[mb_funct],0
je @f
xor ebx,ebx
@@ -182,7 +172,7 @@ close:
je @f
call dword[ebx]
@@:
mcall -1 ;выход из программы
mcall SF_TERMINATE_PROCESS
align 4
MsgBoxDrawAllBut:
@@ -202,8 +192,8 @@ MsgBoxDrawAllBut:
mov esi,edx
call strlen
cmp eax,0
je @f
or eax,eax
jz @f
call MsgBoxDrawButton
inc ecx
@@ -253,8 +243,7 @@ MsgBoxDrawButton:
ror ebx,16
mov bx,ax
mov eax,8
int 0x40
mcall SF_DEFINE_BUTTON
pop edx ebx eax
;caption
@@ -264,8 +253,7 @@ MsgBoxDrawButton:
mov ecx,[sc.work_button]
@@:
mov esi,eax
mov eax,4
int 0x40
mcall SF_DRAW_TEXT
pop ecx
ret
@@ -284,6 +272,25 @@ MsgBoxReInit:
add esi,eax ;add len of caption
mov [txtMsg],esi
;--- calc window width ---
push eax ebx esi
.cycle:
call strlen
mov ebx,eax
call linlen
add esi,eax
sub ebx,eax
imul eax,6
add eax,10+2*SF_DRAW_TEXT
cmp [mb_width],ax
jge @f
mov [mb_width],ax
@@:
inc esi
cmp ebx,5 ;length of the remaining text
jg .cycle
pop esi ebx eax
;--- go to first button text --- buttons 1...MB_MAX_BUT
mov ebx,txtBut
mov cx,MB_MAX_BUT
@@ -320,12 +327,11 @@ MsgBoxReInit:
add eax,MB_BUT_HEIGHT
add ax,5 ;height of border
mov [mb_height],ax
mcall 48,4 ;skin height
mcall SF_STYLE_SETTINGS,SSF_GET_SKIN_HEIGHT
add [mb_height],ax
;--- calc window top ---
mov eax,14
int 0x40
mcall SF_GET_SCREEN_SIZE
mov word[mb_top],ax
mov ax,word[mb_height]
sub word[mb_top],ax
@@ -367,6 +373,7 @@ MsgBoxReInit:
;input:
; [esp+8] = pointer to msgbox text
; [esp+12] = thread stack
align 4
MsgBoxCreate:
push ebp
@@ -374,11 +381,7 @@ MsgBoxCreate:
m2m dword[mb_text],dword[ebp+8]
push eax ebx ecx edx
mov eax,51
mov ebx,1
mov ecx,start
mov edx,dword[ebp+12];thread
int 0x40
mcall SF_THREAD_CONTROL,SSF_CREATE_THREAD,start,[ebp+12]
mov dword[mb_funct],0
pop edx ecx ebx eax
+9 -4
View File
@@ -1,5 +1,6 @@
format MS COFF
public EXPORTS
include '../../../KOSfuncs.inc'
section '.flat' code readable align 16
; void __stdcall START(dword state);
DLL_ENTRY equ 1
@@ -60,6 +61,7 @@ START:
; SORT_BY_ACCESSED = 12, SORT_BY_ACCESSED_REV = 13 };
; int __stdcall sort_dir(BDFE* folder_data, unsigned num_folder_entries, sort_mode mode);
; return: 0 = ok, 1 = error
align 4
sort_dir:
cmp dword [esp+12], num_compare_fns
jae .error
@@ -73,9 +75,9 @@ sort_dir:
jz .done
cmp eax, ecx
jae .memok
push 68
push SF_SYS_MISC
pop eax
push 12
push SSF_MEM_ALLOC
pop ebx
int 0x40
test eax, eax
@@ -103,6 +105,8 @@ sort_dir:
pop ecx
mov ebx, edx
sub esp, 304
cld
align 4
.moveloop:
mov esi, [ebx]
test esi, esi
@@ -139,9 +143,9 @@ sort_dir:
.done_free:
cmp edx, ptr_table
jz .done
push 68
push SF_SYS_MISC
pop eax
push 13
push SSF_MEM_FREE
pop ebx
mov ecx, edx
int 0x40
@@ -269,6 +273,7 @@ compare_name_rev:
stc
ret
align 4
strcmpi:
push eax
@@:
+4
View File
@@ -1,6 +1,10 @@
HISTORY:
4.1.1 (18/09/2026, Leency)
bug-fixes:
- fixed crash on deleting the whole text (Ctrl+A, Del)
4.1 (17/07/2015, Pathoswithin)
- various fixes
+3 -3
View File
@@ -5,8 +5,8 @@
; project name: TINYPAD
; compiler: flat assembler 1.67.21
; memory to compile: 3.0/9.0 MBytes (without/with size optimizations)
; version: SVN (4.1)
; last update: 2015-07-17 (Jul 17, 2015)
; version: SVN (4.1.1)
; last update: 2026-09-18 (Sep 18, 2026)
; minimal kernel: revision #4199 (https://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/kernel/trunk)
;-----------------------------------------------------------------------------
; originally by: Ville Michael Turjanmaa >> villemt@aton.co.jyu.fi
@@ -40,7 +40,7 @@ include 'tinypad.inc'
__header '01',1,@CODE,TINYPAD_END,STATIC_MEM_END,MAIN_STACK,@PARAMS,ini_path
APP_VERSION equ '4.1'
APP_VERSION equ '4.1.1'
TRUE = 1
FALSE = 0
+30 -1
View File
@@ -355,7 +355,7 @@ proc line_add_spaces ;////////////////////////////////////////////////////////
; ESI = line offset
; ECX = needed line length
; Output:
; EAX = delta
; EAX = delta, CF = 1 on failure
;-----------------------------------------------------------------------------
xor eax,eax
pushad
@@ -365,6 +365,7 @@ proc line_add_spaces ;////////////////////////////////////////////////////////
sub ecx,edx
lea eax,[ecx+sizeof.EDITOR_LINE_DATA]
call editor_realloc_lines
jc .failed
mov [esp+4*7],eax
add esi,eax
push ecx
@@ -388,6 +389,26 @@ proc line_add_spaces ;////////////////////////////////////////////////////////
rep stosb
.exit:
popad
clc
ret
.failed:
popad
stc
ret
endp
;-----------------------------------------------------------------------------
proc set_lines_terminator ;///////////////////////////////////////////////////
;-----------------------------------------------------------------------------
; Lines buffer is terminated by a line header with zero Size, restore it after
; the data has been compacted (line count decreased)
;-----------------------------------------------------------------------------
push ecx esi
mov ecx,[cur_editor.Lines.Count]
call get_line_offset
mov [esi+EDITOR_LINE_DATA.Size],0
mov [esi+EDITOR_LINE_DATA.Flags],0
pop esi ecx
ret
endp
@@ -408,6 +429,7 @@ proc delete_selection ;///////////////////////////////////////////////////////
or [esi+EDITOR_LINE_DATA.Flags],EDITOR_LINE_FLAG_MOFIFIED
mov ecx,[sel.begin.x]
call line_add_spaces
jc .abort
add esi,eax
lea edi,[esi+sizeof.EDITOR_LINE_DATA]
mov ecx,[sel.end.y]
@@ -456,6 +478,8 @@ proc delete_selection ;///////////////////////////////////////////////////////
rep movsb
.exit:
call set_lines_terminator
mov eax,[sel.begin.x]
mov [cur_editor.Caret.X],eax
mov [cur_editor.SelStart.X],eax
@@ -478,6 +502,11 @@ proc delete_selection ;///////////////////////////////////////////////////////
clc
ret
.abort:
popad
clc
ret
.exit.2:
stc
ret
+13
View File
@@ -993,17 +993,30 @@ endp
proc editor_realloc_lines ;///// ADD $DELTA$ TO LINES SIZE ///////////////////
;-----------------------------------------------------------------------------
; EAX = delta
; Output:
; EAX = buffer displacement, CF = 1 on failure (buffer left untouched)
;-----------------------------------------------------------------------------
push ebx ecx
mov ebx,[cur_editor.Lines.Size]
push ebx
add ebx,eax
mov eax,[cur_editor.Lines]
mov [cur_editor.Lines.Size],ebx
mov ecx,eax
stdcall mem.ReAlloc,eax,ebx
test eax,eax
jz .failed
add esp,4
mov [cur_editor.Lines],eax
sub eax,ecx
pop ecx ebx
clc
ret
.failed:
pop [cur_editor.Lines.Size]
xor eax,eax
pop ecx ebx
stc
ret
endp
+1
View File
@@ -237,6 +237,7 @@ proc load_from_memory ;///////////////////////////////////////////////////////
lea edx,[ebx+ecx]
imul ebx,eax,16
add ebx,edx
add ebx,sizeof.EDITOR_LINE_DATA
mov [ebp+EDITOR.Lines.Size],ebx
stdcall mem.ReAlloc,[ebp+EDITOR.Lines],ebx
mov [ebp+EDITOR.Lines],eax
+14
View File
@@ -591,10 +591,12 @@ proc key.ctrl_v ;///// PASTE ///////////////////////////////////
mov eax,[copy_size]
sub eax,sizeof.EDITOR_LINE_DATA
call editor_realloc_lines
jc .exit_1
mov ecx,[cur_editor.Caret.Y]
call get_line_offset
mov ecx,[cur_editor.Caret.X]
call line_add_spaces
jc .exit_1
pushd [esi+EDITOR_LINE_DATA.Size]
push esi
lea eax,[esi+ecx+sizeof.EDITOR_LINE_DATA]
@@ -692,6 +694,7 @@ proc key.ctrl_d ;///// INSERT SEPARATOR ////////////////////////
;---------------------------------------------------------------
mov eax,90+sizeof.EDITOR_LINE_DATA
call editor_realloc_lines
jc .exit
mov ecx,[cur_editor.Caret.Y]
call get_line_offset
@@ -748,6 +751,7 @@ proc key.ctrl_y ;///// DELETE CURRENT LINE /////////////////////
shr ecx,2
cld
rep movsd
call set_lines_terminator
pop eax
add eax,sizeof.EDITOR_LINE_DATA
@@ -1151,6 +1155,7 @@ proc key.del ;///// DELETE NEXT CHAR OR SELECTION //////////////
.ok.dec.lines:
dec [cur_editor.Lines.Count]
call set_lines_terminator
mov eax,[cur_editor.Lines.Count]
cmp [cur_editor.Caret.Y],eax
jb @f
@@ -1264,6 +1269,7 @@ proc key.tab ;///// TABULATE ///////////////////////////////////
push eax
call editor_realloc_lines
pop eax
jc .failed
mov ecx,[cur_editor.Caret.Y]
call get_line_offset
and [esi+EDITOR_LINE_DATA.Flags],not EDITOR_LINE_FLAG_SAVED
@@ -1282,6 +1288,7 @@ proc key.tab ;///// TABULATE ///////////////////////////////////
push eax
mov eax,10
call editor_realloc_lines
jc .failed.1
add esi,eax
pop eax
pushad
@@ -1332,6 +1339,12 @@ proc key.tab ;///// TABULATE ///////////////////////////////////
.exit:
ret
.failed.1:
pop eax
.failed:
add esp,4*2
ret
endp
;---------------------------------------------------------------
@@ -1342,6 +1355,7 @@ proc key.return ;///// CARRIAGE RETURN /////////////////////////
; so you should do a little more value
mov eax,14*100
call editor_realloc_lines
jc .exit
mov ecx,[cur_editor.Caret.Y]
call get_line_offset
+34 -25
View File
@@ -51,6 +51,7 @@ include '../../load_lib.mac'
include '../../dll.inc'
include '../../develop/libraries/libs-dev/libio/libio.inc'
include '../../develop/libraries/libs-dev/libimg/libimg.inc'
include '../../develop/libraries/box_lib/box_lib.mac'
;include '../../debug.inc'
@use_library mem.Alloc,mem.Free,mem.ReAlloc,dll.Load
@@ -63,15 +64,16 @@ ci_offs_skin_w equ 5 ;adjustment to the width of the skin frame
ci_offs_skin_h equ 24 ;skin height adjustment
; main window
ci_wnd_min_siz_x equ 585 ;minimum size x
ci_wnd_min_siz_y equ 400 ;minimum size y
ci_wnd_start_siz_x equ 585
ci_wnd_start_siz_y equ 400
ci_wnd_min_siz_x equ 510 ;minimum size x
ci_wnd_min_siz_y equ 180 ;minimum size y
; toolbar
ci_panel_x_pos equ 0 ;coord. x for panel
ci_panel_y_pos equ 20 ;coord. y for panel
ci_panel_but_y1 equ ci_panel_y_pos +5 ;y coordinate for 1st row of buttons
ci_panel_but_y2 equ ci_panel_y_pos+30 ;y coordinate for 2nd row of buttons
ci_palete_y_pos equ ci_panel_y_pos+51 ;y coordinate for color palette
ci_panel_zoom_x equ 178 ;x coordinate for zoom bar buttons
; editor window
@@ -80,7 +82,7 @@ ci_edit_wnd_y_pos equ 71 ;y coordinate for editor window
ci_edit_wnd_border equ 3 ;frame around the editor window
; scrolling
ci_scroll_dim equ 22 ;scroll sizes
ci_scroll_dim equ 16 ;scroll sizes
ci_scrollh_coord_x_min equ (ci_edit_wnd_x_pos+3) ;x minimum slider position
;horizontal scrolling
ci_scrollv_coord_y_min equ (ci_edit_wnd_y_pos+3) ;y minimum slider position
@@ -149,6 +151,12 @@ include 'init_data.inc'
;OpenDialog initialisation
stdcall [OpenDialog_Init], OpenDialog_data
stdcall [ColorDialog_Init], ColorDialog_data
mcall SF_REDRAW,SSF_BEGIN_DRAW
mov ebx,50 shl 16 + ci_wnd_start_siz_x
mov ecx,50 shl 16 + ci_wnd_start_siz_y
mcall SF_CREATE_WINDOW,,,0x73aabbcc,,name_of_program
mcall SF_REDRAW,SSF_END_DRAW
;---------------------------------------------------------------------
align 4
@@ -161,16 +169,16 @@ align 4
still:
mcall SF_WAIT_EVENT
cmp eax,1
cmp eax,EV_REDRAW
je red
cmp eax,2
cmp eax,EV_KEY
je keys
cmp eax,3
cmp eax,EV_BUTTON
je buttons
cmp eax,6
cmp eax,EV_MOUSE
je mouse
jmp still
@@ -186,7 +194,16 @@ copy_str_1:
jnz @b
ret
;---------------------------------------------------------------------
include 'events.inc'
;description:
; move both scrollbars back to the top left corner (0,0)
align 4
scrollbar_move_00:
and [PosX],0
and [PosY],0
mov [sb_horizont.position],0
mov [sb_vertical.position],0
ret
;---------------------------------------------------------------------
include 'events_of_window.inc'
include 'events_of_keys.inc'
include 'events_of_buttons.inc'
@@ -205,7 +222,6 @@ include 'menu.inc'
;-----------------------------------------------------------
;------------variables and data of program------------------
;-----------------------------------------------------------
;sound_havent_memory db 150,64,0
include 'lib_data.inc'
include 'panel_data.inc'
@@ -240,6 +256,13 @@ spray_cursor:
file 'cursors/spray.cur'
zoom_cursor:
file 'cursors/zoom.cur'
align 4
scroll_drag dd 0
sb_horizont scrollbar ci_wnd_start_siz_x-ci_scroll_dim-2*ci_offs_skin_w,0,\
ci_scroll_dim,ci_edit_wnd_y_pos+284, 15, 100,30,0, 0xaaaaaa, 0xcccccc,0, 1
sb_vertical scrollbar ci_scroll_dim,ci_wnd_start_siz_x-ci_scroll_dim-2*ci_offs_skin_w,\
284,ci_edit_wnd_y_pos, 15, 100,30,0, 0xaaaaaa, 0xcccccc,0, 1
;----------------------------------------------------------
align 4
IM_END:
@@ -305,20 +328,6 @@ counter2 rd 1
number_panel rd 1
number_menu rd 1
Scroll1CoordinatX rd 1 ;scroll x screen position
Scroll1CoordinatY rd 1 ;scroll y screen position
Scroll1MaxSizeX rd 1
Scroll1MaxSizeY rd 1
Scroll1SizeX rd 1 ;scroll polzunok size
Scroll1FreeX rd 1
Scroll2CoordinatX rd 1
Scroll2CoordinatY rd 1
Scroll2MaxSizeX rd 1
Scroll2MaxSizeY rd 1
Scroll2SizeY rd 1
Scroll2FreeY rd 1
x rd 1
y rd 1
@@ -366,7 +375,7 @@ filename_area rb 256
temp_dir_pach rb 4096
library_path rb 4096
cur_dir_path rb 4096
procinfo: rb 1024
procinfo process_information
align 4
syscolors rb 192
syscolors_end:
-21
View File
@@ -1,21 +0,0 @@
;----------------------------------------------------------
;---------------------sound of events----------------------
;----------------------------------------------------------
align 4
sound:
mcall SF_SPEAKER_PLAY,55
ret
;----------------------------------------------------------
;---------------------user events--------------------------
;----------------------------------------------------------
;description:
; перемещение скроллингов в левый верхний угол (0,0)
align 4
scrollbar_move_00:
and [PosX],0
and [PosY],0
mov [Scroll1CoordinatX],ci_scrollh_coord_x_min
mov [Scroll2CoordinatY],ci_scrollv_coord_y_min
ret
+33 -78
View File
@@ -1,17 +1,22 @@
;---------------------------------------------
;-------------interraction MOUSE--------------
;---------------------------------------------
align 4
mouse:
stdcall [kmainmenu_dispatch_cursorevent], [main_menu]
or ecx,-1
mcall SF_THREAD_INFO,procinfo
mov eax,[procinfo+70] ;staus of window
movzx eax,byte [procinfo.wnd_state]
test eax,100b
jne still
call GetMouseClick
bt [MouseBut],16
jnc @f
mov [scroll_drag],0
@@:
call GetMouseCoordinats
mov eax,[MouseX]
@@ -21,6 +26,11 @@ mouse:
add ecx,ci_scrollh_coord_x_min
add edx,ci_scrollv_coord_y_min
cmp [scroll_drag],1
je sb_hor_mouse
cmp [scroll_drag],2
je sb_ver_mouse
cmp eax,ecx
jae mouse_scroll
@@ -36,105 +46,50 @@ mouse_scroll:
;call GetMouseCoordinats
;interraction with horizontal scroller
mov eax,[Scroll1CoordinatX]
mov ebx,[Scroll1CoordinatY]
movzx eax,[sb_horizont.x_pos]
movzx ebx,[sb_horizont.y_pos]
mov ecx,[MouseX]
mov edx,[MouseY]
mov esi,[Scroll1MaxSizeX]
mov edi,[Scroll1MaxSizeY]
movzx esi,[sb_horizont.x_size]
movzx edi,[sb_horizont.y_size]
call columnus
test eax,eax
jz no_horizontal
mov eax,ci_scrollh_coord_x_min
mov ebx,[Scroll1CoordinatY]
mov ecx,[Scroll1MaxSizeX]
inc ecx
mov edx,ci_scroll_dim-6
mov esi,7
call draw_volume_rectangle ; horizontal scrollbar clear
mov eax,[MouseX]
mov ebx,[Scroll1SizeX]
shr ebx,1
sub eax,ebx
mov ecx,[MouseX]
add ecx,ebx
mov edx,ci_scrollh_coord_x_min
add edx,[Scroll1MaxSizeX]
mov [Scroll1CoordinatX],eax
sub eax,ci_scrollh_coord_x_min
jns no_min_scroll
mov [Scroll1CoordinatX],ci_scrollh_coord_x_min
no_min_scroll:
cmp ecx,edx
jl no_max_scroll
sub edx,ebx
sub edx,ebx
mov [Scroll1CoordinatX],edx
no_max_scroll:
mov eax,[Scroll1CoordinatX]
sub eax,ci_scrollh_coord_x_min
bt [MouseBut],8
jnc sb_hor_mouse
mov [scroll_drag],1
sb_hor_mouse:
stdcall [scrollbar_h_mouse],sb_horizont
mov eax,[sb_horizont.position]
mov ebx,[Picture_SizeX]
imul eax,ebx
mov ebx,[Scroll1MaxSizeX]
mov ebx,[sb_horizont.max_area]
cdq
idiv ebx
mov [PosX],eax
jmp no_vertical
no_horizontal:
mov eax,[Scroll2CoordinatX]
mov ebx,[Scroll2CoordinatY]
movzx eax,[sb_vertical.x_pos]
movzx ebx,[sb_vertical.y_pos]
mov ecx,[MouseX]
mov edx,[MouseY]
mov esi,[Scroll2MaxSizeX]
mov edi,[Scroll2MaxSizeY]
movzx esi,[sb_vertical.x_size]
movzx edi,[sb_vertical.y_size]
call columnus
test eax,eax
jz no_vertical
mov eax,[Scroll2CoordinatX]
mov ebx,ci_scrollv_coord_y_min
mov ecx,ci_scroll_dim-6
mov edx,[Scroll2MaxSizeY]
inc edx
mov esi,7
call draw_volume_rectangle ; vertical scrollbar clear
mov eax,[MouseY]
mov ebx,[Scroll2SizeY]
shr ebx,1
sub eax,ebx
mov ecx,[MouseY]
add ecx,ebx
mov edx,ci_scrollv_coord_y_min
add edx,[Scroll2MaxSizeY]
mov [Scroll2CoordinatY],eax
sub eax,ci_scrollv_coord_y_min
jns no_min_scroll2
mov [Scroll2CoordinatY],ci_scrollv_coord_y_min
no_min_scroll2:
cmp ecx,edx
jl no_max_scroll2
sub edx,ebx
sub edx,ebx
mov [Scroll2CoordinatY],edx
no_max_scroll2:
mov eax,[Scroll2CoordinatY]
sub eax,ci_scrollv_coord_y_min
bt [MouseBut],8
jnc sb_ver_mouse
mov [scroll_drag],2
sb_ver_mouse:
stdcall [scrollbar_v_mouse],sb_vertical
mov eax,[sb_vertical.position]
mov ebx,[Picture_SizeY]
imul eax,ebx
mov ebx,[Scroll2MaxSizeY]
mov ebx,[sb_vertical.max_area]
cdq
idiv ebx
mov [PosY],eax
+20 -24
View File
@@ -4,12 +4,11 @@
drawwin:
or ecx,-1
mcall SF_THREAD_INFO,procinfo
mov esi,procinfo
mov eax,[esi+process_information.box.left]
mov ebx,[esi+process_information.box.top]
mov ecx,[esi+process_information.box.width]
mov edx,[esi+process_information.box.height]
mov eax,[procinfo.box.left]
mov ebx,[procinfo.box.top]
mov ecx,[procinfo.box.width]
mov edx,[procinfo.box.height]
mov [Window_CordinatX],eax
mov [Window_CordinatY],ebx
@@ -23,6 +22,20 @@ drawwin:
@@:
mov [Window_SizeX],ecx
mov [Window_SizeY],edx
; keep the size alone for a rolled up window
test [procinfo.wnd_state],byte 100b
jnz .no_change
cmp ecx,[procinfo.box.width]
jne @f
cmp edx,[procinfo.box.height]
jz .no_change
@@:
push ecx edx esi
mov esi,edx
mov edx,ecx
mcall SF_CHANGE_WINDOW, -1, -1
pop esi edx ecx
.no_change:
mov [MaxWorkScreen_SizeX],ecx
mov [MaxWorkScreen_SizeY],edx
sub [MaxWorkScreen_SizeX],ci_edit_wnd_x_pos+2*ci_edit_wnd_border\
@@ -51,7 +64,7 @@ no_znak2:
add ecx, [Window_SizeY]
mcall SF_CREATE_WINDOW,,,0x73aabbcc,,name_of_program
mov eax,[procinfo+70] ;staus of window
movzx eax,byte [procinfo.wnd_state]
test eax,100b
jne .end
@@ -81,7 +94,7 @@ no_znak2:
add ebx,ci_edit_wnd_x_pos+ci_edit_wnd_border
mov edx,[Window_SizeX]
sub edx,ebx
sub edx,ci_scroll_dim+5-ci_edit_wnd_border
sub edx,ci_scroll_dim+5+ci_edit_wnd_border
shl ebx,16
mov bx,dx ;ширина бордюра
@@ -113,23 +126,6 @@ no_znak2:
;------------------------------------------------
mcall ,,<ci_edit_wnd_y_pos,ci_edit_wnd_border> ;бордюр под панелью и над окном
;------------------------------------------------
mov eax,ci_edit_wnd_x_pos
mov ebx,[Window_SizeY]
mov ecx,[Window_SizeX]
mov edx,ci_scroll_dim
mov esi,3
sub ecx,ci_scroll_dim+5+ci_edit_wnd_x_pos+ci_offs_skin_w
sub ebx,ci_scroll_dim+5+ci_offs_skin_h
call draw_volume_rectangle ; horizontal scrollbar border
;------------------------------------------------
mov eax,[Window_SizeX]
mov ebx,ci_edit_wnd_y_pos
mov ecx,ci_scroll_dim
mov edx,[Window_SizeY]
mov esi,3
sub eax,ci_scroll_dim+5+ci_offs_skin_w
sub edx,ci_scroll_dim+5+ci_edit_wnd_y_pos+ci_offs_skin_h
call draw_volume_rectangle ; vertical scrollbar border
call draw_scrollers
;------------------------------------------------
mov eax,[Window_SizeX]
+5 -45
View File
@@ -2,12 +2,14 @@
system_dir_1: db '/sys/lib/libimg.obj',0
system_dir_2 db '/sys/lib/proc_lib.obj',0
system_dir_3: db '/sys/lib/kmenu.obj',0
system_dir_4: db '/sys/lib/box_lib.obj',0
;---------------------------------------------------------------------
align 4
l_libs_start:
lib1 l_libs system_dir_1+9, library_path, system_dir_1, import_libimg
lib2 l_libs system_dir_2+9, library_path, system_dir_2, ProcLib_import
lib3 l_libs system_dir_3+9, library_path, system_dir_3, import_libkmenu
lib4 l_libs system_dir_4+9, library_path, system_dir_4, import_box_lib
end_l_libs:
;---------------------------------------------------------------------
align 4
@@ -79,51 +81,7 @@ colordialog_path:
path4 db '/sys/noname.bmp',0
;---------------------------------------------------------------------
align 4
import_libimg:
dd alib_init1
img_is_img dd aimg_is_img
img_info dd aimg_info
img_from_file dd aimg_from_file
img_to_file dd aimg_to_file
img_from_rgb dd aimg_from_rgb
img_to_rgb dd aimg_to_rgb
img_to_rgb2 dd aimg_to_rgb2
img_decode dd aimg_decode
img_encode dd aimg_encode
img_create dd aimg_create
img_destroy dd aimg_destroy
img_destroy_layer dd aimg_destroy_layer
img_count dd aimg_count
img_lock_bits dd aimg_lock_bits
img_unlock_bits dd aimg_unlock_bits
img_flip dd aimg_flip
img_flip_layer dd aimg_flip_layer
img_rotate dd aimg_rotate
img_rotate_layer dd aimg_rotate_layer
img_draw dd aimg_draw
dd 0,0
alib_init1 db 'lib_init',0
aimg_is_img db 'img_is_img',0
aimg_info db 'img_info',0
aimg_from_file db 'img_from_file',0
aimg_to_file db 'img_to_file',0
aimg_from_rgb db 'img_from_rgb',0
aimg_to_rgb db 'img_to_rgb',0
aimg_to_rgb2 db 'img_to_rgb2',0
aimg_decode db 'img_decode',0
aimg_encode db 'img_encode',0
aimg_create db 'img_create',0
aimg_destroy db 'img_destroy',0
aimg_destroy_layer db 'img_destroy_layer',0
aimg_count db 'img_count',0
aimg_lock_bits db 'img_lock_bits',0
aimg_unlock_bits db 'img_unlock_bits',0
aimg_flip db 'img_flip',0
aimg_flip_layer db 'img_flip_layer',0
aimg_rotate db 'img_rotate',0
aimg_rotate_layer db 'img_rotate_layer',0
aimg_draw db 'img_draw',0
include '../../develop/libraries/libs-dev/libimg/import.inc'
align 4
ProcLib_import:
@@ -163,4 +121,6 @@ dd 0,0
akmenuitem_new db 'kmenuitem_new',0
akmenuitem_delete db 'kmenuitem_delete',0
akmenuitem_draw db 'kmenuitem_draw',0
include '../../develop/libraries/box_lib/import.inc'
;---------------------------------------------------------------------
Loaded 100 of 126 files, more files were not shown because too many files have changed in this diff. Show more