Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
723a1b4437 | ||
|
|
bd071d588b | ||
|
|
9ec66b0eba | ||
|
|
95bcf78537 | ||
|
|
6f3cae4e0c | ||
|
|
b59e371c0e | ||
|
|
939505198f | ||
|
|
75cb80fd33 | ||
|
|
6ba901606d | ||
|
|
b1d329da2a | ||
|
|
df9946fe80 | ||
|
|
e3d744f1b5 | ||
|
|
8ca3758efb | ||
|
|
02916ed0ee | ||
|
|
873d4de379 | ||
|
|
b2f9cc9809 | ||
|
|
298155191d | ||
|
|
49b8cdcd54 | ||
|
|
c121db7a88 | ||
|
|
9527a0f3d1 | ||
|
|
1e05d19c4c | ||
|
|
ecdebae231 | ||
|
|
0150178c90 | ||
|
|
3caf2a7a72 | ||
|
|
019f2629dc | ||
|
|
63ee53f4a3 | ||
|
|
7c8eba2ed4 | ||
|
|
15396a0304 | ||
|
|
0969869ba8 | ||
|
|
dd3af88a30 | ||
|
|
85ae0c8703 | ||
|
|
2ad11d3acc | ||
|
|
450054a86c | ||
|
|
b0055ba472 | ||
|
|
f711f9286b | ||
|
|
7802c7b18a | ||
|
|
8a94db94a5 | ||
|
|
513af11464 | ||
|
|
e0e8a35364 | ||
|
|
f2ea10c1cd | ||
|
|
302bf7e221 | ||
|
|
a3af661ed6 | ||
|
|
e74f989500 | ||
|
|
4fe3987e39 | ||
|
|
060ec1a5d0 | ||
|
|
882f1f0242 | ||
|
|
02070aa233 | ||
|
|
d0244f1513 | ||
|
|
44465b3cc2 | ||
|
|
1df9d8496d | ||
|
|
7917972a37 | ||
|
|
8334324d9c | ||
|
|
2757ea7d3e | ||
|
|
bf8ae67dbf | ||
|
|
69bd99e991 | ||
|
|
3bde56821f | ||
|
|
2c22604f39 | ||
|
|
de952921ee | ||
|
|
7f44db1b7f | ||
|
|
f143ca1928 | ||
|
|
931071a0e9 | ||
|
|
bed9528756 | ||
|
|
570a432a84 | ||
|
|
1215116155 | ||
|
|
e470ef5db5 | ||
|
|
24d1b5877a | ||
|
|
aa8913ea33 | ||
|
|
647f35ea10 | ||
|
|
f44ceb560c | ||
|
|
6defa11a9e | ||
|
|
944d74f013 | ||
|
|
2bebbcbdc3 | ||
|
|
201e8b2de3 | ||
|
|
0390ad41e4 | ||
|
|
2515d1fa37 | ||
|
|
da0e6f492b | ||
|
|
3c2bdfb418 | ||
|
|
67770ec3f4 | ||
|
|
76294451d2 | ||
|
|
031fe62338 | ||
|
|
8766bfc546 | ||
|
|
2db92868a9 | ||
|
|
4bdee82489 | ||
|
|
b9fe23b7b2 | ||
|
|
d33a03c2e4
|
||
|
|
35f35b39e7 | ||
|
|
a020a2c434 | ||
|
|
77d600c663 | ||
|
|
f7dd4033ba | ||
|
|
0ca124d6cb | ||
|
|
7365a98326 | ||
|
|
9941a5dfc9 | ||
|
|
041029b406 | ||
|
|
7c4d3f57e6 | ||
|
|
00fb7afe33 | ||
|
|
db846b5eee | ||
|
|
686f18772a | ||
|
|
9b7292f3e7 | ||
|
|
e41362fb04 | ||
|
|
bbc0f1262c | ||
|
|
5fb16b1d81 |
No files matched your search
@@ -0,0 +1,54 @@
|
||||
# =============================================================================
|
||||
# Apps
|
||||
# User-facing applications, games, multimedia, UI and desktop resources
|
||||
# =============================================================================
|
||||
|
||||
^programs/(cmm|demos|emulator|games|media|other)/.* @KolibriOS/apps
|
||||
^contrib/(games|media|other)/.* @KolibriOS/apps
|
||||
^skins/.* @KolibriOS/apps
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# System
|
||||
# Kernel, drivers, filesystems, SDK, libraries, toolchain and system utilities
|
||||
# =============================================================================
|
||||
|
||||
^kernel/.* @KolibriOS/system
|
||||
^drivers/.* @KolibriOS/system
|
||||
|
||||
^programs/(bcc32|develop|fs|hd_load|system|testing)/.* @KolibriOS/system
|
||||
^contrib/(C_Layer|sdk|toolchain)/.* @KolibriOS/system
|
||||
|
||||
# Shared system/API includes in programs/
|
||||
^programs/[^/]+\\.inc$ @KolibriOS/system
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Network
|
||||
# Network stack, network drivers, protocols, libraries and network applications
|
||||
# =============================================================================
|
||||
|
||||
^kernel/trunk/network/.* @KolibriOS/network
|
||||
|
||||
^drivers/ethernet/.* @KolibriOS/network
|
||||
^drivers/(mii|netdrv)\\.inc$ @KolibriOS/network
|
||||
|
||||
^programs/network/.* @KolibriOS/network
|
||||
^programs/network\\.inc$ @KolibriOS/network
|
||||
|
||||
^programs/develop/libraries/(http|network|kos_mbedtls)/.* @KolibriOS/network
|
||||
|
||||
^contrib/network/.* @KolibriOS/network
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# DevOps
|
||||
# CI/CD, repository infrastructure, build system and autobuild configuration
|
||||
# =============================================================================
|
||||
|
||||
^\\.gitea/.* @KolibriOS/devops
|
||||
^_tools/.* @KolibriOS/devops
|
||||
|
||||
^\\.gitmodules$ @KolibriOS/devops
|
||||
^build\\.txt$ @KolibriOS/devops
|
||||
^tup\\.config\\.template$ @KolibriOS/devops
|
||||
@@ -19,3 +19,62 @@
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
mode: preserve
|
||||
|
||||
# per-program binaries browsable at <version>/<lang>/data/, like on the old builds server
|
||||
- name: Creating build tree folders
|
||||
ansible.builtin.file:
|
||||
path: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
|
||||
state: directory
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
mode: '0755'
|
||||
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
|
||||
|
||||
- name: Unpacking build trees
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
|
||||
|
||||
# stable URL for the newest build: <storage_path>/latest/<lang>/...
|
||||
- name: Updating latest symlink
|
||||
ansible.builtin.file:
|
||||
src: "{{ version }}"
|
||||
dest: "{{ storage_path }}/latest"
|
||||
state: link
|
||||
force: true
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
|
||||
# emulators hardcode <site root>/<lang>/data/data/kolibri.img; storage_path is the ci folder, one level under the site root
|
||||
- name: Sending bare images to stable emulator paths
|
||||
ansible.builtin.copy:
|
||||
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"
|
||||
Executable
+74
@@ -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"
|
||||
+90
-24
@@ -62,7 +62,7 @@ jobs:
|
||||
make -f Makefile.lin32
|
||||
chmod +x c--
|
||||
mv c-- /home/autobuild/tools/win32/bin/c--
|
||||
cp ${{ gitea.workspace }}/programs/cmm/c--/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
cp ${{ gitea.workspace }}/programs/develop/cmm/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
make -f Makefile.lin32 clean
|
||||
|
||||
- name: Install TCC
|
||||
@@ -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
|
||||
@@ -162,12 +167,13 @@ jobs:
|
||||
tup init
|
||||
tup variant ${{ matrix.lang }}.config
|
||||
|
||||
# build the image for language variant
|
||||
# build the image for language variant; keep the tup log for publishing
|
||||
- name: Build KolibriOS
|
||||
run: |
|
||||
set -o pipefail
|
||||
export PATH=/home/autobuild/tools/win32/bin:$PATH
|
||||
source kos32-export-env-vars ${{ gitea.workspace }}
|
||||
tup build-${{ matrix.lang }}
|
||||
tup build-${{ matrix.lang }} 2>&1 | tee build.log
|
||||
|
||||
# stamp the cache with its commit so later builds diff against it
|
||||
- name: Record cache base commit
|
||||
@@ -181,15 +187,26 @@ jobs:
|
||||
id: vars
|
||||
run: echo "descr=$(git describe --tags)" >> $GITEA_OUTPUT
|
||||
|
||||
# rename build outputs to their final names so artifacts are bare files
|
||||
- name: Rename images
|
||||
# stage build outputs under their final names, plus distribution kit and checksums
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
set -e
|
||||
BASE="kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}"
|
||||
for ext in img iso raw; do
|
||||
cp "build-${{ matrix.lang }}/data/kolibri.$ext" \
|
||||
"kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.$ext"
|
||||
cp "build-${{ matrix.lang }}/data/kolibri.$ext" "$BASE.$ext"
|
||||
done
|
||||
# zip: distr targets Windows/DOS users, Explorer opens it natively
|
||||
(cd "build-${{ matrix.lang }}/data" && zip -r -9 -q "${{ gitea.workspace }}/$BASE.distr.zip" distribution_kit)
|
||||
# whole build tree for per-program downloads; the big images ship separately
|
||||
tar -C "build-${{ matrix.lang }}" \
|
||||
--exclude './data/kolibri.iso' \
|
||||
--exclude './data/kolibri.raw' \
|
||||
--exclude './data/distribution_kit' \
|
||||
-czf "$BASE.tree.tar.gz" .
|
||||
sha256sum "$BASE".img "$BASE".iso "$BASE".raw "$BASE".distr.zip > "$BASE.sha256sums.txt"
|
||||
mv build.log "$BASE.build.log"
|
||||
|
||||
#publish the three images; longer retention for the floppy image.
|
||||
# publish the images; longer retention for the floppy image
|
||||
- name: Upload floppy image
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -211,6 +228,34 @@ jobs:
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.raw
|
||||
retention-days: 15
|
||||
|
||||
- name: Upload distribution kit
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload checksums
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload build log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload build tree
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
|
||||
retention-days: 15
|
||||
|
||||
deploy:
|
||||
name: "Publish Images"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -235,31 +280,50 @@ jobs:
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
rm -rf ./norm-artifacts
|
||||
mkdir -p ./norm-artifacts
|
||||
rm -rf ./norm-artifacts ./stable-artifacts ./tree-artifacts
|
||||
mkdir -p ./norm-artifacts ./stable-artifacts ./tree-artifacts
|
||||
|
||||
find ./artifacts -type f \( \
|
||||
-name 'kolibrios-*.img' -o \
|
||||
-name 'kolibrios-*.iso' -o \
|
||||
-name 'kolibrios-*.raw' \
|
||||
\) | while read -r file; do
|
||||
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<ext>
|
||||
name_without_ext="${fname%.*}"
|
||||
lang="${name_without_ext##*-}"
|
||||
find ./artifacts -type f -name 'kolibrios-*' | while read -r file; do
|
||||
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<suffix>
|
||||
case "$fname" in
|
||||
*.tree.tar.gz) stem="${fname%.tree.tar.gz}";;
|
||||
*.distr.zip) stem="${fname%.distr.zip}";;
|
||||
*.sha256sums.txt) stem="${fname%.sha256sums.txt}";;
|
||||
*.build.log) stem="${fname%.build.log}";;
|
||||
*.img) stem="${fname%.img}";;
|
||||
*.iso) stem="${fname%.iso}";;
|
||||
*.raw) stem="${fname%.raw}";;
|
||||
*) continue;;
|
||||
esac
|
||||
lang="${stem##*-}" # <lang> has no dashes, <descr> may
|
||||
|
||||
mkdir -p "./norm-artifacts/$lang"
|
||||
cp "$file" "./norm-artifacts/$lang/$fname"
|
||||
case "$fname" in
|
||||
*.tree.tar.gz)
|
||||
# unpacked on the server into <version>/<lang>/data/ for per-program downloads
|
||||
cp "$file" "./tree-artifacts/$lang.tar.gz";;
|
||||
*.sha256sums.txt)
|
||||
cp "$file" "./norm-artifacts/$lang/sha256sums.txt";;
|
||||
*.build.log)
|
||||
cp "$file" "./norm-artifacts/$lang/build.log";;
|
||||
*.img)
|
||||
cp "$file" "./norm-artifacts/$lang/$fname"
|
||||
# emulators (e.g. v86) hardcode <lang>/data/data/kolibri.img at the site root
|
||||
mkdir -p "./stable-artifacts/$lang/data/data"
|
||||
cp "$file" "./stable-artifacts/$lang/data/data/kolibri.img";;
|
||||
*)
|
||||
cp "$file" "./norm-artifacts/$lang/$fname";;
|
||||
esac
|
||||
done
|
||||
|
||||
# derive the version (git describe) from an artifact name:
|
||||
# kolibrios-<descr>-<lang>.<ext> -> <descr>
|
||||
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*' | head -n1)"
|
||||
# derive the version (git describe) from an artifact name: kolibrios-<descr>-<lang>.iso -> <descr>
|
||||
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*.iso' | head -n1)"
|
||||
base="$(basename "${sample%.*}")" # kolibrios-<descr>-<lang>
|
||||
version="${base%-*}" # kolibrios-<descr>
|
||||
version="${version#kolibrios-}" # <descr>
|
||||
echo "version=$version" >> $GITEA_OUTPUT
|
||||
|
||||
find ./norm-artifacts -type f -print
|
||||
find ./norm-artifacts ./stable-artifacts ./tree-artifacts -type f -print
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
@@ -285,4 +349,6 @@ jobs:
|
||||
-e "storage_path=${{ secrets.STORAGE_PATH }}" \
|
||||
-e "version=${{ steps.normalize.outputs.version }}" \
|
||||
-e "artifact_path=${{ gitea.workspace }}/norm-artifacts" \
|
||||
-e "stable_artifact_path=${{ gitea.workspace }}/stable-artifacts" \
|
||||
-e "tree_artifact_path=${{ gitea.workspace }}/tree-artifacts" \
|
||||
-v
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
make -f Makefile.lin32
|
||||
chmod +x c--
|
||||
mv c-- /home/autobuild/tools/win32/bin/c--
|
||||
cp ${{ gitea.workspace }}/programs/cmm/c--/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
cp ${{ gitea.workspace }}/programs/develop/cmm/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
make -f Makefile.lin32 clean
|
||||
|
||||
- name: Install TCC
|
||||
|
||||
@@ -24,6 +24,8 @@ jobs:
|
||||
path: programs/develop/cmm
|
||||
- name: oberon07
|
||||
path: programs/develop/oberon07
|
||||
- name: cmm_apps
|
||||
path: programs/cmm
|
||||
- name: kterm
|
||||
path: programs/other/kterm
|
||||
|
||||
@@ -68,7 +70,7 @@ jobs:
|
||||
git config user.name "kolibri-bot"
|
||||
git config user.email "bot@kolibrios.org"
|
||||
git checkout -B "$BRANCH"
|
||||
git commit -m "$NAME: bump submodule to $WANT" -- "$PATH_"
|
||||
git commit -m "chore/submodules: bump $NAME to $WANT" -- "$PATH_"
|
||||
git push -f origin "$BRANCH"
|
||||
|
||||
# Open a PR via the Gitea API.
|
||||
@@ -77,7 +79,7 @@ jobs:
|
||||
http=$(curl -sS -o /tmp/pr.json -w '%{http_code}' -X POST \
|
||||
-H "Authorization: token ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"${NAME}: bump submodule to upstream\"}" \
|
||||
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"chore/submodules: bump ${NAME} to upstream\"}" \
|
||||
"${API}/repos/${REPO}/pulls")
|
||||
echo "PR API HTTP status: $http"
|
||||
cat /tmp/pr.json; echo
|
||||
|
||||
+5
-1
@@ -4,8 +4,12 @@
|
||||
branch = main
|
||||
[submodule "programs/develop/oberon07"]
|
||||
path = programs/develop/oberon07
|
||||
url = https://github.com/AntKrotov/oberon-07-compiler.git
|
||||
url = https://git.kolibrios.org/KolibriOS/oberon-07-compiler.git
|
||||
branch = master
|
||||
[submodule "programs/cmm"]
|
||||
path = programs/cmm
|
||||
url = https://git.kolibrios.org/KolibriOS/cmm_apps.git
|
||||
branch = main
|
||||
[submodule "programs/other/kterm"]
|
||||
path = programs/other/kterm
|
||||
url = https://git.kolibrios.org/b00bl1k/kterm.git
|
||||
|
||||
@@ -59,6 +59,12 @@ Co-authored-by: ANOTHER-NAME <ANOTHER-NAME@EXAMPLE.COM>
|
||||
|
||||
to the end commit message body on a new line.
|
||||
|
||||
If you used AI tools while preparing the commit, you are encouraged to include an Assisted-by tag:
|
||||
|
||||
```
|
||||
Assisted-by: AGENT_NAME:MODEL_VERSION
|
||||
```
|
||||
|
||||
### Merge commits
|
||||
|
||||
> [!WARNING]
|
||||
|
||||
+41
-27
@@ -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"},
|
||||
@@ -74,7 +69,6 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
{"WELCOME.HTM", VAR_DATA .. "/" .. build_type .. "/welcome.htm.kpack"},
|
||||
{"EXAMPLE.ASM", SRC_PROGS .. "/develop/examples/example/rus/example.asm"},
|
||||
{"DEVELOP/BACKY", SRC_PROGS .. "/develop/backy/Backy_ru"},
|
||||
{"GAMES/BASEKURS.KLA", build_type .. "/games/basekurs.kla"},
|
||||
{"File Managers/KFAR.INI", build_type .. "/File Managers/kfar.ini"},
|
||||
{"GAMES/DESCENT", build_type .. "/games/descent"},
|
||||
{"SETTINGS/.shell", SRC_PROGS .. "/system/shell/bin/rus/.shell"},
|
||||
@@ -170,10 +164,9 @@ extra_files = {
|
||||
{"kolibrios/demos/life2", "common/demos/life2"},
|
||||
{"kolibrios/demos/relay.lif", "common/demos/relay.lif"},
|
||||
{"kolibrios/demos/rpento.lif", "common/demos/rpento.lif"},
|
||||
{"kolibrios/develop/c--/c--.ini", SRC_PROGS .. "/cmm/c--/c--.ini"},
|
||||
{"kolibrios/develop/c--/manual_c--.htm", SRC_PROGS .. "/cmm/c--/manual_c--.htm"},
|
||||
{"kolibrios/develop/fpc/", "common/develop/fpc/*"},
|
||||
{"kolibrios/develop/fpc/examples/", "../programs/develop/fp/examples/src/*"},
|
||||
{"kolibrios/develop/fasm/fasm.txt", SRC_PROGS .. "/develop/fasm/1.73/fasm.txt"},
|
||||
{"kolibrios/develop/oberon07/compiler.kex", SRC_PROGS .. "/develop/oberon07/Compiler.kex"},
|
||||
{"kolibrios/develop/oberon07/LICENSE", SRC_PROGS .. "/develop/oberon07/LICENSE"},
|
||||
{"kolibrios/develop/oberon07/doc/CC.txt", SRC_PROGS .. "/develop/oberon07/doc/CC.txt"},
|
||||
@@ -194,6 +187,12 @@ extra_files = {
|
||||
{"kolibrios/develop/tcc/samples/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/*.sh"},
|
||||
{"kolibrios/develop/tcc/samples/clayer/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/clayer/*"},
|
||||
{"kolibrios/develop/utils/SPEDump", SRC_PROGS .. "/develop/SPEDump/SPEDump.kex"},
|
||||
{"kolibrios/develop/XDPascal/", SRC_PROGS .. "/develop/XDPascal/xdpk/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/Compiler/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/Compiler/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2026/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2026/*"},
|
||||
{"kolibrios/develop/XDPascal/source/", SRC_PROGS .. "/develop/XDPascal/xdpk/source/*"},
|
||||
{"kolibrios/develop/XDPascal/units/", SRC_PROGS .. "/develop/XDPascal/xdpk/units/*"},
|
||||
{"kolibrios/emul/", "common/emul/*"},
|
||||
{"kolibrios/emul/dosbox/", "common/emul/DosBox/*"},
|
||||
{"kolibrios/emul/e80/readme.txt", SRC_PROGS .. "/emulator/e80/readme.txt"},
|
||||
@@ -270,6 +269,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"},
|
||||
@@ -293,8 +296,6 @@ extra_files = {
|
||||
{"kolibrios/utils/vmode", "common/vmode"},
|
||||
{"kolibrios/utils/texture", "common/utils/texture"},
|
||||
{"kolibrios/utils/kterm/kterm", VAR_PROGS .. "/other/kterm/kterm"},
|
||||
{"kolibrios/utils/kterm/serial.sys", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"kolibrios/utils/kterm/install.sh", SRC .. "/drivers/serial/install.sh"},
|
||||
{"kolibrios/utils/cnc_editor/cnc_editor", VAR_PROGS .. "/other/cnc_editor/cnc_editor"},
|
||||
{"kolibrios/utils/cnc_editor/kolibri.NC", SRC_PROGS .. "/other/cnc_editor/kolibri.NC"},
|
||||
{"kolibrios/utils/kfm/kfm.ini", "common/File Managers/kfm.ini"},
|
||||
@@ -428,7 +429,6 @@ tup.append_table(img_files, {
|
||||
{"DISPTEST", VAR_PROGS .. "/testing/disptest/disptest"},
|
||||
{"END", VAR_PROGS .. "/system/end/light/end"},
|
||||
{"ESKIN", VAR_PROGS .. "/system/eskin/eskin"},
|
||||
{"FSPEED", VAR_PROGS .. "/testing/fspeed/fspeed"},
|
||||
{"GMON", VAR_PROGS .. "/system/gmon/gmon"},
|
||||
{"HDD_INFO", VAR_PROGS .. "/system/hdd_info/hdd_info"},
|
||||
{"KBD", VAR_PROGS .. "/testing/kbd/kbd"},
|
||||
@@ -437,7 +437,6 @@ tup.append_table(img_files, {
|
||||
{"LOADDRV", VAR_PROGS .. "/system/loaddrv/loaddrv"},
|
||||
{"MAGNIFY", VAR_PROGS .. "/system/magnify/magnify"},
|
||||
{"MADMOUSE", VAR_PROGS .. "/other/madmouse/madmouse"},
|
||||
{"MGB", VAR_PROGS .. "/testing/mgb/mgb"},
|
||||
{"MOUSEMUL", VAR_PROGS .. "/system/mousemul/mousemul"},
|
||||
{"MOUSEPOS", VAR_PROGS .. "/other/mousepos/mousepos"},
|
||||
{"MYKEY", VAR_PROGS .. "/system/MyKey/MyKey"},
|
||||
@@ -488,11 +487,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"},
|
||||
@@ -543,7 +537,7 @@ tup.append_table(img_files, {
|
||||
{"NETWORK/PING", VAR_PROGS .. "/network/ping/ping"},
|
||||
{"NETWORK/NETCFG", VAR_PROGS .. "/network/netcfg/netcfg"},
|
||||
{"NETWORK/NETSTAT", VAR_PROGS .. "/network/netstat/netstat"},
|
||||
{"NETWORK/NSINST", VAR_PROGS .. "/network/netsurf/nsinstall"},
|
||||
{"NETWORK/NETSURF", VAR_PROGS .. "/network/netsurf/netsurf"},
|
||||
{"NETWORK/NSLOOKUP", VAR_PROGS .. "/network/nslookup/nslookup"},
|
||||
{"NETWORK/PASTA", VAR_PROGS .. "/network/pasta/pasta"},
|
||||
{"NETWORK/SYNERGYC", VAR_PROGS .. "/network/synergyc/synergyc"},
|
||||
@@ -574,10 +568,15 @@ tup.append_table(img_files, {
|
||||
{"DRIVERS/UHCI.SYS", VAR_DRVS .. "/usb/uhci.sys"},
|
||||
{"DRIVERS/OHCI.SYS", VAR_DRVS .. "/usb/ohci.sys"},
|
||||
{"DRIVERS/EHCI.SYS", VAR_DRVS .. "/usb/ehci.sys"},
|
||||
{"DRIVERS/XHCI.SYS", VAR_DRVS .. "/usb/xhci/xhci.sys"},
|
||||
{"DRIVERS/USBHID.SYS", VAR_DRVS .. "/usb/usbhid/usbhid.sys"},
|
||||
{"DRIVERS/USBFTDI.SYS", VAR_DRVS .. "/usb/usbftdi/usbftdi.sys"},
|
||||
{"DRIVERS/USBOTHER.SYS",VAR_DRVS .. "/usb/usbother/usbother.sys"},
|
||||
{"DRIVERS/USBCDC.SYS", VAR_DRVS .. "/usb/usbnet/usbcdc.sys"},
|
||||
{"DRIVERS/USBRNDIS.SYS", VAR_DRVS .. "/usb/usbnet/usbrndis.sys"},
|
||||
{"DRIVERS/USBSTOR.SYS", VAR_DRVS .. "/usb/usbstor.sys"},
|
||||
{"DRIVERS/RDC.SYS", VAR_DRVS .. "/video/rdc.sys"},
|
||||
{"DRIVERS/SERIAL.SYS", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"DRIVERS/COMMOUSE.SYS", VAR_DRVS .. "/mouse/commouse.sys"},
|
||||
{"DRIVERS/PS2MOUSE.SYS", VAR_DRVS .. "/mouse/ps2mouse4d/ps2mouse.sys"},
|
||||
{"DRIVERS/TMPDISK.SYS", VAR_DRVS .. "/disk/tmpdisk.sys"},
|
||||
@@ -594,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"},
|
||||
@@ -640,24 +640,35 @@ tup.append_table(extra_files, {
|
||||
{"kolibrios/media/zsea/plugins/rotate.obj", VAR_PROGS .. "/media/zsea/plugins/rotate/rotate.obj"},
|
||||
{"kolibrios/media/zsea/plugins/scaling.obj", VAR_PROGS .. "/media/zsea/plugins/scaling/scaling.obj"},
|
||||
{"kolibrios/utils/AMDtemp", VAR_PROGS .. "/system/amd_temp_view/AMDtemp"},
|
||||
{"kolibrios/utils/fspeed", VAR_PROGS .. "/testing/fspeed/fspeed"},
|
||||
{"kolibrios/utils/mgb", VAR_PROGS .. "/testing/mgb/mgb"},
|
||||
{"kolibrios/utils/kfm/kfm", VAR_PROGS .. "/fs/kfm/kfm"},
|
||||
{"kolibrios/utils/tedit/t_edit", VAR_PROGS .. "/other/t_edit/t_edit"},
|
||||
{"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, {
|
||||
{"GAMES/KLAVISHA", VAR_PROGS .. "/games/klavisha/klavisha"},
|
||||
{"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'
|
||||
@@ -681,6 +692,7 @@ tup.append_table(img_files, {
|
||||
{"EASYSHOT", VAR_PROGS .. "/cmm/misc/easyshot.com"},
|
||||
{"MOUSECFG", VAR_PROGS .. "/cmm/mousecfg/mousecfg.com"},
|
||||
{"BARSCFG", VAR_PROGS .. "/cmm/barscfg/barscfg.com"},
|
||||
{"BBENCH", VAR_PROGS .. "/cmm/bbench/bbench.com"},
|
||||
{"SEARCH", VAR_PROGS .. "/cmm/misc/search.com"},
|
||||
{"SYSPANEL", VAR_PROGS .. "/cmm/misc/software_widget.com"},
|
||||
{"SYSMON", VAR_PROGS .. "/cmm/sysmon/sysmon.com"},
|
||||
@@ -809,6 +821,8 @@ tup.append_table(extra_files, {
|
||||
{"kolibrios/utils/minizip/minizip", VAR_PROGS .. "/fs/minizip/minizip"},
|
||||
{"kolibrios/utils/minizip/miniunz", VAR_PROGS .. "/fs/minizip/miniunz"},
|
||||
{"kolibrios/develop/c--/c--", VAR_PROGS .. "/develop/cmm/cmm"},
|
||||
{"kolibrios/develop/c--/c--.ini", SRC_PROGS .. "/develop/cmm/c--.ini"},
|
||||
{"kolibrios/develop/c--/manual_c--.htm", SRC_PROGS .. "/develop/cmm/manual_c--.htm"},
|
||||
{"kolibrios/develop/tcc/tcc", VAR_PROGS .. "/develop/ktcc/source/tcc"},
|
||||
{"kolibrios/develop/sqlite3/sqlite3", VAR_CONTRIB .. "/sdk/sources/sqlite3/shell/sqlite3"},
|
||||
{"kolibrios/develop/utils/objconv", VAR_PROGS .. "/develop/objconv/objconv"},
|
||||
|
||||
@@ -29,6 +29,7 @@ xcf=/sys/media/kiv
|
||||
rtf=/sys/RtfRead
|
||||
3ds=/sys/3d/view3ds
|
||||
asc=/sys/3d/view3ds
|
||||
stl=/sys/3d/view3ds
|
||||
lif=/kolibrios/demos/life2
|
||||
skn=/sys/skincfg
|
||||
dtp=/sys/skincfg
|
||||
@@ -47,7 +48,7 @@ mht=/sys/network/WebView
|
||||
docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -174,11 +174,12 @@ sh=/sys/shell
|
||||
|
||||
3ds=/sys/3d/view3ds
|
||||
asc=/sys/3d/view3ds
|
||||
stl=/sys/3d/view3ds
|
||||
|
||||
skn=/sys/skincfg
|
||||
dtp=/sys/skincfg
|
||||
lif=/kolibrios/demos/life2
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
|
||||
smc=/kolibrios/emul/zsnes/zsnes
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
; 21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=games/klavisha,69
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -35,7 +35,6 @@ Console Board=develop/dbgboard,19
|
||||
PCI Devices=pcidev,38
|
||||
CPU Info=cpuid,37
|
||||
Display Test=disptest,113
|
||||
Graphic Bench=mgb,121
|
||||
Benchmark=bbench,121
|
||||
HDD Info=hdd_info,50
|
||||
File Speed=fspeed,45
|
||||
Network Speed=network/dl|-test,51
|
||||
@@ -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
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -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
|
||||
@@ -116,6 +116,7 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Downloader |network/dl
|
||||
12 WebView Browser |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#13 **** SERVERS
|
||||
24 FTP |network/ftpd
|
||||
#14 **** OTHER
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -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
|
||||
@@ -121,6 +121,7 @@
|
||||
16 HTTPGet |network/httpget
|
||||
16 Descargas |network/dl
|
||||
16 Navegador WebView |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#15 **** OTROS
|
||||
16 Reloj analвgico |demos/aclock
|
||||
16 Reloj binario |demos/bcdclk
|
||||
|
||||
@@ -35,7 +35,6 @@ Consola de depuracion=develop/dbgboard,19
|
||||
Dispositivos PCI=pcidev,38
|
||||
CPU Info=cpuid,37
|
||||
Prueba de pantalla=disptest,113
|
||||
Rendimiento grafico=mgb,121
|
||||
Benchmark=bbench,121
|
||||
Info de disco=hdd_info,50
|
||||
Velocidad FS=fspeed,45
|
||||
Velocidad de red=network/dl|-test,51
|
||||
@@ -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 ****
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -39,7 +39,7 @@ docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
mht=/sys/network/WebView
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
<a href="hardware_support.htm">Поддержка оборудования</a>
|
||||
|
||||
<strong>Разработка</strong>
|
||||
<a href="/sys/docpack|f">Справочник по системным функциям Колибри</a>
|
||||
<a href="/sys/docpack|e">Использование отладчика</a>
|
||||
<a href="/sys/docpack|d">Руководство FASM</a>
|
||||
<a href="/sys/docpack|d">Справочник по системным функциям Колибри</a>
|
||||
<a href="/sys/docpack|c">Использование отладчика</a>
|
||||
<a href="/kolibrios/develop/fasm/fasm.txt">Руководство FASM</a>
|
||||
|
||||
<strong>Использование библиотек</strong>
|
||||
<a href="/sys/docpack|i">Ini</a>
|
||||
<a href="/sys/docpack|j">Диалог открытия файла OpenDial</a>
|
||||
<a href="/sys/docpack|g">Ini</a>
|
||||
<a href="/sys/docpack|h">Диалог открытия файла OpenDial</a>
|
||||
|
||||
<strong>Смотрите также</strong>
|
||||
Вики проекта <a href="http://wiki.kolibrios.org/">wiki.kolibrios.org</a>
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=games/klavisha,69
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -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 **** Звук и видео
|
||||
@@ -115,6 +115,7 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Загрузчик |network/dl
|
||||
12 Браузер WebView |network/webview
|
||||
12 Браузер NetSurf |network/netsurf
|
||||
#14 **** Разное
|
||||
00 Эмуляторы* > |@6
|
||||
45 Создание скриншотов |scrshoot
|
||||
@@ -122,7 +123,7 @@
|
||||
18 FB2 Читалка |fb2read
|
||||
16 Аналоговые часы |aclock
|
||||
21 Таблица Менделеева |/kolibrios/utils/period
|
||||
59 Тренажёр KJ|ABuIIIA |games/klavisha
|
||||
59 Тренажёр KJIABuIIIA |/kolibrios/games/klavisha/klavisha
|
||||
16 Бинарные часы |demos/bcdclk
|
||||
53 Таймер |timer
|
||||
09 Разархиватор Unz |unz
|
||||
|
||||
@@ -35,7 +35,6 @@ AMDtemp=/k/utils/AMDtemp,128
|
||||
Устройства PCI=pcidev,38
|
||||
CPU Info=cpuid,37
|
||||
Тест экрана=disptest,113
|
||||
Скорость графики=mgb,121
|
||||
Benchmark=bbench,121
|
||||
Информация о дисках=hdd_info,50
|
||||
Скорость ФС=fspeed,45
|
||||
Скорость сети=network/dl|-test,51
|
||||
@@ -515,20 +515,18 @@ HDA_AMP_VOLMASK equ 0x7F
|
||||
|
||||
|
||||
; unsolicited event handler
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64 ; must stay a power of 2 (used as a bitmask for wrap)
|
||||
|
||||
;struc HDA_BUS_UNSOLICITED
|
||||
;{
|
||||
; ; ring buffer
|
||||
; .queue:
|
||||
; times HDA_UNSOL_QUEUE_SIZE*2 dd ?
|
||||
; .rp dd ?
|
||||
; .wp dd ?
|
||||
;
|
||||
; ; workqueue
|
||||
; .work dd ?;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
;};
|
||||
struc HDA_BUS_UNSOLICITED
|
||||
{
|
||||
; ring buffer
|
||||
.queue rd HDA_UNSOL_QUEUE_SIZE * 2 ; 2 dword for each event (res and res_ex)
|
||||
.rp dd ? ; Read pointer
|
||||
.wp dd ? ; Write pointer
|
||||
; ; workqueue
|
||||
; .work dd ? ;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
}
|
||||
|
||||
; Helper for automatic ping configuration
|
||||
AUTO_PIN_MIC equ 0
|
||||
|
||||
@@ -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
|
||||
@@ -654,7 +650,15 @@ end if
|
||||
stdcall hda_codec_setup_stream, eax, SDO_TAG, 0, 0x11 ; Left & Right channels (Back panel)
|
||||
;Asper+ ]
|
||||
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
if USE_UNSOL_EV = 0
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 1
|
||||
else
|
||||
; Keep the unsolicited-event mode on the event-driven path. Running
|
||||
; snd_hda_automute at startup can issue codec commands before the new
|
||||
; unsolicited-response flow is ready, which hangs some systems.
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
end if
|
||||
|
||||
if USE_SINGLE_MODE
|
||||
mov esi, msgSingleMode
|
||||
invoke SysMsgBoardStr
|
||||
@@ -850,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]
|
||||
@@ -893,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
|
||||
@@ -907,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
|
||||
@@ -1195,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
|
||||
|
||||
@@ -1202,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
|
||||
@@ -1235,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
|
||||
@@ -1446,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
|
||||
@@ -1646,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]
|
||||
@@ -1934,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
|
||||
@@ -1949,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
|
||||
@@ -2635,7 +2720,7 @@ proc snd_hda_automute stdcall, data:dword
|
||||
test eax, eax
|
||||
jz .out
|
||||
|
||||
stdcall snd_hda_read_pin_sense, edx, 1
|
||||
stdcall snd_hda_read_pin_sense, edx, [data]
|
||||
test eax, AC_PINSENSE_PRESENCE
|
||||
jnz @f
|
||||
xchg ecx, esi
|
||||
@@ -2664,24 +2749,65 @@ proc snd_hda_automute stdcall, data:dword
|
||||
endp
|
||||
|
||||
|
||||
;Asper remember to add this functions:
|
||||
proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
;if DEBUG
|
||||
; push esi
|
||||
; mov esi, msgUnsolEvent
|
||||
; invoke SysMsgBoardStr
|
||||
; pop esi
|
||||
;end if
|
||||
if USE_UNSOL_EV = 1
|
||||
;Test. Do not make queue, process immediately!
|
||||
;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
;and then mute/unmute pin based on the results
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
end if
|
||||
ret
|
||||
endp
|
||||
;...
|
||||
; ;Asper remember to add this functions:
|
||||
; proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
; ;if DEBUG
|
||||
; ; push esi
|
||||
; ; mov esi, msgUnsolEvent
|
||||
; ; invoke SysMsgBoardStr
|
||||
; ; pop esi
|
||||
; ;end if
|
||||
; if USE_UNSOL_EV = 1
|
||||
; ;Test. Do not make queue, process immediately!
|
||||
; ;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
; ;and then mute/unmute pin based on the results
|
||||
; invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
; end if
|
||||
; ret
|
||||
; endp
|
||||
; ;...
|
||||
|
||||
align 4
|
||||
proc snd_hda_queue_unsol_event stdcall, res:dword, res_ex:dword
|
||||
; Single-producer (HDA IRQ) lock-free enqueue. The caller azx_update_rirb
|
||||
; 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]
|
||||
je .full ; ring full -> drop, keep 1 slot free
|
||||
|
||||
mov ecx, [res]
|
||||
mov [unsol_events.queue + eax*8], ecx
|
||||
mov ecx, [res_ex]
|
||||
mov [unsol_events.queue + eax*8 + 4], ecx
|
||||
mov [unsol_events.wp], edx ; publish only after data is stored
|
||||
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
.full:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc process_unsol_events stdcall, data:dword
|
||||
; Runs from TimerHS (single consumer). Uses only EAX (scratch) and calls
|
||||
; snd_hda_automute, which preserves every register, so nothing is saved.
|
||||
.loop:
|
||||
mov eax, [unsol_events.rp]
|
||||
cmp eax, [unsol_events.wp]
|
||||
je .done
|
||||
; The event payload is at [unsol_events.queue + eax*8] (res) and +4 (res_ex).
|
||||
; Per-pin tag parsing is not implemented yet, so just re-evaluate jack state.
|
||||
inc eax
|
||||
and eax, HDA_UNSOL_QUEUE_SIZE - 1
|
||||
mov [unsol_events.rp], eax
|
||||
stdcall snd_hda_automute, 0
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc fdword2str stdcall, flags:dword ; bit 0 - skipLeadZeroes; bit 1 - newLine; other bits undefined
|
||||
@@ -2950,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
|
||||
@@ -3019,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
|
||||
@@ -3053,10 +3181,16 @@ 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
|
||||
ctrl AC_CNTRL
|
||||
unsol_events HDA_BUS_UNSOLICITED
|
||||
|
||||
;Asper: BDL must be aligned to 128 according to HDA specification.
|
||||
pcmout_bdl rd 1
|
||||
|
||||
+100
-14
@@ -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:
|
||||
|
||||
|
||||
@@ -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")
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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:
|
||||
@@ -139,6 +139,7 @@ import core,\
|
||||
RegKeyboard,\
|
||||
DelKeyboard,\
|
||||
Sleep,\
|
||||
Delay,\
|
||||
GetTimerTicks,\
|
||||
\
|
||||
strncat,\
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes
|
||||
SERIAL_COMPATIBLE_API_VER = 1 ; increments in case of breaking changes
|
||||
|
||||
SERIAL_API_GET_VERSION = 0
|
||||
SERIAL_API_SRV_ADD_PORT = 1
|
||||
@@ -9,6 +9,7 @@ SERIAL_API_CLOSE_PORT = 5
|
||||
SERIAL_API_SETUP_PORT = 6
|
||||
SERIAL_API_READ = 7
|
||||
SERIAL_API_WRITE = 8
|
||||
SERIAL_API_ENUM_PORTS = 9
|
||||
|
||||
SERIAL_API_ERR_PORT_INVALID = 1
|
||||
SERIAL_API_ERR_PORT_BUSY = 2
|
||||
@@ -29,6 +30,9 @@ SERIAL_CONF_STOP_BITS_2 = 2
|
||||
|
||||
SERIAL_CONF_FLOW_CTRL_NONE = 0
|
||||
|
||||
SERIAL_INFO_DRIVER_LEN = 16
|
||||
SERIAL_INFO_DESCR_LEN = 64
|
||||
|
||||
struct SP_DRIVER
|
||||
size dd ? ; size of this struct
|
||||
startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
|
||||
@@ -46,7 +50,20 @@ struct SP_CONF
|
||||
flow_ctrl db ?
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword
|
||||
struct SP_PORT_INFO
|
||||
size dd ? ; size of this struct
|
||||
driver dd ? ; ASCIIZ driver name, e.g. "uart16550", "usb-cdc"
|
||||
descr dd ? ; ASCIIZ description, may be NULL
|
||||
ends
|
||||
|
||||
struct SP_PORT_ENUM_ENTRY
|
||||
id dd ? ; unique port number (SERIAL_PORT.id)
|
||||
busy dd ? ; 0 = free, non-zero = port is opened
|
||||
driver rb SERIAL_INFO_DRIVER_LEN
|
||||
descr rb SERIAL_INFO_DESCR_LEN
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword, info:dword
|
||||
locals
|
||||
handler dd ?
|
||||
io_code dd ?
|
||||
@@ -60,7 +77,7 @@ endl
|
||||
mov [io_code], SERIAL_API_SRV_ADD_PORT
|
||||
lea eax, [drv]
|
||||
mov [input], eax
|
||||
mov [inp_size], 8
|
||||
mov [inp_size], 12
|
||||
xor eax, eax
|
||||
mov [output], eax
|
||||
mov [out_size], eax
|
||||
@@ -129,7 +146,7 @@ proc serial_port_init
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_get_version stdcall, version:dword
|
||||
proc serial_port_get_version stdcall uses ebx, version:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
@@ -149,7 +166,7 @@ endl
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
|
||||
ret
|
||||
endp
|
||||
|
||||
@@ -297,6 +314,43 @@ endl
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_enum stdcall uses ebx, buf:dword, buf_size:dword, \
|
||||
total:dword, filled:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
push [buf_size]
|
||||
push [buf]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_ENUM_PORTS
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 8
|
||||
sub esp, 8
|
||||
mov [.output], esp
|
||||
mov dword [.out_size], 8
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
pop ebx edx
|
||||
cmp eax, -1
|
||||
je .err
|
||||
mov ecx, [total]
|
||||
mov [ecx], ebx
|
||||
mov ecx, [filled]
|
||||
mov [ecx], edx
|
||||
.err:
|
||||
|
||||
add esp, 8
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
serial_drv_name db "SERIAL", 0
|
||||
serial_drv_handle dd ?
|
||||
@@ -1,5 +0,0 @@
|
||||
#SHS
|
||||
echo Installing serial driver for kterm...
|
||||
cp /kolibrios/utils/kterm/serial.sys /sys/drivers/
|
||||
/sys/loaddrv serial
|
||||
echo Serial driver successfully installed!
|
||||
+148
-7
@@ -44,6 +44,8 @@ struct SERIAL_PORT
|
||||
rx_buf RING_BUF
|
||||
tx_buf RING_BUF
|
||||
conf SP_CONF
|
||||
driver rb SERIAL_INFO_DRIVER_LEN ; ASCIIZ, copied from SP_PORT_INFO.driver in add_port
|
||||
descr rb SERIAL_INFO_DESCR_LEN ; ASCIIZ, copied from SP_PORT_INFO.descr in add_port (may be empty)
|
||||
ends
|
||||
|
||||
proc START c, reason:dword, cmdline:dword
|
||||
@@ -57,7 +59,7 @@ proc START c, reason:dword, cmdline:dword
|
||||
stdcall uart_probe, 0x2f8, 3
|
||||
stdcall uart_probe, 0x3e8, 4
|
||||
stdcall uart_probe, 0x2e8, 3
|
||||
invoke RegService, drv_name, service_proc
|
||||
invoke RegService, serial_drv_name, service_proc
|
||||
ret
|
||||
|
||||
.fail:
|
||||
@@ -75,7 +77,7 @@ srv_calls:
|
||||
dd service_proc.setup
|
||||
dd service_proc.read
|
||||
dd service_proc.write
|
||||
; TODO enumeration
|
||||
dd service_proc.enum_ports
|
||||
srv_calls_end:
|
||||
|
||||
proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
@@ -97,11 +99,13 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; in:
|
||||
; +0: driver
|
||||
; +4: driver data
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
; +8: port info (SP_PORT_INFO*)
|
||||
cmp [edx + IOCTL.inp_size], 12
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov ecx, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
mov ebx, [ebx + 8]
|
||||
call add_port
|
||||
ret
|
||||
|
||||
@@ -137,6 +141,7 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; +4 addr to SERIAL_CONF
|
||||
; out:
|
||||
; +0 port handle if success
|
||||
; eax = 0 if success, otherwise an error code SERIAL_API_ERR_*
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
@@ -220,25 +225,60 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
mov [ebx], ecx
|
||||
ret
|
||||
|
||||
.enum_ports:
|
||||
; in:
|
||||
; +0 output buffer (array of SP_PORT_ENUM_ENTRY), may be NULL
|
||||
; +4 output buffer size in bytes
|
||||
; out:
|
||||
; +0 total number of ports in the system
|
||||
; +4 number of entries actually filled into the buffer
|
||||
; eax = 0 if success, -1 otherwise
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 8
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
push edx
|
||||
mov eax, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
call sp_enum
|
||||
pop edx
|
||||
mov ebx, [edx + IOCTL.output]
|
||||
mov [ebx], eax
|
||||
mov [ebx + 4], ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.err:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
; struct SERIAL_PORT __fastcall *add_port(const struct SP_DRIVER *drv, const void *drv_data);
|
||||
align 4
|
||||
; @param ecx pointer to SP_DRIVER
|
||||
; @param edx driver-specific argument
|
||||
; @param ebx pointer to SP_PORT_INFO
|
||||
; @return SERIAL_PORT descriptor
|
||||
proc add_port uses edi
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x\n", ecx, edx
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x info=%x\n", ecx, edx, ebx
|
||||
|
||||
mov eax, [ecx + SP_DRIVER.size]
|
||||
cmp eax, sizeof.SP_DRIVER
|
||||
jne .fail
|
||||
|
||||
test ebx, ebx
|
||||
jz .fail
|
||||
mov eax, [ebx + SP_PORT_INFO.size]
|
||||
cmp eax, sizeof.SP_PORT_INFO
|
||||
jne .fail
|
||||
|
||||
; alloc memory for serial port descriptor
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
movi eax, sizeof.SERIAL_PORT
|
||||
invoke Kmalloc
|
||||
pop ebx
|
||||
pop edx
|
||||
pop ecx
|
||||
test eax, eax
|
||||
@@ -252,6 +292,17 @@ proc add_port uses edi
|
||||
invoke MutexInit
|
||||
and [edi + SERIAL_PORT.con], 0
|
||||
|
||||
; copy port info strings
|
||||
mov eax, [ebx + SP_PORT_INFO.driver]
|
||||
lea edx, [edi + SERIAL_PORT.driver]
|
||||
mov ecx, SERIAL_INFO_DRIVER_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov eax, [ebx + SP_PORT_INFO.descr]
|
||||
lea edx, [edi + SERIAL_PORT.descr]
|
||||
mov ecx, SERIAL_INFO_DESCR_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
|
||||
@@ -282,7 +333,35 @@ proc add_port uses edi
|
||||
endp
|
||||
|
||||
align 4
|
||||
; u32 __fastcall *remove_port(struct SERIAL_PORT *port);
|
||||
; copies an ASCIIZ string into a fixed-size buffer: copies up to (size - 1)
|
||||
; bytes or until the NUL, then zero-pads the rest of the buffer
|
||||
; @param eax source ASCIIZ ptr, may be NULL
|
||||
; @param edx dest buffer ptr
|
||||
; @param ecx dest buffer size in bytes, must be >= 1
|
||||
proc copy_bounded_str uses esi edi
|
||||
mov esi, eax
|
||||
mov edi, edx
|
||||
dec ecx ; reserve the last byte for the NUL terminator
|
||||
.copy:
|
||||
test ecx, ecx
|
||||
jz .pad
|
||||
test esi, esi
|
||||
jz .pad
|
||||
lodsb
|
||||
test al, al
|
||||
jz .pad
|
||||
stosb
|
||||
dec ecx
|
||||
jmp .copy
|
||||
.pad:
|
||||
inc ecx ; account for the reserved NUL byte
|
||||
xor al, al
|
||||
rep stosb
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param ecx serial port descriptor
|
||||
proc remove_port uses esi
|
||||
mov esi, ecx
|
||||
mov ecx, port_list_mutex
|
||||
@@ -657,7 +736,69 @@ proc sp_write
|
||||
ret
|
||||
endp
|
||||
|
||||
drv_name db 'SERIAL', 0
|
||||
align 4
|
||||
; @param eax buf
|
||||
; @param edx buf_size (bytes)
|
||||
; @return eax total port count in the system
|
||||
; ecx entries filled into buf
|
||||
proc sp_enum uses ebx esi edi
|
||||
mov ecx, eax
|
||||
mov eax, edx
|
||||
xor edx, edx
|
||||
mov ebx, sizeof.SP_PORT_ENUM_ENTRY
|
||||
div ebx
|
||||
; eax max entries count
|
||||
|
||||
mov edi, ecx
|
||||
imul eax, sizeof.SP_PORT_ENUM_ENTRY
|
||||
add eax, ecx
|
||||
mov edx, eax ; end-of-buffer boundary
|
||||
|
||||
xor ebx, ebx ; total port count
|
||||
xor ecx, ecx ; filled count
|
||||
|
||||
push ecx edx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
pop edx ecx
|
||||
|
||||
mov esi, port_list
|
||||
.next:
|
||||
mov esi, [esi + SERIAL_PORT.fd]
|
||||
cmp esi, port_list
|
||||
jz .done
|
||||
inc ebx
|
||||
cmp edi, edx
|
||||
jae .next
|
||||
|
||||
mov eax, [esi + SERIAL_PORT.id]
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.id], eax
|
||||
xor eax, eax
|
||||
cmp dword [esi + SERIAL_PORT.con], 0
|
||||
setnz al
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.busy], eax
|
||||
|
||||
push ecx esi edi
|
||||
lea esi, [esi + SERIAL_PORT.driver]
|
||||
lea edi, [edi + SP_PORT_ENUM_ENTRY.driver]
|
||||
mov ecx, (SERIAL_INFO_DRIVER_LEN + SERIAL_INFO_DESCR_LEN) / 4
|
||||
rep movsd
|
||||
pop edi esi ecx
|
||||
|
||||
add edi, sizeof.SP_PORT_ENUM_ENTRY
|
||||
inc ecx
|
||||
jmp .next
|
||||
|
||||
.done:
|
||||
push ecx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexUnlock
|
||||
pop ecx
|
||||
|
||||
mov eax, ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
include_debug_strings
|
||||
|
||||
align 4
|
||||
|
||||
@@ -169,6 +169,7 @@ proc uart_probe stdcall uses ebx esi edi, io_addr:dword, irqn:dword
|
||||
; register port
|
||||
lea ecx, [uart_drv]
|
||||
mov edx, edi
|
||||
lea ebx, [uart_port_info]
|
||||
call add_port
|
||||
test eax, eax
|
||||
jz .free_desc ; TODO detach_int_handler?
|
||||
@@ -406,3 +407,11 @@ uart_drv:
|
||||
dd uart_reconf
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
align 4
|
||||
uart_port_info:
|
||||
dd uart_port_end - uart_port_info
|
||||
dd uart_port_name
|
||||
dd 0
|
||||
uart_port_end:
|
||||
uart_port_name db 'uart16550', 0
|
||||
+203
-310
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; FTDI chips driver for KolibriOS ;;
|
||||
@@ -15,10 +15,11 @@
|
||||
format PE DLL native 0.05
|
||||
entry START
|
||||
|
||||
DEBUG = 1
|
||||
L_DBG = 1
|
||||
L_ERR = 2
|
||||
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = 1
|
||||
__DEBUG_LEVEL__ = L_ERR
|
||||
|
||||
node equ ftdi_context
|
||||
node.next equ ftdi_context.next_context
|
||||
@@ -122,9 +123,10 @@ TYPE_232H=6
|
||||
TYPE_230X=7
|
||||
|
||||
;strings
|
||||
my_driver db 'usbother',0
|
||||
my_driver db 'usbftdi',0
|
||||
serial_driver db 'SERIAL',0
|
||||
nomemory_msg db 'K : no memory',13,10,0
|
||||
nomemory_msg db 'ftdi: no memory',13,10,0
|
||||
ftdi_port_name db 'ftdi',0
|
||||
|
||||
; Structures
|
||||
struct ftdi_context
|
||||
@@ -200,10 +202,13 @@ endp
|
||||
|
||||
|
||||
proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
|
||||
|
||||
locals
|
||||
.pinfo rb sizeof.SP_PORT_INFO
|
||||
endl
|
||||
|
||||
invoke USBGetParam, [.config_pipe], 0
|
||||
mov edx, eax
|
||||
DEBUGF 2,'K : Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
DEBUGF L_DBG, 'ftdi: Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
cmp word[eax+usb_descr.idVendor], 0x0403
|
||||
jnz .notftdi
|
||||
mov eax, sizeof.ftdi_context
|
||||
@@ -214,7 +219,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
invoke SysMsgBoardStr
|
||||
jmp .nothing
|
||||
@@:
|
||||
DEBUGF 2,'K : Adding struct to list 0x%x\n', eax
|
||||
DEBUGF L_DBG, 'ftdi: Adding struct to list 0x%x\n', eax
|
||||
call linkedlist_add
|
||||
|
||||
mov ebx, [.config_pipe]
|
||||
@@ -233,7 +238,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
jmp .slow
|
||||
|
||||
mov cx, [edx+usb_descr.bcdDevice]
|
||||
DEBUGF 2, 'K : Chip type 0x%x\n', ecx
|
||||
DEBUGF L_DBG, 'ftdi: Chip type 0x%x\n', ecx
|
||||
cmp cx, 0x400
|
||||
jnz @f
|
||||
mov [eax + ftdi_context.chipType], TYPE_BM
|
||||
@@ -287,8 +292,13 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
mov eax, [serial_drv_entry]
|
||||
test eax, eax
|
||||
jz @f
|
||||
stdcall serial_add_port, uart_drv, ebx
|
||||
DEBUGF 1, "usbftdi: add serial port with result %x\n", eax
|
||||
mov dword [.pinfo + SP_PORT_INFO.size], sizeof.SP_PORT_INFO
|
||||
mov dword [.pinfo + SP_PORT_INFO.driver], ftdi_port_name
|
||||
; TODO obtain iManufacturer, iProduct and iSerial strings
|
||||
mov dword [.pinfo + SP_PORT_INFO.descr], 0
|
||||
lea ecx, [.pinfo]
|
||||
stdcall serial_add_port, uart_drv, ebx, ecx
|
||||
DEBUGF L_DBG, 'ftdi: add serial port with result %x\n', eax
|
||||
@@:
|
||||
mov [ebx + ftdi_context.port_handle], eax
|
||||
|
||||
@@ -296,7 +306,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
ret
|
||||
|
||||
.notftdi:
|
||||
DEBUGF 1,'K : Skipping not FTDI device\n'
|
||||
DEBUGF L_DBG, 'ftdi: Skipping not FTDI device\n'
|
||||
.nothing:
|
||||
xor eax, eax
|
||||
ret
|
||||
@@ -317,7 +327,7 @@ EventData rd 3
|
||||
endl
|
||||
mov edi, [ioctl]
|
||||
mov eax, [edi+io_code]
|
||||
DEBUGF 1,'K : FTDI got the request: %d\n', eax
|
||||
DEBUGF L_DBG, 'ftdi: FTDI got the request: %d\n', eax
|
||||
test eax, eax ;0
|
||||
jz .version
|
||||
dec eax ;1
|
||||
@@ -416,7 +426,7 @@ endl
|
||||
.version:
|
||||
jmp .endswitch
|
||||
.error:
|
||||
DEBUGF 1, 'K : FTDI error occured! %d\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: error occured! %d\n', eax
|
||||
;mov esi, [edi+output]
|
||||
;mov [esi], dword 'ERR0'
|
||||
;or [esi], eax
|
||||
@@ -449,7 +459,7 @@ endl
|
||||
mov word[ConfPacket+6], cx
|
||||
.own_index:
|
||||
mov ebx, [edi+4]
|
||||
DEBUGF 2,'K : ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
DEBUGF L_DBG, 'ftdi: ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
lea esi, [ConfPacket]
|
||||
lea edi, [EventData]
|
||||
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\
|
||||
@@ -465,7 +475,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_setrtshigh:
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -473,7 +483,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setrtslow:
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -481,7 +491,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrhigh:
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -489,7 +499,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrlow:
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -497,7 +507,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_usb_reset:
|
||||
DEBUGF 2,'K : FTDI Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -505,7 +515,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_rx_buf:
|
||||
DEBUGF 2, 'K : FTDI Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -513,7 +523,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_tx_buf:
|
||||
DEBUGF 2, 'K : FTDI Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -521,42 +531,42 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_set_bitmode:
|
||||
DEBUGF 2, 'K : FTDI Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:2,[edi+10]:2,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BITMODE_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_line_property:
|
||||
DEBUGF 2, 'K : FTDI Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:4,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_DATA_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_latency_timer:
|
||||
DEBUGF 2, 'K : FTDI Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_event_char:
|
||||
DEBUGF 2, 'K : FTDI Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_EVENT_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_error_char:
|
||||
DEBUGF 2, 'K : FTDI Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_ERROR_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_setflowctrl:
|
||||
DEBUGF 2, 'K : FTDI Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)
|
||||
@@ -569,7 +579,7 @@ endl
|
||||
jmp .own_index
|
||||
|
||||
.ftdi_read_pins:
|
||||
DEBUGF 2, 'K : FTDI Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -598,7 +608,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_set_wchunksize:
|
||||
DEBUGF 2, 'K : FTDI Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -608,7 +618,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_wchunksize:
|
||||
DEBUGF 2, 'K : FTDI Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -618,7 +628,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_set_rchunksize:
|
||||
DEBUGF 2, 'K : FTDI Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -628,7 +638,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_rchunksize:
|
||||
DEBUGF 2, 'K : FTDI Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -638,7 +648,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_write_data:
|
||||
DEBUGF 2, 'K : FTDI Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF L_DBG, 'ftdi: Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov esi, edi
|
||||
add esi, 12
|
||||
@@ -685,7 +695,7 @@ endl
|
||||
jmp .write_loop
|
||||
|
||||
.ftdi_read_data:
|
||||
DEBUGF 2, 'K : FTDI Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF L_DBG, 'ftdi: Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov edi, [ioctl]
|
||||
mov esi, [edi+input]
|
||||
@@ -743,7 +753,7 @@ endl
|
||||
;---Dirty hack end
|
||||
|
||||
.ftdi_poll_modem_status:
|
||||
DEBUGF 2, 'K : FTDI Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -767,7 +777,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_latency_timer:
|
||||
DEBUGF 2, 'K : FTDI Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE \
|
||||
@@ -787,7 +797,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_list:
|
||||
DEBUGF 2, 'K : FTDI devices list request\n'
|
||||
DEBUGF L_DBG, 'ftdi: devices list request\n'
|
||||
mov edi, [edi+output]
|
||||
xor ecx, ecx
|
||||
call linkedlist_gethead
|
||||
@@ -817,7 +827,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_lock:
|
||||
DEBUGF 2, 'K : FTDI Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF L_DBG, 'ftdi: Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov ebx, [esi+4]
|
||||
mov eax, [ebx + ftdi_context.lockPID]
|
||||
@@ -831,7 +841,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_unlock:
|
||||
DEBUGF 2, 'K : FTDI Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF L_DBG, 'ftdi: Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov edi, [edi+output]
|
||||
mov ebx, [esi+4]
|
||||
@@ -845,145 +855,19 @@ endl
|
||||
mov [edi], eax
|
||||
jmp .endswitch
|
||||
|
||||
H_CLK = 120000000
|
||||
C_CLK = 48000000
|
||||
.ftdi_set_baudrate:
|
||||
DEBUGF 2, 'K : FTDI Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
DEBUGF L_DBG, 'ftdi: Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [edi+8], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword[edi+8], H_CLK/10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK/10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp dword[edi+8], C_CLK/16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK/16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword[edi+8], H_CLK/(10 + 10/2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK/(10 + 10/2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword[edi+8], C_CLK/(16 + 16/2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16/2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword[edi+8], H_CLK/(2*10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK/(2*10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword[edi+8], C_CLK/(2*16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK/(2*16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK*16/10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK*16/10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp+eax*4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov esi, [edi+8]
|
||||
call ftdi_calc_baud_divisor
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word[ConfPacket+2], ax
|
||||
mov word[ConfPacket+4], cx
|
||||
mov word[ConfPacket+6], 0
|
||||
jmp .own_index
|
||||
|
||||
jmp .own_index
|
||||
|
||||
endp
|
||||
restore handle
|
||||
restore io_code
|
||||
@@ -993,10 +877,143 @@ restore output
|
||||
restore out_size
|
||||
|
||||
|
||||
proc ftdi_calc_baud_divisor
|
||||
; in: ebx = ftdi_context pointer
|
||||
; esi = baud rate
|
||||
; out: ax = encoded value
|
||||
; cx = encoded index
|
||||
; destroys: eax, ecx, edx, esi
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, esi, 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp esi, H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp esi, C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp esi, H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp esi, C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp esi, H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp esi, C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
ret
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1011,7 +1028,7 @@ endp
|
||||
proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1034,7 +1051,7 @@ endp
|
||||
|
||||
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
|
||||
|
||||
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
|
||||
DEBUGF L_DBG, 'ftdi: deleting device data 0x%x\n', [.device_data]
|
||||
mov esi, [.device_data]
|
||||
mov eax, [esi + ftdi_context.readBufPtr]
|
||||
test eax, eax
|
||||
@@ -1062,7 +1079,7 @@ proc bulk_in_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk in error %x\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: bulk in error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
btr dword [ebx + ftdi_context.writeBufLock], 0
|
||||
@@ -1075,7 +1092,7 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk out error %x\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: bulk out error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
mov ecx, [.length]
|
||||
@@ -1092,18 +1109,18 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
endp
|
||||
|
||||
proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
DEBUGF 1, "ftdi: startup %x %x\n", [data], [conf]
|
||||
DEBUGF L_DBG, "ftdi: startup %x %x\n", [data], [conf]
|
||||
stdcall uart_reconf, [data], [conf]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, "ftdi: uart reconf error %x\n", eax
|
||||
DEBUGF L_ERR, "ftdi: uart reconf error %x\n", eax
|
||||
jmp .exit
|
||||
@@:
|
||||
mov ebx, [data]
|
||||
invoke TimerHS, 2, 2, uart_rx, ebx
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF 2, "ftdi: timer creation error\n"
|
||||
DEBUGF L_ERR, "ftdi: timer creation error\n"
|
||||
or eax, -1
|
||||
jmp .exit
|
||||
@@:
|
||||
@@ -1114,7 +1131,7 @@ proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
endp
|
||||
|
||||
proc uart_shutdown stdcall uses ebx, data:dword
|
||||
DEBUGF 1, "ftdi: shutdown %x\n", [data]
|
||||
DEBUGF L_DBG, "ftdi: shutdown %x\n", [data]
|
||||
mov ebx, [data]
|
||||
cmp [ebx + ftdi_context.rx_timer], 0
|
||||
jz @f
|
||||
@@ -1246,137 +1263,14 @@ proc uart_rx stdcall uses ebx esi, data:dword
|
||||
ret
|
||||
endp
|
||||
|
||||
proc ftdi_set_baudrate stdcall uses ebx, dev:dword, baud:dword
|
||||
proc ftdi_set_baudrate stdcall uses ebx esi, dev:dword, baud:dword
|
||||
locals
|
||||
ConfPacket rb 8
|
||||
endl
|
||||
mov ebx, [dev]
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [baud], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword [baud], H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
mov esi, [baud]
|
||||
call ftdi_calc_baud_divisor
|
||||
|
||||
.c_clk:
|
||||
cmp dword [baud], C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword [baud], H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword [baud], C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword [baud], H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword [baud], C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov word [ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word [ConfPacket + 2], ax
|
||||
@@ -1451,10 +1345,9 @@ uart_drv:
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
serial_drv_entry dd 0
|
||||
include_debug_strings
|
||||
|
||||
data fixups
|
||||
end data
|
||||
|
||||
;for DEBUGF macro
|
||||
include_debug_strings
|
||||
|
||||
serial_drv_entry dd ?
|
||||
@@ -0,0 +1,3 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
ROOT = "../../.."
|
||||
tup.foreach_rule("*.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -79,7 +79,7 @@ macro ADD_CLASS drv_name, class, subclass, protocol {
|
||||
..class_code = ..length or (class shl 8)
|
||||
|
||||
if ..length = 3
|
||||
..class_code = ..class_code or (protocol shl 24)
|
||||
..class_code = ..class_code or (subclass shl 16) or (protocol shl 24)
|
||||
end if
|
||||
if ..length = 2
|
||||
..class_code = ..class_code or (subclass shl 16)
|
||||
@@ -172,7 +172,17 @@ macro ADD_IDL drv_name, [vendor_id, device_id] {
|
||||
|
||||
INIT_USBDRV_FILE
|
||||
|
||||
;ADD_CLASS 'usbcdc-ctrl' , 0x02, X , X
|
||||
; CDC (Communications Device Class): NCM network + ACM serial
|
||||
ADD_CLASS 'usbcdc' , 0x02, X , X
|
||||
|
||||
; RNDIS network (Remote NDIS): LTE modems in HiLink mode, USB tethering.
|
||||
; Three encodings exist: Wireless-Controller/RF/RNDIS, Miscellaneous/
|
||||
; RNDIS-over-Ethernet (phone tethering) and an ACM masquerade (the
|
||||
; latter is declined by usbcdc, so the scan falls through to us).
|
||||
ADD_CLASS 'usbrndis' , 0xE0, 0x01, 0x03
|
||||
ADD_CLASS 'usbrndis' , 0xEF, 0x04, 0x01
|
||||
ADD_CLASS 'usbrndis' , 0x02, 0x02, 0xFF
|
||||
|
||||
;ADD_CLASS 'usbimage' , 0x06, 1 , 1
|
||||
;ADD_CLASS 'usbcdc-data' , 0x0A, X , X
|
||||
;ADD_CLASS 'ccid' , 0x0B, X , X
|
||||
|
||||
+476
-2
@@ -722,6 +722,225 @@ endp
|
||||
; callback inquiry_callback;
|
||||
; * inquiry_callback checks that a logical device is a block device
|
||||
; and the unit was ready; if so, it notifies the kernel about new disk device.
|
||||
; Open the bulk pipes of the Zero-CD device and send the switch message
|
||||
; chosen for it (optionally preceded by an INQUIRY exchange). Used as
|
||||
; the fallback when the device has no MS OS 2.0 alternate enumeration.
|
||||
proc modeswitch_send_cbw
|
||||
push ebx
|
||||
mov ebx, [modeswitch_pipe0]
|
||||
cmp dword [modeswitch_in_ep], 0
|
||||
jz @f
|
||||
invoke USBOpenPipe, ebx, [modeswitch_in_ep], [modeswitch_in_mps], \
|
||||
BULK_PIPE, 0
|
||||
mov [modeswitch_in_pipe], eax
|
||||
@@:
|
||||
invoke USBOpenPipe, ebx, [modeswitch_out_ep], [modeswitch_out_mps], \
|
||||
BULK_PIPE, 0
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [modeswitch_out_pipe], eax
|
||||
; warm up the firmware with an INQUIRY exchange first, if the method
|
||||
; asks for it (and the CSW pipe is available)
|
||||
cmp dword [modeswitch_inq], 0
|
||||
jz .magic
|
||||
cmp dword [modeswitch_in_pipe], 0
|
||||
jz .magic
|
||||
invoke USBNormalTransferAsync, eax, modeswitch_cbw_inq, 31, \
|
||||
modeswitch_inq_cbw_callback, 0, 0
|
||||
DEBUGF 1,'K : modeswitch INQUIRY CBW submitted, handle %x\n', eax
|
||||
test eax, eax
|
||||
jz .fail
|
||||
pop ebx
|
||||
ret
|
||||
.magic:
|
||||
invoke USBNormalTransferAsync, [modeswitch_out_pipe], [modeswitch_msg], 31, \
|
||||
modeswitch_callback, 0, 0
|
||||
DEBUGF 1,'K : modeswitch CBW submitted, handle %x\n', eax
|
||||
test eax, eax
|
||||
jz .fail
|
||||
pop ebx
|
||||
ret
|
||||
.fail:
|
||||
mov dword [modeswitch_pipe0], 0 ; transaction over
|
||||
pop ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; The INQUIRY CBW went out: read the 36 data bytes.
|
||||
proc modeswitch_inq_cbw_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch INQUIRY CBW done, status %d\n', [.status]
|
||||
cmp [.status], 0
|
||||
jne .fail
|
||||
invoke USBNormalTransferAsync, [modeswitch_in_pipe], modeswitch_bos_buf, \
|
||||
36, modeswitch_inq_data_callback, 0, 1
|
||||
test eax, eax
|
||||
jz .fail
|
||||
ret
|
||||
.fail:
|
||||
mov dword [modeswitch_pipe0], 0 ; transaction over
|
||||
ret
|
||||
endp
|
||||
|
||||
; The INQUIRY data arrived: read the CSW.
|
||||
proc modeswitch_inq_data_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch INQUIRY data done, status %d len %d\n', [.status], [.length]
|
||||
invoke USBNormalTransferAsync, [modeswitch_in_pipe], modeswitch_csw, \
|
||||
13, modeswitch_inq_csw_callback, 0, 1
|
||||
test eax, eax
|
||||
jz .fail
|
||||
ret
|
||||
.fail:
|
||||
mov dword [modeswitch_pipe0], 0 ; transaction over
|
||||
ret
|
||||
endp
|
||||
|
||||
; The INQUIRY transaction is complete: now the switch message itself.
|
||||
proc modeswitch_inq_csw_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch INQUIRY CSW done, status %d\n', [.status]
|
||||
invoke USBNormalTransferAsync, [modeswitch_out_pipe], [modeswitch_msg], 31, \
|
||||
modeswitch_callback, 0, 0
|
||||
DEBUGF 1,'K : modeswitch CBW submitted, handle %x\n', eax
|
||||
test eax, eax
|
||||
jz .fail
|
||||
ret
|
||||
.fail:
|
||||
mov dword [modeswitch_pipe0], 0 ; transaction over
|
||||
ret
|
||||
endp
|
||||
|
||||
; The BOS descriptor has been read. If the device carries an
|
||||
; MS OS 2.0 platform capability with a nonzero bAltEnumCode, switch it
|
||||
; the way Windows does: a vendor control request "set alternate
|
||||
; enumeration". Otherwise fall back to the bulk switch message.
|
||||
proc modeswitch_bos_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch BOS done, status %d len %d\n', [.status], [.length]
|
||||
cmp [.status], 0
|
||||
jne .fallback
|
||||
mov ecx, [.length]
|
||||
sub ecx, 8 ; minus the setup packet
|
||||
cmp ecx, 5
|
||||
jb .fallback
|
||||
mov esi, modeswitch_bos_buf
|
||||
cmp byte [esi+1], 0x0F ; BOS descriptor type
|
||||
jne .fallback
|
||||
movzx edx, word [esi+2] ; wTotalLength
|
||||
cmp edx, ecx
|
||||
jbe @f
|
||||
mov edx, ecx ; clamp to what was received
|
||||
@@:
|
||||
add edx, esi ; edx = end of BOS data
|
||||
add esi, 5 ; first device capability
|
||||
.cap_loop:
|
||||
lea eax, [esi+3]
|
||||
cmp eax, edx
|
||||
ja .fallback ; no more capabilities
|
||||
movzx ecx, byte [esi] ; bLength
|
||||
test ecx, ecx
|
||||
jz .fallback
|
||||
cmp byte [esi+1], 0x10 ; DEVICE_CAPABILITY
|
||||
jne .next_cap
|
||||
cmp byte [esi+2], 0x05 ; PLATFORM capability
|
||||
jne .next_cap
|
||||
cmp ecx, 20+8 ; header + GUID + one set info
|
||||
jb .next_cap
|
||||
lea eax, [esi+ecx]
|
||||
cmp eax, edx
|
||||
ja .fallback ; capability sticks out of BOS
|
||||
; is it the MS OS 2.0 platform GUID?
|
||||
push esi edi ecx
|
||||
add esi, 4
|
||||
mov edi, msos20_guid
|
||||
mov ecx, 16
|
||||
repe cmpsb
|
||||
pop ecx edi esi
|
||||
jne .next_cap
|
||||
; walk the descriptor set info structures, take one with bAltEnumCode
|
||||
push ecx
|
||||
sub ecx, 20
|
||||
shr ecx, 3 ; number of 8-byte set infos
|
||||
lea eax, [esi+20]
|
||||
.set_loop:
|
||||
test ecx, ecx
|
||||
jz .no_alt_enum
|
||||
cmp byte [eax+7], 0 ; bAltEnumCode
|
||||
jne .set_found
|
||||
add eax, 8
|
||||
dec ecx
|
||||
jmp .set_loop
|
||||
.set_found:
|
||||
pop ecx
|
||||
mov cl, [eax+6] ; bMS_VendorCode
|
||||
mov [modeswitch_alt_setup+1], cl
|
||||
mov cl, [eax+7] ; bAltEnumCode -> wValue high byte
|
||||
mov [modeswitch_alt_setup+3], cl
|
||||
DEBUGF 1,'K : modeswitch: MS OS 2.0 alt enum supported\n'
|
||||
mov ebx, [.calldata] ; pipe 0
|
||||
invoke USBControlTransferAsync, ebx, modeswitch_alt_setup, 0, 0, \
|
||||
modeswitch_alt_callback, ebx, 0
|
||||
DEBUGF 1,'K : modeswitch SET_ALT_ENUMERATION submit %x\n', eax
|
||||
test eax, eax
|
||||
jz .fallback
|
||||
ret
|
||||
.no_alt_enum:
|
||||
pop ecx
|
||||
jmp .fallback
|
||||
.next_cap:
|
||||
add esi, ecx
|
||||
jmp .cap_loop
|
||||
.fallback:
|
||||
DEBUGF 1,'K : modeswitch: no MS OS 2.0, using bulk message\n'
|
||||
call modeswitch_send_cbw
|
||||
ret
|
||||
endp
|
||||
|
||||
; SET_ALT_ENUMERATION completed: on success the device re-enumerates
|
||||
; by itself; if it stalled the request, try the bulk message instead.
|
||||
proc modeswitch_alt_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch SET_ALT_ENUMERATION done, status %d\n', [.status]
|
||||
cmp [.status], 0
|
||||
je .ret
|
||||
call modeswitch_send_cbw
|
||||
.ret:
|
||||
ret
|
||||
endp
|
||||
|
||||
; The mode-switch CBW has completed. Read the CSW status like
|
||||
; usb_modeswitch does: some firmwares only switch after the host has
|
||||
; completed the whole Bulk-Only transaction.
|
||||
proc modeswitch_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch CBW done, status %d\n', [.status]
|
||||
cmp [.status], 0
|
||||
jne .done
|
||||
mov eax, [modeswitch_in_pipe]
|
||||
test eax, eax
|
||||
jz .done
|
||||
invoke USBNormalTransferAsync, eax, modeswitch_csw, 13, \
|
||||
modeswitch_csw_callback, 0, 1
|
||||
test eax, eax
|
||||
jnz .ret
|
||||
.done:
|
||||
mov dword [modeswitch_pipe0], 0 ; transaction over
|
||||
.ret:
|
||||
ret
|
||||
endp
|
||||
|
||||
; The CSW arrived (or errored); nothing more to do, the device should
|
||||
; drop off the bus and re-enumerate in its real configuration.
|
||||
proc modeswitch_csw_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch CSW done, status %d len %d\n', [.status], [.length]
|
||||
mov dword [modeswitch_pipe0], 0 ; transaction over
|
||||
ret
|
||||
endp
|
||||
|
||||
; SET_FEATURE(1) completed; the device either resets into its real
|
||||
; configuration or (newer firmwares) just resets back into Zero-CD,
|
||||
; which re-triggers the quirk with the next method of the list.
|
||||
proc modeswitch_sf_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
|
||||
DEBUGF 1,'K : modeswitch SET_FEATURE done, status %d\n', [.status]
|
||||
mov dword [modeswitch_pipe0], 0 ; transaction over
|
||||
ret
|
||||
endp
|
||||
|
||||
proc AddDevice
|
||||
push ebx esi
|
||||
virtual at esp
|
||||
@@ -737,6 +956,134 @@ end virtual
|
||||
; bInterfaceProtocol are subsequent in interface_descr, just one
|
||||
; memory reference is used for both.
|
||||
mov esi, [.interface]
|
||||
; Some 3G/LTE modems enumerate as a mass-storage-only "Zero-CD" (a
|
||||
; virtual CD-ROM with Windows drivers) and must be switched to their
|
||||
; real configuration by a magic vendor SCSI command sent to the bulk
|
||||
; OUT endpoint (usb_modeswitch's "HuaweiNewMode"; a SET_FEATURE(1)
|
||||
; only resets these devices back into Zero-CD). Match by VID:PID,
|
||||
; fire the command and do not bind: the device drops off the bus and
|
||||
; re-enumerates with a new PID.
|
||||
mov ebx, [.pipe0]
|
||||
invoke USBGetParam, ebx, 0 ; 0 = get device descriptor
|
||||
test eax, eax
|
||||
jz .no_modeswitch
|
||||
mov ecx, [eax+8] ; idVendor | idProduct shl 16
|
||||
mov edx, modeswitch_ids
|
||||
.modeswitch_scan:
|
||||
cmp dword [edx], 0
|
||||
jz .no_modeswitch
|
||||
cmp ecx, [edx]
|
||||
jz .do_modeswitch
|
||||
add edx, 8
|
||||
jmp .modeswitch_scan
|
||||
.do_modeswitch:
|
||||
; one switch transaction at a time: some Zero-CDs (12d1:14ad) carry TWO
|
||||
; storage interfaces and AddDevice fires for each; a second concurrent
|
||||
; CBW confuses the firmware
|
||||
cmp [modeswitch_pipe0], ebx
|
||||
je .nothing
|
||||
; pick the method: repeated appearances of the same id walk its method
|
||||
; list (wrapping around), a different id starts from the first method
|
||||
cmp ecx, [modeswitch_last_id]
|
||||
je @f
|
||||
mov [modeswitch_last_id], ecx
|
||||
mov dword [modeswitch_attempt], 0
|
||||
jmp .method_select
|
||||
@@:
|
||||
inc [modeswitch_attempt]
|
||||
.method_select:
|
||||
mov eax, [edx+4] ; start of the method list
|
||||
mov ecx, [modeswitch_attempt]
|
||||
.method_walk:
|
||||
cmp dword [eax], -1 ; end of list: wrap around
|
||||
jne @f
|
||||
mov eax, [edx+4]
|
||||
@@:
|
||||
test ecx, ecx
|
||||
jz .method_found
|
||||
add eax, 8
|
||||
dec ecx
|
||||
jmp .method_walk
|
||||
.method_found:
|
||||
mov [modeswitch_pipe0], ebx
|
||||
push esi
|
||||
mov esi, switchdevice
|
||||
invoke SysMsgBoardStr
|
||||
pop esi
|
||||
DEBUGF 1,'K : modeswitch attempt %d, method %d\n', [modeswitch_attempt], [eax]
|
||||
cmp dword [eax], MSW_SET_FEATURE
|
||||
je .method_set_feature
|
||||
xor ecx, ecx
|
||||
cmp dword [eax], MSW_CBW_INQ
|
||||
jne @f
|
||||
inc ecx
|
||||
@@:
|
||||
mov [modeswitch_inq], ecx
|
||||
mov eax, [eax+4] ; the CBW for this attempt
|
||||
mov [modeswitch_msg], eax
|
||||
jmp .method_cbw
|
||||
; SET_FEATURE(1) needs no endpoints: fire the control request and let
|
||||
; the device drop off the bus by itself
|
||||
.method_set_feature:
|
||||
invoke USBControlTransferAsync, ebx, modeswitch_sf_setup, 0, 0, \
|
||||
modeswitch_sf_callback, 0, 0
|
||||
DEBUGF 1,'K : modeswitch SET_FEATURE submit %x\n', eax
|
||||
test eax, eax
|
||||
jnz .nothing
|
||||
mov dword [modeswitch_pipe0], 0
|
||||
jmp .nothing
|
||||
.method_cbw:
|
||||
; collect the bulk IN and bulk OUT endpoints of this interface
|
||||
mov dword [modeswitch_in_pipe], 0
|
||||
mov dword [modeswitch_in_ep], 0
|
||||
mov dword [modeswitch_out_ep], 0
|
||||
mov edx, [.config]
|
||||
movzx ecx, [edx+config_descr.wTotalLength]
|
||||
add edx, ecx ; edx = end of configuration data
|
||||
.modeswitch_ep_scan:
|
||||
movzx ecx, byte [esi] ; bLength
|
||||
test ecx, ecx
|
||||
jz .modeswitch_send ; malformed, use what we have
|
||||
add esi, ecx
|
||||
lea ecx, [esi+sizeof.endpoint_descr]
|
||||
cmp ecx, edx
|
||||
ja .modeswitch_send ; ran out of descriptors
|
||||
cmp byte [esi+1], ENDPOINT_DESCR_TYPE
|
||||
jne .modeswitch_ep_scan
|
||||
mov cl, [esi+endpoint_descr.bmAttributes]
|
||||
and cl, 3
|
||||
cmp cl, BULK_PIPE
|
||||
jne .modeswitch_ep_scan
|
||||
movzx ecx, [esi+endpoint_descr.bEndpointAddress]
|
||||
push edx
|
||||
movzx edx, [esi+endpoint_descr.wMaxPacketSize]
|
||||
and edx, 0xFFF
|
||||
test cl, 80h
|
||||
jz .modeswitch_ep_out
|
||||
mov [modeswitch_in_ep], ecx
|
||||
mov [modeswitch_in_mps], edx
|
||||
pop edx
|
||||
jmp .modeswitch_ep_scan
|
||||
.modeswitch_ep_out:
|
||||
mov [modeswitch_out_ep], ecx
|
||||
mov [modeswitch_out_mps], edx
|
||||
pop edx
|
||||
jmp .modeswitch_ep_scan
|
||||
.modeswitch_send:
|
||||
cmp dword [modeswitch_out_ep], 0
|
||||
jz .nothing ; no bulk OUT: cannot switch
|
||||
mov [modeswitch_pipe0], ebx
|
||||
; try the Windows mechanism first (MS OS 2.0 alternate enumeration,
|
||||
; this is how E3372h switches); its callback falls back to the classic
|
||||
; bulk switch message if the device has no such capability
|
||||
invoke USBControlTransferAsync, ebx, modeswitch_bos_setup, \
|
||||
modeswitch_bos_buf, 256, modeswitch_bos_callback, ebx, 1
|
||||
DEBUGF 1,'K : modeswitch BOS read submit %x\n', eax
|
||||
test eax, eax
|
||||
jnz .nothing
|
||||
call modeswitch_send_cbw ; could not even ask: fall back
|
||||
jmp .nothing
|
||||
.no_modeswitch:
|
||||
xor ebx, ebx
|
||||
mov cx, word [esi+interface_descr.bInterfaceSubClass]
|
||||
; 1b. For Mass-storage SCSI-command-set Bulk-only devices subclass must be 6
|
||||
@@ -991,6 +1338,16 @@ proc inquiry_callback
|
||||
test al, al
|
||||
jnz .nothing
|
||||
DEBUGF 1,'K : direct-access mass storage device detected\n'
|
||||
; Units that report 'medium not present' (the empty card slot of an LTE
|
||||
; modem or card reader) are not registered: the kernel has no media
|
||||
; change detection, so such a disk would only sit dead in the file
|
||||
; managers. Replugging the device after inserting a card registers it.
|
||||
mov edx, [esp+8]
|
||||
cmp [edx+usb_unit_data.MediaPresent], 0
|
||||
jnz @f
|
||||
DEBUGF 1,'K : no media, not registering the disk\n'
|
||||
ret 8
|
||||
@@:
|
||||
; 3. We have found a new disk device. Increment number of references.
|
||||
lock inc [ecx+usb_device_data.NumReferences]
|
||||
; Unfortunately, we are now in the context of the USB thread,
|
||||
@@ -1397,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
|
||||
@@ -1568,6 +1931,117 @@ inquiry_fail db 'K : INQUIRY command failed',13,10,0
|
||||
;read_capacity_fail db 'K : READ CAPACITY command failed',13,10,0
|
||||
;read_fail db 'K : READ command failed',13,10,0
|
||||
noindex db 'K : failed to generate disk name',13,10,0
|
||||
switchdevice db 'K : Zero-CD modem detected, switching mode',13,10,0
|
||||
|
||||
; Zero-CD devices to switch: pairs of (idVendor + idProduct shl 16,
|
||||
; pointer to a method list). Different firmware generations accept
|
||||
; different switch methods and silently ignore (or merely ACK) the
|
||||
; others, and some do not react to the method the usb_modeswitch
|
||||
; database prescribes. So every id gets a LIST of methods and each
|
||||
; (re)appearance of the same id tries the next one, wrapping around.
|
||||
; No timers needed: an unswitched stick resets itself about half a
|
||||
; minute after a swallowed command (observed on K3806), and the user
|
||||
; can always just replug.
|
||||
MSW_CBW = 0 ; method: bulk message, param = CBW ptr
|
||||
MSW_SET_FEATURE = 1 ; method: SET_FEATURE(1) control request
|
||||
MSW_CBW_INQ = 2 ; method: INQUIRY exchange, then the CBW;
|
||||
; some firmwares accept the switch only
|
||||
; after normal SCSI traffic (on Linux and
|
||||
; Windows the storage driver reads the
|
||||
; virtual CD before any switch tool runs)
|
||||
|
||||
align 4
|
||||
modeswitch_ids dd 0x1F0112D1, modeswitch_list_1f01 ; Huawei E3372 etc
|
||||
dd 0x14AD12D1, modeswitch_list_14ad ; Vodafone K3806
|
||||
dd 0
|
||||
|
||||
; E3372h-153: the 10-byte command is the only one this firmware
|
||||
; reacts to (verified on hardware; SET_FEATURE only resets it)
|
||||
modeswitch_list_1f01:
|
||||
dd MSW_CBW, modeswitch_cbw_new
|
||||
dd -1
|
||||
; K3806: the plain usb_modeswitch message (classic Huawei), the eject
|
||||
; and the E3372 message are all ACKed but ignored, SET_FEATURE stalls
|
||||
; (verified on hardware) - so lead with INQUIRY+message
|
||||
modeswitch_list_14ad:
|
||||
dd MSW_CBW_INQ, modeswitch_cbw_old
|
||||
dd MSW_SET_FEATURE, 0
|
||||
dd MSW_CBW, modeswitch_cbw_eject
|
||||
dd MSW_CBW, modeswitch_cbw_new
|
||||
dd MSW_CBW, modeswitch_cbw_old
|
||||
dd -1
|
||||
; usb_modeswitch's message for the 1F01 Zero-CD family: a CBW with the
|
||||
; 10-byte vendor command 11 06 20 00 00 00 00 00 01 00 (note the 01 in
|
||||
; byte 8; the older 6-byte 11 06 20 00 00 01 variant is ignored by
|
||||
; E3372h firmwares) and no data stage
|
||||
modeswitch_cbw_new:
|
||||
db 'USBC' ; dCBWSignature
|
||||
dd 0x12345678 ; dCBWTag
|
||||
dd 0 ; dCBWDataTransferLength
|
||||
db 0 ; bmCBWFlags
|
||||
db 0 ; bCBWLUN
|
||||
db 10 ; bCBWCBLength
|
||||
db 0x11, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
|
||||
db 0, 0, 0, 0, 0, 0
|
||||
; the classic Huawei message for older sticks (usb_modeswitch 12d1:14ad
|
||||
; etc): the 6-byte vendor command 11 06 20 00 00 01, byte-for-byte as
|
||||
; usb_modeswitch sends it (bCBWCBLength is 0 in the original message)
|
||||
modeswitch_cbw_old:
|
||||
db 'USBC' ; dCBWSignature
|
||||
dd 0x12345678 ; dCBWTag
|
||||
dd 0 ; dCBWDataTransferLength
|
||||
db 0 ; bmCBWFlags
|
||||
db 0 ; bCBWLUN
|
||||
db 0 ; bCBWCBLength
|
||||
db 0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
|
||||
db 0, 0, 0, 0, 0, 0
|
||||
; the standard eject (START STOP UNIT with LoEj|Stop): the generic
|
||||
; Zero-CD switch used by many non-Huawei sticks
|
||||
modeswitch_cbw_eject:
|
||||
db 'USBC' ; dCBWSignature
|
||||
dd 0x12345678 ; dCBWTag
|
||||
dd 0 ; dCBWDataTransferLength
|
||||
db 0 ; bmCBWFlags
|
||||
db 0 ; bCBWLUN
|
||||
db 6 ; bCBWCBLength
|
||||
db 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
db 0, 0, 0, 0, 0, 0
|
||||
; SET_FEATURE(1) to the device: the switch of the oldest Huawei sticks
|
||||
modeswitch_sf_setup db 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
; standard INQUIRY (36 bytes of data IN), the warm-up for MSW_CBW_INQ
|
||||
modeswitch_cbw_inq:
|
||||
db 'USBC' ; dCBWSignature
|
||||
dd 0x12345678 ; dCBWTag
|
||||
dd 36 ; dCBWDataTransferLength
|
||||
db 0x80 ; bmCBWFlags: data IN
|
||||
db 0 ; bCBWLUN
|
||||
db 6 ; bCBWCBLength
|
||||
db 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
db 0, 0, 0, 0, 0, 0
|
||||
; scratch state of the mode-switch transaction
|
||||
modeswitch_pipe0 dd 0 ; config pipe of the device
|
||||
; (nonzero = transaction running)
|
||||
modeswitch_msg dd 0 ; the CBW chosen for this device
|
||||
modeswitch_inq dd 0 ; run an INQUIRY before the CBW
|
||||
modeswitch_out_pipe dd 0 ; bulk OUT pipe handle
|
||||
modeswitch_last_id dd 0 ; VID:PID of the last attempt
|
||||
modeswitch_attempt dd 0 ; method index for that id
|
||||
modeswitch_in_pipe dd 0 ; bulk IN pipe handle (for the CSW)
|
||||
modeswitch_in_ep dd 0
|
||||
modeswitch_in_mps dd 0
|
||||
modeswitch_out_ep dd 0
|
||||
modeswitch_out_mps dd 0
|
||||
; GET_DESCRIPTOR(BOS), up to 256 bytes
|
||||
modeswitch_bos_setup db 0x80, 0x06, 0x00, 0x0F, 0x00, 0x00
|
||||
dw 256
|
||||
; MS OS 2.0 "set alternate enumeration": vendor request to the device,
|
||||
; bRequest (+1) and wValue high byte (+3) are patched in at runtime
|
||||
modeswitch_alt_setup db 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
|
||||
; platform capability GUID of MS OS 2.0: D8DD60DF-4589-4CC7-9CD2-659D9E648A9F
|
||||
msos20_guid db 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C
|
||||
db 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F
|
||||
modeswitch_csw rb 16 ; CSW receive buffer
|
||||
modeswitch_bos_buf rb 256 ; BOS descriptor buffer
|
||||
|
||||
align 4
|
||||
; Structure with callback functions.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
ROOT = "../../.."
|
||||
tup.rule("xhci.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,993 @@
|
||||
; Device slots, contexts and pipes for the xHCI driver.
|
||||
; This file is included from xhci.asm.
|
||||
|
||||
; =============================================================================
|
||||
; ============================ Context helpers ================================
|
||||
; =============================================================================
|
||||
|
||||
; Returns the address of one context inside a context structure.
|
||||
; in: eax = base of the structure, ecx = index of the context,
|
||||
; esi -> usb_controller.
|
||||
; out: eax = address of the context.
|
||||
proc xhci_context
|
||||
push ecx edx
|
||||
mov edx, [esi+xhci_controller.ContextSize-XCD]
|
||||
imul edx, ecx
|
||||
add eax, edx
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Zeroes the Input Context. The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller.
|
||||
proc xhci_clear_input_ctx
|
||||
push eax ecx edi
|
||||
mov edi, [esi+xhci_controller.InputCtx-XCD]
|
||||
xor eax, eax
|
||||
mov ecx, 33*64/4
|
||||
rep stosd
|
||||
pop edi ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Returns the pipe of the default control endpoint of the same device, which
|
||||
; represents the device as a whole.
|
||||
; in: ebx -> xhci_pipe. out: eax -> xhci_pipe or 0.
|
||||
proc xhci_ctrl_pipe
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov eax, [eax+XHCI_PIPES_OFS+1*4]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
sub eax, sizeof.xhci_pipe
|
||||
.nothing:
|
||||
ret
|
||||
endp
|
||||
|
||||
; Fills the Slot Context of the Input Context from the device description kept
|
||||
; in a pipe. The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe describing the device,
|
||||
; ecx = value for the Context Entries field.
|
||||
proc xhci_fill_slot_ctx
|
||||
push eax ecx edx edi
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
push ecx
|
||||
movi ecx, 1
|
||||
call xhci_context
|
||||
pop ecx
|
||||
mov edi, eax
|
||||
; dword 0: Route String, Speed and Context Entries.
|
||||
mov eax, [ebx+xhci_pipe.Route]
|
||||
and eax, 0FFFFFh
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed root-port device carries the raw PORTSC speed identifier;
|
||||
; its kernel-visible Speed pretends high-speed and must not get here.
|
||||
mov edx, [ebx+xhci_pipe.PSIV]
|
||||
test edx, edx
|
||||
jnz .havespeed
|
||||
end if
|
||||
mov edx, [ebx+xhci_pipe.Speed]
|
||||
cmp edx, USB_SPEED_FS
|
||||
jz .fs
|
||||
cmp edx, USB_SPEED_LS
|
||||
jz .ls
|
||||
movi edx, XHCI_PSI_HS
|
||||
jmp .havespeed
|
||||
.fs:
|
||||
movi edx, XHCI_PSI_FS
|
||||
jmp .havespeed
|
||||
.ls:
|
||||
movi edx, XHCI_PSI_LS
|
||||
.havespeed:
|
||||
shl edx, 20
|
||||
or eax, edx
|
||||
shl ecx, 27
|
||||
or eax, ecx
|
||||
mov [edi], eax
|
||||
; dword 1: Root Hub Port Number.
|
||||
mov eax, [ebx+xhci_pipe.RootPort]
|
||||
shl eax, 16
|
||||
mov [edi+4], eax
|
||||
; dword 2: the Transaction Translator, if the device is served by one.
|
||||
mov eax, [ebx+xhci_pipe.TTSlot]
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov edx, [ebx+xhci_pipe.TTPort]
|
||||
shl edx, 8
|
||||
or eax, edx
|
||||
@@:
|
||||
mov [edi+8], eax
|
||||
and dword [edi+12], 0
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Fills the Endpoint Context of the Input Context for the given pipe.
|
||||
; The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe.
|
||||
proc xhci_fill_ep_ctx
|
||||
push eax ecx edx edi
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
inc ecx
|
||||
call xhci_context
|
||||
mov edi, eax
|
||||
; dword 0: Interval.
|
||||
mov eax, [ebx+xhci_pipe.Interval]
|
||||
shl eax, 16
|
||||
mov [edi], eax
|
||||
; dword 1: Error Count, Endpoint Type, Max Burst Size and Max Packet Size.
|
||||
mov eax, [ebx+xhci_pipe.EpType]
|
||||
shl eax, 3
|
||||
or eax, 3 shl 1 ; three retries before giving up
|
||||
mov edx, [ebx+xhci_pipe.MaxPacket]
|
||||
mov ecx, edx
|
||||
shr ecx, 11
|
||||
and ecx, 3 ; extra transactions per microframe
|
||||
shl ecx, 8
|
||||
or eax, ecx
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed bulk endpoint may allow bursts of several packets; the field
|
||||
; shares its bits with the extra-transactions ones, which are zero then.
|
||||
mov ecx, [ebx+xhci_pipe.MaxBurst]
|
||||
shl ecx, 8
|
||||
or eax, ecx
|
||||
end if
|
||||
and edx, 7FFh
|
||||
shl edx, 16
|
||||
or eax, edx
|
||||
mov [edi+4], eax
|
||||
; dwords 2 and 3: the TR Dequeue Pointer with the Dequeue Cycle State.
|
||||
mov eax, [ebx+xhci_pipe.Enqueue]
|
||||
shl eax, 4
|
||||
add eax, [ebx+xhci_pipe.RingPhys]
|
||||
or eax, [ebx+xhci_pipe.Cycle]
|
||||
mov [edi+8], eax
|
||||
and dword [edi+12], 0
|
||||
; dword 4: Average TRB Length, only a hint for the bandwidth scheduler.
|
||||
mov eax, [ebx+xhci_pipe.MaxPacket]
|
||||
and eax, 7FFh
|
||||
cmp [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
jnz @f
|
||||
movi eax, 8
|
||||
@@:
|
||||
mov [edi+16], eax
|
||||
and dword [edi+20], 0
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ============================== Slot commands ================================
|
||||
; =============================================================================
|
||||
|
||||
; Issues the Address Device command for a newly created default control pipe.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe. out: eax = 0 on failure.
|
||||
proc xhci_address_device
|
||||
push ebx ecx edx edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [edx+4], 3 ; add the Slot Context and endpoint zero
|
||||
movi ecx, 1
|
||||
call xhci_fill_slot_ctx
|
||||
call xhci_fill_ep_ctx
|
||||
mov [ebx+xhci_pipe.MaxDCI], 1
|
||||
; Point the DCBAA entry of the slot at the Device Context.
|
||||
mov eax, [esi+xhci_controller.CommonPage-XCD]
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edx, [ebx+xhci_pipe.DevPagePhys]
|
||||
mov [eax+ecx*8], edx
|
||||
and dword [eax+ecx*8+4], 0
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_ADDRESS_DEV shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
push eax
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .ok
|
||||
DEBUGF 1,'K : XHCI: Address Device failed, code %d\n',eax
|
||||
xor eax, eax
|
||||
jmp .nothing
|
||||
.ok:
|
||||
movi eax, 1
|
||||
.nothing:
|
||||
pop edi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Issues a Configure Endpoint command that adds the given endpoint.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe of the endpoint,
|
||||
; edi -> xhci_pipe of the default control endpoint of the same device.
|
||||
; out: eax = completion code.
|
||||
proc xhci_configure_endpoint
|
||||
push ebx ecx edx esi edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
; Drop the endpoint and add it again, so that reopening an endpoint that has
|
||||
; been closed before also works.
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
movi eax, 1
|
||||
shl eax, cl
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov [edx], eax
|
||||
or eax, 1 ; the Slot Context is always added
|
||||
mov [edx+4], eax
|
||||
call xhci_fill_ep_ctx
|
||||
; The Context Entries field must cover every endpoint in use by the device.
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, [edi+xhci_pipe.MaxDCI]
|
||||
jae @f
|
||||
mov ecx, [edi+xhci_pipe.MaxDCI]
|
||||
@@:
|
||||
mov [edi+xhci_pipe.MaxDCI], ecx
|
||||
push ebx
|
||||
mov ebx, edi
|
||||
call xhci_fill_slot_ctx
|
||||
pop ebx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
push eax
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
pop edi esi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Tells the controller where the endpoint has to continue from.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe.
|
||||
proc xhci_set_dequeue
|
||||
pushad
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
mov eax, [ebx+xhci_pipe.Dequeue]
|
||||
shl eax, 4
|
||||
add eax, [ebx+xhci_pipe.RingPhys]
|
||||
or eax, [ebx+xhci_pipe.Cycle]
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
shl ecx, 16
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, ecx
|
||||
or edx, XHCI_TRB_SET_DEQ shl 10
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .nothing
|
||||
DEBUGF 1,'K : XHCI: Set TR Dequeue Pointer failed, code %d\n',eax
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; =============================== New device ==================================
|
||||
; =============================================================================
|
||||
|
||||
; Called from xhci_port_init and from the hub support code when a new device
|
||||
; has been connected and reset. Enables a device slot for it and hands it over
|
||||
; to the protocol layer.
|
||||
; in: esi -> usb_controller, eax = speed. out: eax = 0 on failure.
|
||||
proc xhci_new_device
|
||||
push ebx ecx edx edi
|
||||
mov [esi+usb_controller.ResettingSpeed], al
|
||||
; 1. Reserve room for the pseudo-pipe that describes the new device. Only the
|
||||
; fields read by xhci_init_pipe are filled in; the layout matches a real pipe,
|
||||
; so the result can be passed to usb_new_device as a usb_pipe pointer.
|
||||
sub esp, sizeof.xhci_pipe + 4
|
||||
mov ebx, esp
|
||||
push ebx
|
||||
mov edi, ebx
|
||||
xor eax, eax
|
||||
mov ecx, (sizeof.xhci_pipe + 4)/4
|
||||
rep stosd
|
||||
pop ebx
|
||||
mov [ebx+sizeof.xhci_pipe], esi ; usb_pipe.Controller
|
||||
movzx eax, [esi+usb_controller.ResettingSpeed]
|
||||
mov [ebx+xhci_pipe.Speed], eax
|
||||
; 2. Compute the root hub port, the route string and the tier of the device.
|
||||
movzx edx, [esi+usb_controller.ResettingPort]
|
||||
mov edi, [esi+usb_controller.ResettingHub]
|
||||
test edi, edi
|
||||
jnz .behind_hub
|
||||
mov eax, [esi+xhci_controller.PortMap-XCD+edx*4]
|
||||
mov [ebx+xhci_pipe.RootPort], eax
|
||||
if XHCI_SUPERSPEED
|
||||
mov eax, [esi+xhci_controller.ResettingPSIV-XCD]
|
||||
mov [ebx+xhci_pipe.PSIV], eax
|
||||
end if
|
||||
jmp .have_topology
|
||||
.behind_hub:
|
||||
; The parent hub is a device too, and its own pipe carries the topology data.
|
||||
mov eax, [edi+USB_HUB_CONFIGPIPE]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
mov ecx, [eax+xhci_pipe.RootPort]
|
||||
mov [ebx+xhci_pipe.RootPort], ecx
|
||||
mov ecx, [eax+xhci_pipe.Depth]
|
||||
mov eax, [eax+xhci_pipe.Route]
|
||||
; The route string holds one nibble per tier, at most five of them.
|
||||
cmp ecx, 5
|
||||
jae .have_route
|
||||
push ecx edx
|
||||
shl ecx, 2
|
||||
inc edx ; the route uses 1-based port numbers
|
||||
cmp edx, 15
|
||||
jbe @f
|
||||
movi edx, 15
|
||||
@@:
|
||||
shl edx, cl
|
||||
or eax, edx
|
||||
pop edx ecx
|
||||
.have_route:
|
||||
inc ecx
|
||||
mov [ebx+xhci_pipe.Depth], ecx
|
||||
mov [ebx+xhci_pipe.Route], eax
|
||||
; 3. Low- and full-speed devices behind a high-speed hub need the address of
|
||||
; the Transaction Translator that serves them.
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jz .have_topology
|
||||
push ebx
|
||||
mov ecx, edx
|
||||
mov edx, edi
|
||||
invoke usbhc_api.usb_get_tt
|
||||
pop ebx
|
||||
test edx, edx
|
||||
jz .have_topology
|
||||
sub edx, sizeof.xhci_pipe
|
||||
mov eax, [edx+xhci_pipe.SlotId]
|
||||
mov [ebx+xhci_pipe.TTSlot], eax
|
||||
inc ecx
|
||||
mov [ebx+xhci_pipe.TTPort], ecx
|
||||
.have_topology:
|
||||
; 4. Ask the controller for a device slot.
|
||||
xor eax, eax
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
mov edx, XHCI_TRB_ENABLE_SLOT shl 10
|
||||
call xhci_cmd_sync
|
||||
pop ebx
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jnz .fail
|
||||
test edx, edx
|
||||
jz .fail
|
||||
mov [ebx+xhci_pipe.SlotId], edx
|
||||
DEBUGF 1,'K : XHCI new device: slot %d, root port %d, route %x, speed %d\n',edx,[ebx+xhci_pipe.RootPort],[ebx+xhci_pipe.Route],[ebx+xhci_pipe.Speed]
|
||||
; 5. Hand the device over to the protocol layer. It opens the pipe of the
|
||||
; default control endpoint, and that is where the slot is really addressed.
|
||||
lea ecx, [ebx+sizeof.xhci_pipe]
|
||||
invoke usbhc_api.usb_new_device
|
||||
test eax, eax
|
||||
jnz .done
|
||||
; 6. The protocol layer has failed; release the slot again.
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_DISABLE_SLOT shl 10
|
||||
xor eax, eax
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
xor eax, eax
|
||||
jmp .done
|
||||
.fail:
|
||||
dbgstr 'XHCI: Enable Slot failed'
|
||||
xor eax, eax
|
||||
.done:
|
||||
add esp, sizeof.xhci_pipe + 4
|
||||
pop edi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ================================= Pipes =====================================
|
||||
; =============================================================================
|
||||
|
||||
proc xhci_alloc_pipe
|
||||
push ebx ecx edi
|
||||
mov ebx, xhci_ep_mutex
|
||||
invoke usbhc_api.usb_allocate_common, sizeof.xhci_pipe + sizeof.usb_pipe
|
||||
test eax, eax
|
||||
jz @f
|
||||
; Zero the whole block: the kernel may call FreePipe for a pipe whose InitPipe
|
||||
; has never run, and that path must not act on garbage.
|
||||
mov edi, eax
|
||||
push eax
|
||||
xor eax, eax
|
||||
movi ecx, (sizeof.xhci_pipe + sizeof.usb_pipe + 3)/4
|
||||
rep stosd
|
||||
pop eax
|
||||
add eax, sizeof.xhci_pipe
|
||||
@@:
|
||||
pop edi ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
proc xhci_free_pipe stdcall, ptr:dword
|
||||
push ebx esi edi
|
||||
mov ebx, [ptr]
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
mov esi, [ebx+sizeof.xhci_pipe+usb_pipe.Controller]
|
||||
test esi, esi
|
||||
jz .free
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .drop_pipe
|
||||
cmp [ebx+xhci_pipe.DCI], 1
|
||||
jnz .drop_pipe
|
||||
; This is the default control endpoint, that is, the handle of the whole
|
||||
; device: release the slot together with the per-device page.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edx, ecx
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_DISABLE_SLOT shl 10
|
||||
xor eax, eax
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
pop ebx
|
||||
; The controller may access the Device Context until the command above
|
||||
; completes, so only now may the DCBAA entry and the slot table forget it.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edi, [esi+xhci_controller.CommonPage-XCD]
|
||||
and dword [edi+ecx*8], 0
|
||||
and dword [edi+ecx*8+4], 0
|
||||
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz .drop_ring
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.DevPage], 0
|
||||
jmp .drop_ring
|
||||
.drop_pipe:
|
||||
; Remove the pipe from the per-device table, if it is still listed there.
|
||||
; On disconnect the kernel releases the pipes of a device in arbitrary order,
|
||||
; and the pipe of the default control endpoint - the owner of the per-device
|
||||
; page - may well be freed before this one, taking the page with it. The
|
||||
; authoritative pointer is the one in SlotPages: it is cleared when the slot
|
||||
; is released, so it can never point to freed memory.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
test ecx, ecx
|
||||
jz .drop_ring
|
||||
mov eax, [esi+xhci_controller.SlotPages-XCD+ecx*4]
|
||||
test eax, eax
|
||||
jz .drop_ring
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, 32
|
||||
jae .drop_ring
|
||||
and dword [eax+XHCI_PIPES_OFS+ecx*4], 0
|
||||
.drop_ring:
|
||||
mov eax, [ebx+xhci_pipe.Ring]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.Ring], 0
|
||||
@@:
|
||||
mov eax, [ebx+xhci_pipe.RingMap]
|
||||
test eax, eax
|
||||
jz .free
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.RingMap], 0
|
||||
.free:
|
||||
pop edi esi ebx
|
||||
mov eax, [ptr]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
invoke usbhc_api.usb_free_common, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Allocates the transfer ring of a pipe.
|
||||
; in: ebx -> xhci_pipe. out: eax = 0 on failure.
|
||||
proc xhci_alloc_ring
|
||||
push ecx edx
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov [ebx+xhci_pipe.RingMap], eax
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jnz @f
|
||||
invoke KernelFree, [ebx+xhci_pipe.RingMap]
|
||||
and [ebx+xhci_pipe.RingMap], 0
|
||||
xor eax, eax
|
||||
jmp .nothing
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.Ring], eax
|
||||
mov [ebx+xhci_pipe.RingPhys], edx
|
||||
; The last entry returns to the beginning of the ring and toggles the cycle.
|
||||
lea ecx, [eax+(XHCI_RING_TRBS-1)*16]
|
||||
mov [ecx], edx
|
||||
mov dword [ecx+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
|
||||
and [ebx+xhci_pipe.Enqueue], 0
|
||||
and [ebx+xhci_pipe.Dequeue], 0
|
||||
and [ebx+xhci_pipe.Reserved], 0
|
||||
and [ebx+xhci_pipe.FirstFix], 0
|
||||
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
|
||||
movi eax, 1
|
||||
.nothing:
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Stores the pipe in the per-device table used by the event ring handler.
|
||||
; in: ebx -> xhci_pipe.
|
||||
proc xhci_register_pipe
|
||||
push eax ecx edx
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, 32
|
||||
jae @f
|
||||
lea edx, [ebx+sizeof.xhci_pipe]
|
||||
mov [eax+XHCI_PIPES_OFS+ecx*4], edx
|
||||
@@:
|
||||
pop edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Computes the Interval field of the Endpoint Context of an interrupt endpoint.
|
||||
; The kernel passes bInterval from the endpoint descriptor: for high-speed
|
||||
; devices it is an exponent of 125 us periods, for low- and full-speed devices
|
||||
; it is a number of frames.
|
||||
; in: ebx -> xhci_pipe, eax = bInterval.
|
||||
proc xhci_calc_interval
|
||||
push eax ecx
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jnz .low_speed
|
||||
test eax, eax
|
||||
jz @f
|
||||
dec eax
|
||||
@@:
|
||||
jmp .clamp
|
||||
.low_speed:
|
||||
; One frame equals eight periods of 125 us, hence the offset of three.
|
||||
test eax, eax
|
||||
jnz @f
|
||||
movi eax, 1
|
||||
@@:
|
||||
bsr ecx, eax
|
||||
lea eax, [ecx+3]
|
||||
.clamp:
|
||||
cmp eax, 15
|
||||
jbe @f
|
||||
movi eax, 15
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.Interval], eax
|
||||
pop ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Called from usb_open_pipe.
|
||||
; in: edi -> usb_pipe for the target, ecx -> usb_pipe of the config pipe,
|
||||
; esi -> usb_controller, eax -> usb_gtd of the first descriptor,
|
||||
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type,
|
||||
; [ebp+24] = interval.
|
||||
; out: eax = 0 on failure.
|
||||
proc xhci_init_pipe
|
||||
virtual at ebp+8
|
||||
.config_pipe dd ?
|
||||
.endpoint dd ?
|
||||
.maxpacket dd ?
|
||||
.type dd ?
|
||||
.interval dd ?
|
||||
end virtual
|
||||
push ebx
|
||||
sub edi, sizeof.xhci_pipe
|
||||
sub ecx, sizeof.xhci_pipe
|
||||
mov ebx, edi ; ebx -> xhci_pipe being initialized
|
||||
; 1. Copy the description of the device from the config pipe.
|
||||
mov eax, [ecx+xhci_pipe.SlotId]
|
||||
mov [ebx+xhci_pipe.SlotId], eax
|
||||
mov eax, [ecx+xhci_pipe.DevPage]
|
||||
mov [ebx+xhci_pipe.DevPage], eax
|
||||
mov eax, [ecx+xhci_pipe.DevPagePhys]
|
||||
mov [ebx+xhci_pipe.DevPagePhys], eax
|
||||
mov eax, [ecx+xhci_pipe.Speed]
|
||||
mov [ebx+xhci_pipe.Speed], eax
|
||||
mov eax, [ecx+xhci_pipe.RootPort]
|
||||
mov [ebx+xhci_pipe.RootPort], eax
|
||||
mov eax, [ecx+xhci_pipe.Route]
|
||||
mov [ebx+xhci_pipe.Route], eax
|
||||
mov eax, [ecx+xhci_pipe.Depth]
|
||||
mov [ebx+xhci_pipe.Depth], eax
|
||||
mov eax, [ecx+xhci_pipe.TTSlot]
|
||||
mov [ebx+xhci_pipe.TTSlot], eax
|
||||
mov eax, [ecx+xhci_pipe.TTPort]
|
||||
mov [ebx+xhci_pipe.TTPort], eax
|
||||
if XHCI_SUPERSPEED
|
||||
mov eax, [ecx+xhci_pipe.PSIV]
|
||||
mov [ebx+xhci_pipe.PSIV], eax
|
||||
end if
|
||||
; 2. Work out the Device Context Index and the endpoint type.
|
||||
mov eax, [.endpoint]
|
||||
test eax, eax
|
||||
jz .control_ep
|
||||
mov ecx, eax
|
||||
and ecx, 15
|
||||
add ecx, ecx
|
||||
test al, 80h
|
||||
jz @f
|
||||
inc ecx
|
||||
or [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.DCI], ecx
|
||||
mov eax, [.type]
|
||||
cmp eax, BULK_PIPE
|
||||
jz .bulk
|
||||
cmp eax, INTERRUPT_PIPE
|
||||
jz .interrupt
|
||||
; A control endpoint other than endpoint zero is unusual but legal.
|
||||
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
jmp .have_type
|
||||
.bulk:
|
||||
movi eax, XHCI_EP_BULK_OUT
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
movi eax, XHCI_EP_BULK_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.EpType], eax
|
||||
jmp .have_type
|
||||
.interrupt:
|
||||
movi eax, XHCI_EP_INT_OUT
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
movi eax, XHCI_EP_INT_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.EpType], eax
|
||||
mov eax, [.interval]
|
||||
call xhci_calc_interval
|
||||
.have_type:
|
||||
mov eax, [.maxpacket]
|
||||
mov [ebx+xhci_pipe.MaxPacket], eax
|
||||
if XHCI_SUPERSPEED
|
||||
call xhci_ss_get_burst
|
||||
end if
|
||||
jmp .alloc_ring
|
||||
.control_ep:
|
||||
; The default control endpoint always has index one. Until the real packet size
|
||||
; is known from the device descriptor, use the value the specification requires
|
||||
; for the speed of the device: the kernel asks for 64 regardless of the speed,
|
||||
; which is wrong for low- and full-speed devices.
|
||||
mov [ebx+xhci_pipe.DCI], 1
|
||||
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
movi eax, 64
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jz @f
|
||||
movi eax, 8
|
||||
@@:
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed device always uses 512 bytes on the default control endpoint.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb @f
|
||||
mov eax, 512
|
||||
@@:
|
||||
end if
|
||||
mov [ebx+xhci_pipe.MaxPacket], eax
|
||||
.alloc_ring:
|
||||
; 3. Allocate the transfer ring.
|
||||
call xhci_alloc_ring
|
||||
test eax, eax
|
||||
jz .fail
|
||||
; 4. Choose the software list the pipe belongs to and insert it there. The
|
||||
; hardware knows nothing about these lists; they exist only so that the kernel
|
||||
; can walk all pipes and reinsert an aborted one.
|
||||
lea edx, [esi+xhci_controller.ControlED-XCD]
|
||||
cmp [.type], BULK_PIPE
|
||||
jb @f
|
||||
lea edx, [esi+xhci_controller.BulkED-XCD]
|
||||
jz @f
|
||||
lea edx, [esi+xhci_controller.IntED-XCD]
|
||||
@@:
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
mov [edi+usb_pipe.BaseList], edx
|
||||
mov ecx, [edx+usb_pipe.NextVirt]
|
||||
mov [edi+usb_pipe.NextVirt], ecx
|
||||
mov [edi+usb_pipe.PrevVirt], edx
|
||||
mov [ecx+usb_pipe.PrevVirt], edi
|
||||
mov [edx+usb_pipe.NextVirt], edi
|
||||
; 5. Now do the hardware part.
|
||||
cmp [.endpoint], 0
|
||||
jz .address_device
|
||||
call xhci_register_pipe
|
||||
mov edi, [.config_pipe]
|
||||
sub edi, sizeof.xhci_pipe
|
||||
call xhci_configure_endpoint
|
||||
xhci_trace 'K : XHCI open pipe: slot %d dci %d\n', [ebx+xhci_pipe.SlotId], [ebx+xhci_pipe.DCI]
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .success
|
||||
DEBUGF 1,'K : XHCI: Configure Endpoint failed, code %d\n',eax
|
||||
jmp .unlink_fail
|
||||
.address_device:
|
||||
; 6. This is a new device: allocate its Device Context, publish the slot and
|
||||
; let the controller give the device a bus address.
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jz .unlink_fail
|
||||
mov [ebx+xhci_pipe.DevPage], eax
|
||||
mov [ebx+xhci_pipe.DevPagePhys], edx
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov [esi+xhci_controller.SlotPages-XCD+ecx*4], eax
|
||||
call xhci_register_pipe
|
||||
call xhci_address_device
|
||||
test eax, eax
|
||||
jz .free_devpage
|
||||
.success:
|
||||
; usb_open_pipe keeps the pointer to the new pipe in edi across this call, so
|
||||
; it has to be handed back untouched; the branch above has overwritten it with
|
||||
; the pipe of the default control endpoint.
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
pop ebx
|
||||
movi eax, 1
|
||||
ret
|
||||
.free_devpage:
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.DevPage], 0
|
||||
.unlink_fail:
|
||||
; Undo the insertion into the software list before failing.
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
mov eax, [edi+usb_pipe.NextVirt]
|
||||
mov edx, [edi+usb_pipe.PrevVirt]
|
||||
mov [eax+usb_pipe.PrevVirt], edx
|
||||
mov [edx+usb_pipe.NextVirt], eax
|
||||
.fail:
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
pop ebx
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Removes the pipe from the hardware configuration of the device.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe.
|
||||
proc xhci_unlink_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
cmp [ebx+xhci_pipe.DCI], 1
|
||||
jz .nothing ; the slot itself is released by FreePipe
|
||||
call xhci_ctrl_pipe
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov edi, eax ; edi -> pipe of endpoint zero
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
movi eax, 1
|
||||
shl eax, cl
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov [edx], eax ; drop this endpoint
|
||||
mov dword [edx+4], 1 ; keep the Slot Context
|
||||
mov ecx, [edi+xhci_pipe.MaxDCI]
|
||||
test ecx, ecx
|
||||
jnz @f
|
||||
movi ecx, 1
|
||||
@@:
|
||||
push ebx
|
||||
mov ebx, edi
|
||||
call xhci_fill_slot_ctx
|
||||
pop ebx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; Temporarily removes the pipe from the hardware schedule.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe.
|
||||
proc xhci_disable_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
shl ecx, 16
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, ecx
|
||||
or edx, XHCI_TRB_STOP_EP shl 10
|
||||
xor eax, eax
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; Reinserts the pipe into the hardware schedule after xhci_disable_pipe, with
|
||||
; an empty transfer queue.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe,
|
||||
; edx -> current descriptor, eax -> new last descriptor.
|
||||
proc xhci_enable_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
mov eax, [ebx+xhci_pipe.Ring]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
; The queue is empty now, so the ring can be restarted from its beginning.
|
||||
mov edi, eax
|
||||
xor eax, eax
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
mov edi, [ebx+xhci_pipe.RingMap]
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
mov edi, [ebx+xhci_pipe.Ring]
|
||||
add edi, (XHCI_RING_TRBS-1)*16
|
||||
mov eax, [ebx+xhci_pipe.RingPhys]
|
||||
mov [edi], eax
|
||||
mov dword [edi+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
|
||||
and [ebx+xhci_pipe.Enqueue], 0
|
||||
and [ebx+xhci_pipe.Dequeue], 0
|
||||
and [ebx+xhci_pipe.Reserved], 0
|
||||
and [ebx+xhci_pipe.FirstFix], 0
|
||||
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
|
||||
call xhci_set_dequeue
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ========================== Address and packet size ==========================
|
||||
; =============================================================================
|
||||
|
||||
; Called from usb_set_address_callback. The bus address is chosen by the
|
||||
; controller itself while executing the Address Device command, so the only
|
||||
; thing left to do is to remember the number the kernel has reserved: it asks
|
||||
; for it back on disconnect in order to mark it free again.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address.
|
||||
proc xhci_set_device_address
|
||||
movzx eax, cl
|
||||
mov [ebx+xhci_pipe.Address-sizeof.xhci_pipe], eax
|
||||
jmp [usbhc_api.usb_subscribe_control]
|
||||
endp
|
||||
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe. out: eax = address.
|
||||
proc xhci_get_device_address
|
||||
mov eax, [ebx+xhci_pipe.Address-sizeof.xhci_pipe]
|
||||
ret
|
||||
endp
|
||||
|
||||
; Called from usb_get_descr8_callback once the real packet size of the default
|
||||
; control endpoint is known. On xHCI that value lives in the Endpoint Context,
|
||||
; so an Evaluate Context command is needed to update it.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size.
|
||||
proc xhci_set_endpoint_packet_size
|
||||
push ebx ecx edx edi
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
if XHCI_SUPERSPEED
|
||||
; For a SuperSpeed device bMaxPacketSize0 is an exponent, and the only value
|
||||
; the specification allows is 9: use 512 directly instead of the raw byte.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb @f
|
||||
mov ecx, 512
|
||||
@@:
|
||||
end if
|
||||
mov [ebx+xhci_pipe.MaxPacket], ecx
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [edx+4], 2 ; evaluate the default control endpoint
|
||||
call xhci_fill_ep_ctx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_EVAL_CTX shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz @f
|
||||
DEBUGF 1,'K : XHCI: Evaluate Context failed, code %d\n',eax
|
||||
@@:
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop edi edx ecx ebx
|
||||
jmp [usbhc_api.usb_subscribe_control]
|
||||
endp
|
||||
|
||||
; If the descriptor that has just completed is the answer to a request for the
|
||||
; hub descriptor, tell the controller that the device is a hub: it has to know
|
||||
; that in order to serve the devices behind it.
|
||||
; in: ebx -> usb_gtd.
|
||||
proc xhci_check_hub_descriptor
|
||||
pushad
|
||||
cmp [ebx+usb_gtd.Callback], 0
|
||||
jz .nothing
|
||||
mov eax, [ebx+usb_gtd.Pipe]
|
||||
mov esi, [eax+usb_pipe.Controller]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
test [eax+xhci_pipe.Flags], XHCI_PIPE_HUBPEND
|
||||
jz .nothing
|
||||
and [eax+xhci_pipe.Flags], not XHCI_PIPE_HUBPEND
|
||||
cmp [ebx+xhci_gtd.Status-sizeof.xhci_gtd], XHCI_CC_SUCCESS
|
||||
jnz .nothing
|
||||
mov edx, [eax+xhci_pipe.HubBuf]
|
||||
test edx, edx
|
||||
jz .nothing
|
||||
cmp byte [edx+1], 29h ; bDescriptorType
|
||||
jnz .nothing
|
||||
or [eax+xhci_pipe.Flags], XHCI_PIPE_ISHUB
|
||||
mov ebx, eax ; ebx -> xhci_pipe of the hub
|
||||
movzx edi, byte [edx+2] ; bNbrPorts
|
||||
movzx ebp, byte [edx+3] ; low byte of wHubCharacteristics
|
||||
shr ebp, 5
|
||||
and ebp, 3 ; Transaction Translator Think Time
|
||||
DEBUGF 1,'K : XHCI: device on slot %d is a hub with %d ports\n',[ebx+xhci_pipe.SlotId],edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [eax+4], 1 ; only the Slot Context is evaluated
|
||||
mov ecx, [ebx+xhci_pipe.MaxDCI]
|
||||
test ecx, ecx
|
||||
jnz @f
|
||||
movi ecx, 1
|
||||
@@:
|
||||
call xhci_fill_slot_ctx
|
||||
; Patch the Slot Context with the fields that describe a hub. Only Configure
|
||||
; Endpoint takes them into account, Evaluate Context would ignore them.
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
movi ecx, 1
|
||||
call xhci_context
|
||||
or dword [eax], 1 shl 26 ; this device is a hub
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jnz @f
|
||||
shl ebp, 16
|
||||
or [eax+8], ebp
|
||||
@@:
|
||||
shl edi, 24
|
||||
or [eax+4], edi ; Number of Ports
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz @f
|
||||
DEBUGF 1,'K : XHCI: cannot mark the device as a hub, code %d\n',eax
|
||||
@@:
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
@@ -0,0 +1,135 @@
|
||||
; SuperSpeed support for the xHCI driver, included from xhci.asm when
|
||||
; XHCI_SUPERSPEED is enabled. The pieces too small to live here - the port
|
||||
; map, the Slot Context speed, the 512-byte default control endpoint, the
|
||||
; Max Burst field of the Endpoint Context - sit in the other files under
|
||||
; "if XHCI_SUPERSPEED" guards; this file keeps the self-contained procedures.
|
||||
;
|
||||
; The kernel USB stack knows nothing about SuperSpeed, so it never learns
|
||||
; about it: a SuperSpeed device is announced as a high-speed one, which also
|
||||
; keeps the Transaction Translator logic away from it. The raw PORTSC speed
|
||||
; identifier travels in xhci_pipe.PSIV instead and reaches everything that
|
||||
; really needs it. SuperSpeed hubs are not supported: the kernel only speaks
|
||||
; the USB2 hub protocol, so a device behind a USB3 hub is served by the USB2
|
||||
; half of that hub at high speed.
|
||||
|
||||
; =============================================================================
|
||||
; ============================ SuperSpeed ports ===============================
|
||||
; =============================================================================
|
||||
|
||||
; Called from xhci_new_port for a SuperSpeed root port instead of the USB2
|
||||
; reset entry point: a SuperSpeed link trains itself and the port enables
|
||||
; itself on connect, reporting the speed with no reset at all. When the link
|
||||
; is already up, skip straight to the reset recovery stage, after which
|
||||
; xhci_port_init picks the device up; otherwise try a warm reset.
|
||||
; in: esi -> usb_controller, ecx = port index.
|
||||
proc xhci_ss_start_port
|
||||
push eax edx
|
||||
and [esi+usb_controller.ResettingHub], 0
|
||||
mov [esi+usb_controller.ResettingPort], cl
|
||||
push ecx
|
||||
invoke GetTimerTicks
|
||||
pop ecx
|
||||
mov [esi+usb_controller.ResetTime], eax
|
||||
mov [esi+xhci_controller.ResetStart-XCD], eax
|
||||
call xhci_port_reg
|
||||
mov eax, [edx]
|
||||
test al, XHCI_PORT_PED
|
||||
jz .warm_reset
|
||||
mov [esi+usb_controller.ResettingStatus], 2
|
||||
DEBUGF 1,'K : XHCI %x: SS port %d link is up, PORTSC=%x\n',esi,ecx,eax
|
||||
jmp .nothing
|
||||
.warm_reset:
|
||||
; Connected, but the link has not come up. The Port Reset bit is set while a
|
||||
; warm reset is running, so the ordinary reset-wait machinery in
|
||||
; xhci_port_reset_done serves this case unchanged; the extra WRC change bit is
|
||||
; acknowledged there together with the usual ones.
|
||||
mov dword [edx], XHCI_PORT_PP + XHCI_PORT_WPR
|
||||
mov [esi+usb_controller.ResettingStatus], 1
|
||||
DEBUGF 1,'K : XHCI %x: warm-resetting port %d, PORTSC=%x\n',esi,ecx,eax
|
||||
.nothing:
|
||||
pop edx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; The kernel restarts pending root ports through the NewPortReset entry of
|
||||
; usb_hardware_func directly, bypassing xhci_new_port; SuperSpeed ports must
|
||||
; not get the USB2 reset on that path either, so the entry points here.
|
||||
; in: esi -> usb_controller, ecx = port index.
|
||||
proc xhci_ss_port_reset
|
||||
bt [esi+xhci_controller.SSPortMask-XCD], ecx
|
||||
jnc xhci_new_port.reset
|
||||
call xhci_ss_start_port
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ===================== Endpoint Companion descriptors ========================
|
||||
; =============================================================================
|
||||
|
||||
; Reads the SuperSpeed Endpoint Companion descriptor of a bulk endpoint and
|
||||
; keeps its bMaxBurst for the Endpoint Context, allowing bursts of up to
|
||||
; bMaxBurst+1 packets per transaction. Zero (no bursts) is always legal, so
|
||||
; any failure just leaves the field alone. Only bulk endpoints are considered:
|
||||
; a nonzero burst on a periodic endpoint would also require the Max ESIT
|
||||
; Payload fields, and real interrupt endpoints do not burst anyway.
|
||||
; Relies on the stack frame of usb_open_pipe exactly like xhci_init_pipe does:
|
||||
; [ebp+8] is the config pipe of the device.
|
||||
; in: ebx -> xhci_pipe of a non-control endpoint being opened.
|
||||
proc xhci_ss_get_burst
|
||||
push eax ecx edx edi
|
||||
; 1. Only SuperSpeed bulk endpoints are of interest.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb .nothing
|
||||
mov eax, [ebx+xhci_pipe.EpType]
|
||||
and al, 3
|
||||
cmp al, 2 ; bulk endpoint types are 2 and 6
|
||||
jnz .nothing
|
||||
; 2. Find the configuration data kept by the kernel behind the device
|
||||
; descriptor; it holds the endpoint descriptors with their companions.
|
||||
mov eax, [ebp+8]
|
||||
mov eax, [eax+usb_pipe.DeviceData]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
movzx edx, [eax+usb_device_data.DeviceDescrSize]
|
||||
mov edi, [eax+usb_device_data.ConfigDataSize]
|
||||
lea ecx, [eax+edx+usb_device_data.DeviceDescriptor]
|
||||
add edi, ecx ; edi -> end of the configuration data
|
||||
; 3. Reconstruct bEndpointAddress from the Device Context Index.
|
||||
mov edx, [ebx+xhci_pipe.DCI]
|
||||
shr edx, 1
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
or dl, 80h
|
||||
@@:
|
||||
; 4. Walk the descriptors to the one of this endpoint.
|
||||
.walk:
|
||||
lea eax, [ecx+2]
|
||||
cmp eax, edi
|
||||
ja .nothing
|
||||
movzx eax, byte [ecx] ; bLength
|
||||
test eax, eax
|
||||
jz .nothing ; malformed data, stop
|
||||
cmp byte [ecx+1], 5 ; an endpoint descriptor?
|
||||
jnz .advance
|
||||
cmp [ecx+2], dl ; bEndpointAddress
|
||||
jnz .advance
|
||||
; 5. The companion descriptor (type 30h) immediately follows its endpoint.
|
||||
add ecx, eax
|
||||
lea eax, [ecx+3]
|
||||
cmp eax, edi
|
||||
ja .nothing
|
||||
cmp byte [ecx+1], 30h ; SuperSpeed Endpoint Companion
|
||||
jnz .nothing
|
||||
movzx eax, byte [ecx+2] ; bMaxBurst
|
||||
cmp eax, 15
|
||||
ja .nothing
|
||||
mov [ebx+xhci_pipe.MaxBurst], eax
|
||||
DEBUGF 1,'K : XHCI: slot %d dci %d bursts %d+1 packets\n',[ebx+xhci_pipe.SlotId],[ebx+xhci_pipe.DCI],eax
|
||||
jmp .nothing
|
||||
.advance:
|
||||
add ecx, eax
|
||||
jmp .walk
|
||||
.nothing:
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
File diff suppressed because it is too large.
Load diff
+1767
-190
File diff suppressed because it is too large.
Load diff
@@ -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:
|
||||
@@ -1489,19 +1488,31 @@ dyndisk_handler:
|
||||
; 12. The fs operation has specified some partition.
|
||||
push edx ecx
|
||||
xor eax, eax
|
||||
mov ecx, eax
|
||||
lodsb
|
||||
@@:
|
||||
lea ecx, [ecx*4 + ecx]
|
||||
shl ecx, 1
|
||||
|
||||
sub eax, '0'
|
||||
jz .dyndisk_cleanup
|
||||
jb .dyndisk_cleanup
|
||||
cmp eax, 10
|
||||
jnc .dyndisk_cleanup
|
||||
mov ecx, eax
|
||||
|
||||
add ecx, eax
|
||||
cmp ecx, MAX_NUM_PARTITIONS
|
||||
ja .dyndisk_cleanup
|
||||
|
||||
lodsb
|
||||
cmp eax, '/'
|
||||
jz @f
|
||||
test eax, eax
|
||||
jnz .dyndisk_cleanup
|
||||
jnz @b
|
||||
dec esi
|
||||
@@:
|
||||
test ecx, ecx
|
||||
jz .dyndisk_cleanup
|
||||
|
||||
cmp byte [esi], 0
|
||||
jnz @f
|
||||
; partition info
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2507,7 +2507,7 @@ dword-значение цвета 0x00RRGGBB
|
||||
* иначе eax = TID - идентификатор потока
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_CREATE_THREAD (51) /
|
||||
eax - SF_THREAD_CONTROL (51) /
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
|
||||
@@ -4098,6 +4098,9 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* подфункция 7 - запуск программы
|
||||
* подфункция 8 - удаление файла/папки
|
||||
* подфункция 9 - создание папки
|
||||
* подфункция 10 - переименование/перемещение
|
||||
* подфункция 11 - создание симлинка
|
||||
* подфункция 12 - чтение симлинка
|
||||
Для CD-приводов в связи с аппаратными ограничениями доступны
|
||||
только подфункции 0,1,5 и 7, вызов других подфункций завершится
|
||||
ошибкой с кодом 2.
|
||||
@@ -4112,7 +4115,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9)
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
= Функция 70, подфункция 0 - чтение файла с поддержкой длинных имён. =
|
||||
======================================================================
|
||||
@@ -4464,6 +4468,62 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Формирование нового пути отличается от общих правил:
|
||||
относительный путь относится к папке целевого файла (или папки),
|
||||
абсолютный путь считается от корня раздела.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Функция 70, подфункция 11 - создание симлинка. ===========
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 11 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: 0 (зарезервировано)
|
||||
* +16 = +0x10: dword: указатель на строку с целевым путём
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx разрушается
|
||||
Замечания:
|
||||
* Родительская папка должна существовать.
|
||||
* Для CD функция не поддерживается (возвращает код ошибки 2).
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Функция 70, подфункция 12 - чтение симлинка. ============
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 12 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: размер буфера в байтах
|
||||
* +16 = +0x10: dword: указатель на буфер для целевого пути
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx = число байт, записанных в буфер
|
||||
Замечания:
|
||||
* Функция не следует по симлинку; она читает целевой путь,
|
||||
на который указывает симлинк.
|
||||
* Целевой путь всегда завершается нулём, в том числе при обрезании;
|
||||
записывается не более (размер буфера - 1) байт пути.
|
||||
* Значение в ebx включает завершающий 0, как в подфункции 2
|
||||
функции 30.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
========== Функция 71 - установить заголовок окна программы ==========
|
||||
======================================================================
|
||||
@@ -5059,8 +5119,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = дескриптор фьютекса, 0 при ошибке
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
======================================================================
|
||||
============= Функция 77, подфункция 1, Удалить фьютекс. =============
|
||||
======================================================================
|
||||
@@ -5074,8 +5134,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Ядро автоматически удаляет фьютексы при завершении процесса.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
======================================================================
|
||||
================= Функция 77, подфункция 2, Ожидать. =================
|
||||
======================================================================
|
||||
@@ -5091,8 +5151,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
-2 - контрольное значение фьютекса не соответствует
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
======================================================================
|
||||
================ Функция 77, подфункция 3, Разбудить. ================
|
||||
======================================================================
|
||||
@@ -5105,8 +5165,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = количество разбуженых
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
======================================================================
|
||||
Замечания:
|
||||
* Подфункции 4-7 зарезервированы и сейчас возвращают -1.
|
||||
@@ -5128,8 +5188,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
|
||||
======================================================================
|
||||
======== Функция 77, подфункция 11, Записать из буфера в файл. =======
|
||||
@@ -5148,8 +5208,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
|
||||
======================================================================
|
||||
=========== Функция 77, подфункция 13, Создать новый pipe. ===========
|
||||
@@ -5173,8 +5233,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
- дескриптором записи.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
|
||||
======================================================================
|
||||
========== Функция -1 - завершить выполнение потока/процесса =========
|
||||
|
||||
@@ -2492,7 +2492,7 @@ Returned value:
|
||||
* otherwise eax = TID - thread identifier
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_CREATE_THREAD (51)
|
||||
eax - SF_THREAD_CONTROL (51)
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
======================================================================
|
||||
@@ -4060,6 +4060,9 @@ Available subfunctions:
|
||||
* subfunction 7 - start application
|
||||
* subfunction 8 - delete file/folder
|
||||
* subfunction 9 - create folder
|
||||
* subfunction 10 - rename/move
|
||||
* subfunction 11 - create symlink
|
||||
* subfunction 12 - read symlink
|
||||
For CD-drives due to hardware limitations only subfunctions
|
||||
0,1,5 and 7 are available, other subfunctions return error
|
||||
with code 2.
|
||||
@@ -4073,7 +4076,8 @@ is called for corresponding device.
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9)
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
=== Function 70, subfunction 0 - read file with long names support. ==
|
||||
======================================================================
|
||||
@@ -4144,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
|
||||
@@ -4423,6 +4428,60 @@ Remarks:
|
||||
* New path forming differs from general rules:
|
||||
relative path relates to the target's parent folder,
|
||||
absolute path relates to the partition's root folder.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Function 70, subfunction 11 - create symlink. ============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 11 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: 0 (reserved)
|
||||
* +16 = +0x10: dword: pointer to the target path string
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx destroyed
|
||||
Remarks:
|
||||
* The parent folder must already exist.
|
||||
* The function is not supported for CD (returns error code 2).
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Function 70, subfunction 12 - read symlink. =============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 12 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: buffer size in bytes
|
||||
* +16 = +0x10: dword: pointer to buffer for target path
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx = number of bytes written to the buffer
|
||||
Remarks:
|
||||
* The function does not follow the symlink; it reads the target path
|
||||
that the symlink points to.
|
||||
* The target path is always terminated with 0, even when truncated;
|
||||
at most (buffer size - 1) path bytes are written.
|
||||
* The value returned in ebx includes the terminating 0, as in
|
||||
subfunction 2 of function 30.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
================== Function 71 - set window caption ==================
|
||||
======================================================================
|
||||
@@ -5273,8 +5332,8 @@ Returned value:
|
||||
* eax = futex handle, 0 on error
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
======================================================================
|
||||
========= Function 77, Subfunction 1, Destroy futex object ===========
|
||||
======================================================================
|
||||
@@ -5289,8 +5348,8 @@ Remarks:
|
||||
terminates.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 2, Futex wait ===============
|
||||
======================================================================
|
||||
@@ -5306,8 +5365,8 @@ Returned value:
|
||||
-2 - futex control value doesn't match
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 3, Futex wake ===============
|
||||
======================================================================
|
||||
@@ -5320,8 +5379,8 @@ Returned value:
|
||||
* eax = number of waiters that were woken up
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
======================================================================
|
||||
Remarks:
|
||||
* Subfunctions 4-7 are reserved and currently return -1.
|
||||
@@ -5343,8 +5402,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
======================================================================
|
||||
=========== Function 77, Subfunction 11, Write to file. =============
|
||||
======================================================================
|
||||
@@ -5362,8 +5421,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
======================================================================
|
||||
========== Function 77, Subfunction 13, Create pipe. ================
|
||||
======================================================================
|
||||
@@ -5381,8 +5440,8 @@ Remarks:
|
||||
write handle.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
======================================================================
|
||||
=== Function 80 - file system interface with parameter of encoding ===
|
||||
======================================================================
|
||||
|
||||
+1041
-72
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
|
||||
@@ -182,10 +182,22 @@ proc file_system_is_operation_safe stdcall, inf_struct_ptr: dword
|
||||
|
||||
.case6:
|
||||
cmp dword [ebx], 6
|
||||
jnz .switch_none
|
||||
jnz .case11
|
||||
mov ecx, 32
|
||||
jmp .end_switch
|
||||
|
||||
.case11:
|
||||
cmp dword [ebx], 11
|
||||
jnz .case12
|
||||
stdcall is_string_userspace, edx
|
||||
jmp .ret
|
||||
|
||||
.case12:
|
||||
cmp dword [ebx], 12
|
||||
jnz .switch_none
|
||||
mov ecx, dword [ebx + 12]
|
||||
jmp .end_switch
|
||||
|
||||
.switch_none:
|
||||
cmp ecx, ecx
|
||||
jmp .ret
|
||||
|
||||
@@ -253,9 +253,10 @@ UTF16to8_string:
|
||||
|
||||
UTF16to8:
|
||||
; in:
|
||||
; eax = UTF-16 char
|
||||
; ax = UTF-16 char
|
||||
; edi -> buffer for UTF-8 char (increasing)
|
||||
; ecx = byte counter (decreasing)
|
||||
movzx eax, ax
|
||||
dec ecx
|
||||
js .ret
|
||||
cmp eax, 80h
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -48,6 +48,10 @@ dtext:
|
||||
add esp, 28
|
||||
ret
|
||||
|
||||
.nomem:
|
||||
add esp, 40
|
||||
ret
|
||||
|
||||
.redirect:
|
||||
mov ebp, [edi]
|
||||
add edi, 8
|
||||
@@ -81,6 +85,8 @@ dtext:
|
||||
mov [esp+32], eax
|
||||
imul ebp, eax
|
||||
stdcall kernel_alloc, ebp
|
||||
test eax, eax
|
||||
jz .nomem
|
||||
mov ecx, ebp
|
||||
shr ecx, 2
|
||||
mov [esp+36], eax
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; IPv4.INC ;;
|
||||
@@ -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
|
||||
@@ -765,9 +790,9 @@ ipv4_output_raw:
|
||||
push ebx ; push the mac
|
||||
push ax
|
||||
|
||||
inc [IPv4_packets_tx + 4*edi]
|
||||
inc [IPv4_packets_tx + edi]
|
||||
mov ax, ETHER_PROTO_IPv4
|
||||
mov ebx, [net_device_list + 4*edi]
|
||||
mov ebx, [net_device_list + edi]
|
||||
mov ecx, [esp + 6 + 4]
|
||||
add ecx, sizeof.IPv4_header
|
||||
mov edx, esp
|
||||
@@ -951,7 +976,7 @@ endp
|
||||
; edi = device number*4 ;
|
||||
; ;
|
||||
; DESTROYED: ;
|
||||
; ecx ;
|
||||
; ebx, ecx ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
align 4
|
||||
@@ -964,8 +989,11 @@ ipv4_route:
|
||||
cmp eax, 0xffffffff
|
||||
je .broadcast
|
||||
|
||||
; 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
|
||||
@@ -978,9 +1006,58 @@ ipv4_route:
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .loop
|
||||
|
||||
mov eax, [IPv4_gateway + 4] ; TODO: let user (or a user space daemon) configure default route
|
||||
; no on-link match, find first device with a gateway
|
||||
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
|
||||
jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.found_gw:
|
||||
mov eax, [IPv4_gateway + edi]
|
||||
jmp .got_it
|
||||
|
||||
.broadcast:
|
||||
mov edi, 4 ; TODO: same as above
|
||||
; broadcast: we will do our best without full routing..
|
||||
|
||||
; find the first non loopback device which has an active link without IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop1:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
je @f
|
||||
cmp [IPv4_address + edi], 0
|
||||
je .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop1
|
||||
|
||||
; If there is no such device, try the one with active link and IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop2:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
jne .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop2
|
||||
; jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.loopback:
|
||||
xor edi, edi ; nowhere to go for now.. route it to the loopback device
|
||||
|
||||
.got_it:
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
|
||||
test edx, edx
|
||||
@@ -1002,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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
|
||||
@@ -780,8 +780,6 @@ socket_close:
|
||||
|
||||
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
|
||||
jne .free
|
||||
test [eax + SOCKET.state], SS_ISCONNECTED
|
||||
jz @f
|
||||
test [eax + SOCKET.state], SS_ISDISCONNECTING
|
||||
jnz @f
|
||||
call tcp_disconnect
|
||||
@@ -2126,11 +2124,11 @@ socket_free:
|
||||
mov ebx, eax
|
||||
cmp [eax + STREAM_SOCKET.rcv.start_ptr], 0
|
||||
je @f
|
||||
stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr]
|
||||
stdcall kernel_free, [eax + STREAM_SOCKET.rcv.start_ptr]
|
||||
@@:
|
||||
cmp [ebx + STREAM_SOCKET.snd.start_ptr], 0
|
||||
je @f
|
||||
stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr]
|
||||
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
|
||||
@@:
|
||||
mov eax, ebx
|
||||
.no_stream:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -355,9 +355,14 @@ endl
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
|
||||
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
|
||||
|
||||
; remember the peer's scale factor; it is applied to SND_SCALE when the
|
||||
; connection is established (together with our RCV_SCALE)
|
||||
lodsb
|
||||
mov [ebx + TCP_SOCKET.SND_SCALE], al
|
||||
;;;;; TODO
|
||||
cmp al, TCP_max_winshift
|
||||
jbe .wscale_capped
|
||||
mov al, TCP_max_winshift
|
||||
.wscale_capped:
|
||||
mov [ebx + TCP_SOCKET.requested_s_scale], al
|
||||
|
||||
@@:
|
||||
jmp .opt_loop
|
||||
@@ -1417,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
|
||||
@@:
|
||||
|
||||
;-----------------------------------------------------------------------------------
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -320,12 +320,12 @@ tcp_respond:
|
||||
stosb
|
||||
mov eax, SOCKET_BUFFER_SIZE
|
||||
sub eax, [esi + STREAM_SOCKET.rcv.size]
|
||||
cmp eax, TCP_max_win
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl ; scale first, then clamp to the
|
||||
cmp eax, TCP_max_win ; 16-bit field maximum
|
||||
jbe .lessthanmax
|
||||
mov eax, TCP_max_win
|
||||
.lessthanmax:
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl
|
||||
|
||||
xchg al, ah
|
||||
stosw ; window
|
||||
@@ -488,7 +488,7 @@ tcp_set_persist:
|
||||
; Start/restart persistence timer.
|
||||
|
||||
tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
|
||||
or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
or [eax + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
pop ebx
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
|
||||
|
||||
@@ -111,13 +111,13 @@ proc tcp_timer_640ms
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax
|
||||
|
||||
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
|
||||
ja .dont_kill
|
||||
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
||||
jae .dont_kill
|
||||
|
||||
push eax
|
||||
push [eax + SOCKET.NextPtr]
|
||||
call tcp_disconnect
|
||||
pop eax
|
||||
jmp .loop
|
||||
jmp .check_only
|
||||
|
||||
.dont_kill:
|
||||
test [eax + SOCKET.options], SO_KEEPALIVE
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -125,7 +125,7 @@ SF_STYLE_SETTINGS=48
|
||||
SSF_SET_FONT_SIZE=12
|
||||
SF_APM=49
|
||||
SF_SET_WINDOW_SHAPE=50
|
||||
SF_CREATE_THREAD=51
|
||||
SF_THREAD_CONTROL=51
|
||||
SSF_CREATE_THREAD=1
|
||||
SSF_GET_CURR_THREAD_SLOT=2
|
||||
SSF_GET_THREAD_PRIORITY=3
|
||||
@@ -281,14 +281,14 @@ SF_NETWORK_PROTOCOL=76
|
||||
SSF_ARP_DEL_ENTRY=50005h
|
||||
SSF_ARP_SEND_ANNOUNCE=50006h
|
||||
SSF_ARP_CONFLICTS_COUNT=50007h
|
||||
SF_FUTEX=77
|
||||
SSF_CREATE=0
|
||||
SSF_DESTROY=1
|
||||
SSF_WAIT=2
|
||||
SSF_WAKE=3
|
||||
SSF_FILE_READ=10
|
||||
SSF_FILE_WRITE=11
|
||||
SSF_PIPE_CREATE=13
|
||||
SF_POSIX=77
|
||||
SSF_FUTEX_CREATE=0
|
||||
SSF_FUTEX_DESTROY=1
|
||||
SSF_FUTEX_WAIT=2
|
||||
SSF_FUTEX_WAKE=3
|
||||
SSF_FD_READ=10
|
||||
SSF_FD_WRITE=11
|
||||
SSF_FD_PIPE2=13
|
||||
|
||||
; File system errors:
|
||||
FSERR_SUCCESS=0
|
||||
|
||||
@@ -1111,7 +1111,7 @@ end if
|
||||
mov dword [edx+8],ebx
|
||||
mov dword [edx+4],ecx
|
||||
mov dword [edx],Kolibri_ThreadFinish
|
||||
mov eax,SF_CREATE_THREAD
|
||||
mov eax,SF_THREAD_CONTROL
|
||||
mov ebx,1
|
||||
mov ecx,@Kolibri@ThreadMain$qpvt1
|
||||
int 0x40
|
||||
|
||||
Submodule
+1
Submodule programs/cmm added at 86b0211da7.
@@ -1,6 +0,0 @@
|
||||
if tup.getconfig("NO_CMM") ~= "" then return end
|
||||
if tup.getconfig("LANG") == "ru_RU"
|
||||
then C_LANG = "LANG_RUS"
|
||||
else C_LANG = "LANG_ENG" -- this includes default case without config
|
||||
end
|
||||
tup.rule("app_plus.c", "c-- /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "app_plus.com")
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
struct sysdir
|
||||
{
|
||||
char name[64];
|
||||
char path[64];
|
||||
} sysdir;
|
||||
|
||||
|
||||
:int SetAdditionalSystemDirectory(dword tName, tPath)
|
||||
{
|
||||
int i;
|
||||
strcpy(#sysdir.name, tName);
|
||||
strcpy(#sysdir.path, tPath);
|
||||
$mov eax, 30
|
||||
$mov ebx, 3
|
||||
ECX = #sysdir;
|
||||
$int 0x40
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
#define MEMSIZE 1024*60
|
||||
|
||||
#include "..\lib\gui.h"
|
||||
#include "..\lib\obj\proc_lib.h"
|
||||
#include "..\lib\patterns\simple_open_dialog.h"
|
||||
#include "..\lib\patterns\restart_process.h"
|
||||
#include "added_sysdir.c"
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// DATA //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
#define WINW 570
|
||||
#define WINH 300
|
||||
#define CONX 28 //content X pos
|
||||
#define CONY 25 //content Y pos
|
||||
|
||||
char default_dir[] = "/sys";
|
||||
od_filter filter2;
|
||||
|
||||
#define BTN_MANUAL_SEARCH 10
|
||||
#define BTN_OPEN_ANYWAY 11
|
||||
|
||||
#define APP_PLUS_INI_PATH "/sys/settings/app_plus.ini"
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// TRANSLATIONS //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
#ifdef LANG_RUS
|
||||
?define WINDOW_TITLE_TEXT "Внимание!"
|
||||
?define CONTENT_HEADER_TEXT "KolibriOS работает в режиме дискеты"
|
||||
?define DESCRIPTION_TEXT "Многие приложения сейчас недоступны.
|
||||
|
||||
Причина в том, что не смонтирован дополнительный системный
|
||||
каталог. Но вы можете найти и задать его вручную. Его название
|
||||
'kolibrios'. Вы также можете загрузить latest-dirstr.7z через
|
||||
WebView и найти его внутри."
|
||||
?define MANUALLY_BUTTON_TEXT "Указать папку /kolibrios/..."
|
||||
?define OPEN_ANYWAY_BUTTON_TEXT "Запустить APP+ (некоторые программы будут недоступны)"
|
||||
#else
|
||||
?define WINDOW_TITLE_TEXT "Warning!"
|
||||
?define CONTENT_HEADER_TEXT "KolibriOS is running in floppy mode"
|
||||
?define DESCRIPTION_TEXT "A lot of apps aren't available.
|
||||
|
||||
The reason is that additional system directory is not mounted.
|
||||
But you can find and set it manually. Its name is 'kolibrios'.
|
||||
You can also download latest-dirstr.7z via WebView and find
|
||||
it inside."
|
||||
?define MANUALLY_BUTTON_TEXT "Choose /kolibrios/ folder..."
|
||||
?define OPEN_ANYWAY_BUTTON_TEXT "Open APP+ anyway (some programs won't be available)"
|
||||
#endif
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// CODE //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void main()
|
||||
{
|
||||
if (param) {
|
||||
SetAdditionalSystemDirectory("kolibrios", #param+1);
|
||||
ExitProcess();
|
||||
}
|
||||
|
||||
WaitAutosearch();
|
||||
CheckKosMounted();
|
||||
|
||||
o_dialog.type = 2;
|
||||
#define NO_DLL_INIT
|
||||
load_dll(Proc_lib, #OpenDialog_init,0);
|
||||
OpenDialog_init stdcall (#o_dialog);
|
||||
active_button_id = BTN_MANUAL_SEARCH;
|
||||
|
||||
loop() switch(@WaitEvent())
|
||||
{
|
||||
case evButton:
|
||||
EventButton(GetButtonID());
|
||||
break;
|
||||
case evKey:
|
||||
@GetKeyScancode();
|
||||
if (AL == SCAN_CODE_ENTER) {
|
||||
EventButton(active_button_id);
|
||||
} else if (AL == SCAN_CODE_TAB) {
|
||||
active_button_id = active_button_id-10^1 + 10;
|
||||
DrawButtons();
|
||||
}
|
||||
break;
|
||||
|
||||
case evReDraw:
|
||||
draw_window();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_window()
|
||||
{
|
||||
sc.get();
|
||||
DefineAndDrawWindow(screen.w-WINW/2, 100, WINW, WINH+skin_h, 0x34, sc.work, WINDOW_TITLE_TEXT,0);
|
||||
draw_icon_16w(CONX+2, CONY-3, 5);
|
||||
WriteTextB(CONX+27+2,CONY+2,0x81,MixColors(sc.work, 0xB92234,220),CONTENT_HEADER_TEXT);
|
||||
WriteTextB(CONX+27,CONY,0x81,0xB92234,CONTENT_HEADER_TEXT);
|
||||
WriteTextLines(CONX,CONY+42,0x90,sc.work_text,DESCRIPTION_TEXT,20);
|
||||
DrawButtons();
|
||||
}
|
||||
|
||||
void DrawButtons()
|
||||
{
|
||||
DrawStandartCaptButton(CONX, WINH-CONY-58, BTN_MANUAL_SEARCH, MANUALLY_BUTTON_TEXT);
|
||||
DrawStandartCaptButton(CONX, WINH-CONY-22, BTN_OPEN_ANYWAY, OPEN_ANYWAY_BUTTON_TEXT);
|
||||
}
|
||||
|
||||
void CheckKosMounted()
|
||||
{
|
||||
if (dir_exists("/kolibrios"))
|
||||
{
|
||||
if (file_exists(APP_PLUS_INI_PATH)) EventOpenApp();
|
||||
ExitProcess();
|
||||
}
|
||||
}
|
||||
|
||||
void WaitAutosearch()
|
||||
{
|
||||
while (CheckProcessExists("SEARCHAP")) pause(2);
|
||||
}
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// EVENTS //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void EventManualSearch()
|
||||
{
|
||||
OpenDialog_start stdcall (#o_dialog);
|
||||
if (o_dialog.status) SetAdditionalSystemDirectory("kolibrios", #openfile_path+1);
|
||||
pause(3);
|
||||
CheckKosMounted();
|
||||
}
|
||||
|
||||
void EventOpenApp()
|
||||
{
|
||||
if (RunProgram("/sys/syspanel", APP_PLUS_INI_PATH) < 0) {
|
||||
notify("'App+ cannot start because\n/sys/syspanel does not exist' -E");
|
||||
}
|
||||
}
|
||||
|
||||
void EventButton(dword id)
|
||||
{
|
||||
if (id==CLOSE_BTN) ExitProcess();
|
||||
else if (id==BTN_MANUAL_SEARCH) EventManualSearch();
|
||||
else if (id==BTN_OPEN_ANYWAY) {
|
||||
EventOpenApp();
|
||||
ExitProcess();
|
||||
}
|
||||
}
|
||||
|
||||
stop:
|
||||
@@ -1,6 +0,0 @@
|
||||
@c-- /D=LANG_ENG app_plus.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
@pause
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
@c-- /D=LANG_RUS app_plus.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
@pause
|
||||
@@ -1,6 +0,0 @@
|
||||
if tup.getconfig("NO_CMM") ~= "" then return end
|
||||
if tup.getconfig("LANG") == "ru_RU"
|
||||
then C_LANG = "LANG_RUS"
|
||||
else C_LANG = "LANG_ENG" -- this includes default case without config
|
||||
end
|
||||
tup.rule("appearance.c", "c-- /D=AUTOBUILD /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "appearance.com")
|
||||
@@ -1,472 +0,0 @@
|
||||
//11.03.12 - start!
|
||||
|
||||
#define MEMSIZE 1024*70
|
||||
#include "../lib/mem.h"
|
||||
#include "../lib/strings.h"
|
||||
#include "../lib/io.h"
|
||||
#include "../lib/list_box.h"
|
||||
#include "../lib/gui.h"
|
||||
|
||||
#include "../lib/obj/box_lib.h"
|
||||
#include "../lib/obj/proc_lib.h"
|
||||
#include "../lib/obj/libini.h"
|
||||
|
||||
#include "../lib/patterns/select_list.h"
|
||||
#include "../lib/patterns/simple_open_dialog.h"
|
||||
#include "../lib/patterns/restart_process.h"
|
||||
|
||||
dword fmas;
|
||||
|
||||
#include "ui_elements_preview.h"
|
||||
#include "const.h"
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// DATA //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
int active_skin=-1, active_wallpaper=-1, active_screensaver=-1;
|
||||
|
||||
checkbox optionbox_stretch = { T_CHECKBOX_STRETCH, false };
|
||||
checkbox optionbox_tiled = { T_CHECKBOX_TILED, false };
|
||||
checkbox optionbox_auto = { T_CHECKBOX_AUTO, true };
|
||||
|
||||
char ss_available[200];
|
||||
|
||||
collection list;
|
||||
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// CODE //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void main()
|
||||
{
|
||||
int id, i;
|
||||
load_dll(boxlib, #box_lib_init,0);
|
||||
load_dll(libini, #lib_init,1);
|
||||
load_dll(Proc_lib, #OpenDialog_init,0);
|
||||
OpenDialog_init stdcall (#o_dialog);
|
||||
|
||||
GetIniSettings();
|
||||
|
||||
tabs.add(#t_skins, #EventTabSkinsClick);
|
||||
tabs.add(#t_wallpapers, #EventTabWallpappersClick);
|
||||
tabs.add(#t_screensaver, #EventTabScreensaverClick);
|
||||
tabs.draw_active_tab();
|
||||
|
||||
SetEventMask(EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_MOUSE + EVM_MOUSE_FILTER);
|
||||
loop() switch(WaitEvent())
|
||||
{
|
||||
case evMouse:
|
||||
SelectList_ProcessMouse();
|
||||
if (tabs.active_tab == TAB_SCREENSAVERS) {
|
||||
scrollbar_h_mouse stdcall (#ss_timeout);
|
||||
if (ss_timeout.redraw) {
|
||||
draw_timeout();
|
||||
ss_timeout.redraw = false; //reset flag
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case evButton:
|
||||
id=GetButtonID();
|
||||
if (id==1) EventExit();
|
||||
tabs.click(id);
|
||||
if (tabs.active_tab == TAB_SKINS) {
|
||||
checkbox1.click(id);
|
||||
spinbox1.click(id);
|
||||
}
|
||||
if (tabs.active_tab == TAB_WALLPAPERS) {
|
||||
if (id==BTN_SELECT_WALLP_FOLDER) EventSelectWallpFolder();
|
||||
if (optionbox_stretch.click(id)) EventSetWallpMode(1,0,0);
|
||||
if (optionbox_tiled.click(id)) EventSetWallpMode(0,1,0);
|
||||
if (optionbox_auto.click(id)) EventSetWallpMode(0,0,1);
|
||||
}
|
||||
if (tabs.active_tab == TAB_SCREENSAVERS) {
|
||||
if (id==BTN_TEST_SCREENSAVER) EventOpenFile();
|
||||
if (id==BTN_SET_SCREENSAVER) EventSetSs();
|
||||
}
|
||||
break;
|
||||
|
||||
case evKey:
|
||||
GetKeys();
|
||||
if (select_list.ProcessKey(key_scancode)) { EventApply(); break; }
|
||||
if (key_scancode==SCAN_CODE_ENTER) { EventOpenFile(); break; }
|
||||
if (key_scancode==SCAN_CODE_DEL) { EventDeleteFile(); break; }
|
||||
if (key_scancode==SCAN_CODE_TAB) {
|
||||
id = tabs.active_tab+1;
|
||||
if(id==3)id=0;
|
||||
tabs.click(id + tabs.base_id);
|
||||
break;
|
||||
}
|
||||
for (i=select_list.cur_y+1; i<select_list.count; i++)
|
||||
{
|
||||
id = list.get(i) + strrchr(list.get(i), '/');
|
||||
if (ESBYTE[id]==key_ascii) || (ESBYTE[id]==key_ascii-32)
|
||||
{
|
||||
select_list.cur_y = i - 1;
|
||||
select_list.KeyDown();
|
||||
EventApply();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case evReDraw:
|
||||
draw_window();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_window()
|
||||
{
|
||||
sc.get();
|
||||
DefineAndDrawWindow(screen.w-WIN_W-9/2,80,WIN_W+9,WIN_H+4+skin_h,0x74,sc.work,WINDOW_HEADER,0);
|
||||
|
||||
DrawBar(0, 0, WIN_W, PANEL_H-2, sc.work); //top
|
||||
DrawBar(0, PANEL_H-2, LP-2, WIN_H-PANEL_H-LP+4, EDX); //left
|
||||
DrawBar(LIST_W+LP+20, PANEL_H-2, WIN_W-LIST_W-26, WIN_H-PANEL_H-LP+4, EDX); //right
|
||||
DrawBar(0, WIN_H-LP+2, WIN_W, LP-2, EDX); //bottom
|
||||
|
||||
tabs.draw();
|
||||
draw_icon_16w(tabs.x + TAB_P, LP+5, 17);
|
||||
draw_icon_16w(sizeof(t_skins)-1*8 + TAB_P + TAB_P + tabs.x, LP+5, 6);
|
||||
draw_icon_16w(sizeof(t_wallpapers)+sizeof(t_skins)-2*8 + TAB_P + TAB_P + TAB_P + tabs.x, LP+5, 61);
|
||||
|
||||
if (tabs.active_tab == TAB_SKINS)
|
||||
{
|
||||
DrawFrame(RIGHTx, PANEL_H+5, RIGHTw, RIGHTh, T_UI_PREVIEW);
|
||||
DrawUiElementsPreview(RIGHTx+20, PANEL_H+5, RIGHTh);
|
||||
}
|
||||
if (tabs.active_tab == TAB_WALLPAPERS)
|
||||
{
|
||||
DrawFrame(RIGHTx, PANEL_H+5, 180, 105, T_PICTURE_MODE);
|
||||
optionbox_stretch.draw(RIGHTx+14, PANEL_H+25);
|
||||
optionbox_tiled.draw(RIGHTx+14, PANEL_H+52);
|
||||
optionbox_auto.draw(RIGHTx+14, PANEL_H+79);
|
||||
DrawStandartCaptButton(RIGHTx, PANEL_H+130, BTN_SELECT_WALLP_FOLDER, T_SELECT_FOLDER);
|
||||
}
|
||||
if (tabs.active_tab == TAB_SCREENSAVERS)
|
||||
{
|
||||
draw_timeout();
|
||||
ss_timeout.line_col = sc.line;
|
||||
ss_timeout.frnt_col = sc.work;
|
||||
scrollbar_h_draw stdcall (#ss_timeout);
|
||||
DrawRectangle(RIGHTx, RIGHTy+25, RIGHTw-20, 15, sc.line);
|
||||
ESI = DrawStandartCaptButton(RIGHTx, PANEL_H + 65, BTN_TEST_SCREENSAVER, T_SS_PREVIEW);
|
||||
DrawStandartCaptButton(RIGHTx+ESI, PANEL_H + 65, BTN_SET_SCREENSAVER, T_SS_SET);
|
||||
}
|
||||
|
||||
$push select_list.cur_y
|
||||
SelectList_Init(
|
||||
LP,
|
||||
PANEL_H,
|
||||
LIST_W,
|
||||
WIN_H - LP - PANEL_H
|
||||
);
|
||||
$pop select_list.cur_y
|
||||
|
||||
SelectList_Draw();
|
||||
SelectList_DrawBorder();
|
||||
}
|
||||
|
||||
void draw_timeout()
|
||||
{
|
||||
miniprintf(#param, T_SS_TIMEOUT, ss_timeout.position+1);
|
||||
WriteTextWithBg(RIGHTx, PANEL_H, 0xD0, sc.work_text, #param, sc.work);
|
||||
}
|
||||
|
||||
void add_filesnames_into_the_list()
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
miniprintf(#param,"%s/",#folder_path);
|
||||
strcat(#param, io.dir.position(ESDWORD[j*4+fmas]));
|
||||
list.add(#param);
|
||||
}
|
||||
}
|
||||
|
||||
void Open_Dir()
|
||||
{
|
||||
int j;
|
||||
dword ext;
|
||||
select_list.ClearList();
|
||||
|
||||
if (io.dir.buffer) free(io.dir.buffer);
|
||||
io.dir.load(#folder_path,DIR_ONLYREAL);
|
||||
|
||||
if (fmas) free(fmas);
|
||||
fmas = malloc(io.dir.count * 4);
|
||||
|
||||
for (j=0; j<io.dir.count; j++)
|
||||
{
|
||||
strncpy(#param, io.dir.position(j), PATHLEN);
|
||||
strlwr(#param);
|
||||
ext = #param + strrchr(#param,'.');
|
||||
if (tabs.active_tab==TAB_SKINS) {
|
||||
if (!streq(ext,"skn")) continue;
|
||||
}
|
||||
if (tabs.active_tab==TAB_WALLPAPERS) {
|
||||
if (!streq(ext,"png")) && (!streq(ext,"jpg"))
|
||||
&& (!streq(ext,"jpeg")) && (!streq(ext,"bmp"))
|
||||
&& (!streq(ext,"gif")) continue;
|
||||
}
|
||||
ESDWORD[select_list.count*4 + fmas] = j;
|
||||
select_list.count++;
|
||||
}
|
||||
sort_by_name(0, select_list.count-1);
|
||||
|
||||
list.drop();
|
||||
//save current item for tab change
|
||||
//add default item
|
||||
if(tabs.active_tab == TAB_SKINS)
|
||||
{
|
||||
select_list.count++;
|
||||
list.add(#default_skin);
|
||||
add_filesnames_into_the_list();
|
||||
if (active_skin==-1) && (ESBYTE[#previous_skin])
|
||||
{
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
if (streq(list.get(j), #previous_skin)) {
|
||||
active_skin = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
select_list.cur_y = active_skin;
|
||||
} else {
|
||||
select_list.count++;
|
||||
list.add(#default_wallp);
|
||||
add_filesnames_into_the_list();
|
||||
if (active_wallpaper==-1) && (ESBYTE[#previous_wallp]=='\\')
|
||||
{
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
if (streq(list.get(j), #previous_wallp+4)) {
|
||||
active_wallpaper = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
select_list.cur_y = active_wallpaper;
|
||||
}
|
||||
|
||||
if (!select_list.count) notify(T_NO_FILES);
|
||||
if (select_list.cur_y>SL_VISIBLE) {
|
||||
select_list.first = -SL_VISIBLE/2 + select_list.cur_y;
|
||||
}
|
||||
select_list.CheckDoesValuesOkey();
|
||||
if (LIST_W) draw_window();
|
||||
}
|
||||
|
||||
void SelectList_DrawLine(dword i)
|
||||
{
|
||||
int draw_y = i*SELECT_LIST_ITEMH+PANEL_H;
|
||||
int i_abs = select_list.first + i;
|
||||
dword text_color = 0xFFFfff;
|
||||
dword bg_color = 0x000000;
|
||||
char filename_buf[PATHLEN];
|
||||
char* filename = #filename_buf;
|
||||
|
||||
strcpy(filename, list.get(i_abs));
|
||||
if (EAX = strrchr(filename,'/')) filename += EAX;
|
||||
if (ESBYTE[filename]=='T') && (ESBYTE[filename+1]=='_') filename+=2;
|
||||
EAX = math.min(strrchr(filename,'.')-1, LIST_W - 24 / 8);
|
||||
if(EAX) ESBYTE[filename+EAX] = '\0';
|
||||
|
||||
//save current item for tab change
|
||||
switch(tabs.active_tab) {
|
||||
CASE TAB_SKINS:
|
||||
active_skin = select_list.cur_y;
|
||||
if (!i_abs) filename = T_DEFAULT;
|
||||
BREAK;
|
||||
CASE TAB_WALLPAPERS:
|
||||
active_wallpaper = select_list.cur_y;
|
||||
if (!i_abs) filename = T_DEFAULT;
|
||||
BREAK;
|
||||
CASE TAB_SCREENSAVERS:
|
||||
active_screensaver = select_list.cur_y;
|
||||
if (!i_abs) filename = T_NO_SS;
|
||||
}
|
||||
|
||||
if (select_list.cur_y == i_abs) {
|
||||
text_color = sc.button;
|
||||
bg_color = sc.button_text;
|
||||
}
|
||||
DrawBar(select_list.x, draw_y, LIST_W, SELECT_LIST_ITEMH, text_color);
|
||||
WriteText(select_list.x+12,draw_y+select_list.text_y,select_list.font_type,bg_color, filename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GetIniSettings()
|
||||
{
|
||||
ini.section = "style";
|
||||
ini.GetString("default_skin", #default_skin, PATHLEN, 0);
|
||||
ini.GetString("default_wallp", #default_wallp, PATHLEN, 0);
|
||||
ini.GetString("skin", #previous_skin, PATHLEN, 0);
|
||||
ini.GetString("bg_param", #previous_wallp, PATHLEN, 0);
|
||||
|
||||
ini.section = "screensaver";
|
||||
ss_timeout.position = ini.GetInt("timeout", 10) - 1;
|
||||
ini.GetString("available", #ss_available, sizeof(ss_available), 0);
|
||||
ini.GetString("program", #previous_ss, PATHLEN, 0);
|
||||
}
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// EVENTS //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void EventTabSkinsClick()
|
||||
{
|
||||
miniprintf(#folder_path, "%s/res/skins", get_real_kolibrios_path());
|
||||
Open_Dir();
|
||||
}
|
||||
|
||||
void EventTabWallpappersClick()
|
||||
{
|
||||
if (opendir_path) {
|
||||
strcpy(#folder_path, #opendir_path);
|
||||
} else {
|
||||
miniprintf(#folder_path, "%s/res/wallpapers", get_real_kolibrios_path());
|
||||
}
|
||||
Open_Dir();
|
||||
}
|
||||
|
||||
void EventTabScreensaverClick()
|
||||
{
|
||||
dword j;
|
||||
char ssmas[sizeof(ss_available)];
|
||||
list.drop();
|
||||
select_list.ClearList();
|
||||
|
||||
select_list.count++;
|
||||
list.add("");
|
||||
|
||||
strcpy(#ssmas, #ss_available);
|
||||
do {
|
||||
j = strrchr(#ssmas, '|');
|
||||
if (ssmas[j]=='/') {
|
||||
strcpy(#param, #ssmas + j);
|
||||
} else {
|
||||
miniprintf(#param, "/sys/%s", #ssmas + j);
|
||||
}
|
||||
list.add(#param);
|
||||
ESBYTE[#ssmas + j - 1] = '\0';
|
||||
select_list.count++;
|
||||
} while (j);
|
||||
|
||||
if (active_screensaver == -1) && (ESBYTE[#previous_ss]) {
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
if (strstr(list.get(j), #previous_ss)) active_screensaver = j;
|
||||
}
|
||||
}
|
||||
select_list.cur_y = active_screensaver;
|
||||
|
||||
if (LIST_W) draw_window();
|
||||
}
|
||||
|
||||
void EventDeleteFile()
|
||||
{
|
||||
if (select_list.cur_y) DeleteFile(list.get(select_list.cur_y)); //no not delete default
|
||||
Open_Dir();
|
||||
EventApply();
|
||||
}
|
||||
|
||||
void EventSelectWallpFolder()
|
||||
{
|
||||
o_dialog.type = 2; //select folder
|
||||
OpenDialog_start stdcall (#o_dialog);
|
||||
if (o_dialog.status) EventTabWallpappersClick();
|
||||
}
|
||||
|
||||
void EventSetWallpMode(dword _stretch, _titled, _auto)
|
||||
{
|
||||
optionbox_stretch.checked = _stretch;
|
||||
optionbox_tiled.checked = _titled;
|
||||
optionbox_auto.checked = _auto;
|
||||
optionbox_tiled.redraw();
|
||||
optionbox_stretch.redraw();
|
||||
optionbox_auto.redraw();
|
||||
EventApply();
|
||||
}
|
||||
|
||||
void EventApply()
|
||||
{
|
||||
char kivparam[4096+10];
|
||||
dword file_name = list.get(select_list.cur_y);
|
||||
if (tabs.active_tab==TAB_SKINS)
|
||||
{
|
||||
strcpy(#cur_skin_path, list.get(select_list.cur_y));
|
||||
SetSystemSkin(#cur_skin_path);
|
||||
MoveSize(OLD, OLD, OLD, WIN_H+4+GetSkinHeight());
|
||||
}
|
||||
if (tabs.active_tab==TAB_WALLPAPERS)
|
||||
{
|
||||
SelectList_Draw();
|
||||
miniprintf(#kivparam, "\\S__%s", list.get(select_list.cur_y));
|
||||
if (optionbox_tiled.checked) || (!select_list.cur_y) kivparam[1]='T';
|
||||
if (optionbox_auto.checked) {
|
||||
file_name += strrchr(file_name, '/');
|
||||
if (ESBYTE[file_name] == 'T') && (ESBYTE[file_name+1] == '_') {
|
||||
kivparam[1]='T';
|
||||
}
|
||||
}
|
||||
RunProgram("/sys/media/kiv", #kivparam);
|
||||
}
|
||||
if (tabs.active_tab==TAB_SCREENSAVERS)
|
||||
{
|
||||
SelectList_Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void EventOpenFile()
|
||||
{
|
||||
switch (tabs.active_tab) {
|
||||
case TAB_SKINS:
|
||||
RunProgram("/sys/skincfg", list.get(select_list.cur_y));
|
||||
break;
|
||||
case TAB_WALLPAPERS:
|
||||
RunProgram("/sys/media/kiv", list.get(select_list.cur_y));
|
||||
break;
|
||||
case TAB_SCREENSAVERS:
|
||||
if(select_list.cur_y) {
|
||||
KillProcessByName("@ss", MULTIPLE);
|
||||
RunProgram(list.get(select_list.cur_y), "@ss");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventExit()
|
||||
{
|
||||
if (get_real_kolibrios_path()) && (ESBYTE[#cur_skin_path]) {
|
||||
ini.section = "style";
|
||||
ini.SetString("skin", #cur_skin_path, strlen(#cur_skin_path));
|
||||
}
|
||||
ExitProcess();
|
||||
}
|
||||
|
||||
void EventSetSs()
|
||||
{
|
||||
dword cur_ss = list.get(select_list.cur_y);
|
||||
ini.section = "screensaver";
|
||||
ini.SetString("program", cur_ss, strlen(cur_ss));
|
||||
ini.SetInt("timeout", ss_timeout.position+1);
|
||||
RestartProcessByName("/sys/@ss", MULTIPLE);
|
||||
}
|
||||
|
||||
stop:
|
||||
|
||||
char folder_path[PATHLEN];
|
||||
char cur_skin_path[PATHLEN];
|
||||
|
||||
char default_skin[PATHLEN];
|
||||
char default_wallp[PATHLEN];
|
||||
|
||||
char previous_skin[PATHLEN];
|
||||
char previous_wallp[PATHLEN];
|
||||
char previous_ss[PATHLEN];
|
||||
@@ -1,5 +0,0 @@
|
||||
@c-- /D=LANG_ENG appearance.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
if not exist appearance ( @pause )
|
||||
@@ -1,5 +0,0 @@
|
||||
@c-- /D=LANG_RUS appearance.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
if not exist appearance ( @pause )
|
||||
@@ -1,106 +0,0 @@
|
||||
#ifdef LANG_RUS
|
||||
char t_skins[] = " Стиль окон";
|
||||
char t_wallpapers[] = " Обои";
|
||||
char t_screensaver[] = " Скринсейвер";
|
||||
?define WINDOW_HEADER "Настройки оформления"
|
||||
?define T_SELECT_FOLDER "Выбрать папку"
|
||||
?define T_PICTURE_MODE " Положение картинки "
|
||||
?define T_CHECKBOX_STRETCH "Растянуть"
|
||||
?define T_CHECKBOX_TILED "Замостить"
|
||||
?define T_CHECKBOX_AUTO "Автоматически"
|
||||
?define T_UPDATE_DOCK "Обновлять Dock-панель"
|
||||
?define T_NO_FILES "'Поддерживаемые файлы не найдены' -E"
|
||||
?define T_UI_PREVIEW " Пример компонентов "
|
||||
?define T_SS_TIMEOUT "Интервал в минутах: %i "
|
||||
?define T_SS_PREVIEW "Просмотр"
|
||||
?define T_SS_SET "Установить"
|
||||
?define T_NO_SS "[Выключен]"
|
||||
?define T_DEFAULT "[По умолчанию]"
|
||||
#else
|
||||
char t_skins[] = " Skins";
|
||||
char t_wallpapers[] = " Wallpapers";
|
||||
char t_screensaver[] = " Screensaver";
|
||||
?define WINDOW_HEADER "Appearance"
|
||||
?define T_SELECT_FOLDER "Select folder"
|
||||
?define T_PICTURE_MODE " Picture Mode "
|
||||
?define T_CHECKBOX_STRETCH "Stretch"
|
||||
?define T_CHECKBOX_TILED "Tiled"
|
||||
?define T_CHECKBOX_AUTO "Auto"
|
||||
?define T_UPDATE_DOCK "Update Dock"
|
||||
?define T_NO_FILES "'No supported files were found' -E"
|
||||
?define T_UI_PREVIEW " Components Preview "
|
||||
?define T_SS_TIMEOUT "Wait in minutes: %i "
|
||||
?define T_SS_PREVIEW "View"
|
||||
?define T_SS_SET "Set"
|
||||
?define T_NO_SS "[Disable]"
|
||||
?define T_DEFAULT "[Default]"
|
||||
#endif
|
||||
|
||||
#define WIN_W 560
|
||||
#define WIN_H 445
|
||||
#define LIST_W 260
|
||||
#define PANEL_H 50
|
||||
#define LP 6 //LIST_PADDING
|
||||
#define SL_VISIBLE WIN_H - PANEL_H - LP / SELECT_LIST_ITEMH
|
||||
|
||||
#define RIGHTx LP + LIST_W + TAB_P + 30
|
||||
#define RIGHTy PANEL_H
|
||||
#define RIGHTw WIN_W - RIGHTx - LP - TAB_P
|
||||
#define RIGHTh 215
|
||||
|
||||
enum {
|
||||
TAB_SKINS,
|
||||
TAB_WALLPAPERS,
|
||||
TAB_SCREENSAVERS
|
||||
};
|
||||
|
||||
enum {
|
||||
BASE_TAB_BUTTON_ID=3,
|
||||
BTN_SELECT_WALLP_FOLDER=10,
|
||||
BTN_TEST_SCREENSAVER,
|
||||
BTN_SET_SCREENSAVER
|
||||
};
|
||||
|
||||
_ini ini = { "/sys/settings/system.ini" };
|
||||
|
||||
char default_dir[] = "/sys";
|
||||
od_filter filter2 = { 8, "TXT\0\0" };
|
||||
|
||||
_tabs tabs = { -sizeof(t_skins)-sizeof(t_wallpapers)-sizeof(t_screensaver)
|
||||
-3*8+WIN_W - TAB_P / 2, LP, NULL, BASE_TAB_BUTTON_ID };
|
||||
|
||||
scroll_bar ss_timeout = { RIGHTw-19,RIGHTx,15,RIGHTy+25,0,3,89,10,0,0xFFFfff,
|
||||
0xBBBbbb,0xeeeeee};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void sort_by_name(int a, b) // for the first call: a = 0, b = sizeof(mas) - 1
|
||||
{
|
||||
int j;
|
||||
int isn = a;
|
||||
if (a >= b) return;
|
||||
for (j = a; j <= b; j++) {
|
||||
if (strcmpi(io.dir.position(ESDWORD[j*4+fmas]), io.dir.position(ESDWORD[b*4+fmas]))<=0) {
|
||||
ESDWORD[isn*4+fmas] >< ESDWORD[j*4+fmas];
|
||||
isn++;
|
||||
}
|
||||
}
|
||||
sort_by_name(a, isn-2);
|
||||
sort_by_name(isn, b);
|
||||
}
|
||||
|
||||
dword get_real_kolibrios_path()
|
||||
{
|
||||
char real_kolibrios_path[256];
|
||||
if (!dir_exists("/kolibrios")) return 0;
|
||||
SetCurDir("/kolibrios");
|
||||
GetCurDir(#real_kolibrios_path, sizeof(real_kolibrios_path));
|
||||
return #real_kolibrios_path;
|
||||
}
|
||||
|
||||
void SelectList_LineChanged()
|
||||
{
|
||||
EventApply();
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
checkbox checkbox1 = { "Checkbox", true };
|
||||
more_less_box spinbox1 = { 23, 0, 999, "SpinBox" };
|
||||
edit_box edit_cmm = {180,NULL,NULL,0xffffff,0x94AECE,0xFFFfff,0xffffff,
|
||||
0x10000000,sizeof(param)-2,#param,0, 0b};
|
||||
char st_str[16];
|
||||
edit_box edit_st = {180,NULL,NULL,0xffffff,0x94AECE,0xFFFfff,0xffffff,
|
||||
0x10000000,sizeof(st_str)-2,#st_str,0, 0b};
|
||||
|
||||
|
||||
void DrawUiElementsPreview(dword x,y,h)
|
||||
{
|
||||
incn y2;
|
||||
spinbox1.draw(x, y2.set(y+30));
|
||||
WriteText(x, y2.inc(30), 0x90, sc.work_text, "C-- Edit");
|
||||
DrawEditBoxPos(x, y2.inc(20), #edit_cmm);
|
||||
WriteText(x, y2.inc(35), 0x90, sc.work_text, "Standard Edit");
|
||||
DrawStEditBoxPos(x, y2.inc(20), #edit_st);
|
||||
DrawStandartCaptButton(x, y+h-40, GetFreeButtonId(), "Button1");
|
||||
DrawStandartCaptButton(x+100, y+h-40, GetFreeButtonId(), "Button2");
|
||||
}
|
||||
|
||||
:void DrawStEditBoxPos(dword x,y, edit_box_pointer)
|
||||
{
|
||||
dword c_inactive = MixColors(sc.line, sc.work, 128);
|
||||
dword c_active = MixColors(sc.line, 0, 128);
|
||||
ESI = edit_box_pointer;
|
||||
ESI.edit_box.left = x;
|
||||
ESI.edit_box.top = y;
|
||||
ESI.edit_box.border_color = c_inactive;
|
||||
ESI.edit_box.focus_border_color = c_active;
|
||||
edit_box_draw stdcall (edit_box_pointer);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
if tup.getconfig("NO_CMM") ~= "" then return end
|
||||
if tup.getconfig("LANG") == "ru_RU"
|
||||
then C_LANG = "LANG_RUS"
|
||||
else C_LANG = "LANG_ENG" -- this includes default case without config
|
||||
end
|
||||
tup.rule("barscfg.c", "c-- /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "barscfg.com")
|
||||
Loaded 100 of 670 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user