freedos-micro-python 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. freedos_micro_python/__init__.py +8 -0
  2. freedos_micro_python/cli.py +106 -0
  3. freedos_micro_python/gen_qstrdefs.py +275 -0
  4. freedos_micro_python/port/arch/bpstruct.h +2 -0
  5. freedos_micro_python/port/arch/cc.h +4 -0
  6. freedos_micro_python/port/arch/epstruct.h +1 -0
  7. freedos_micro_python/port/base64_uc386dos.c +164 -0
  8. freedos_micro_python/port/file_uc386dos.c +228 -0
  9. freedos_micro_python/port/lib/axtls/crypto/crypto.h +45 -0
  10. freedos_micro_python/port/lwip-arch-cc.h +46 -0
  11. freedos_micro_python/port/lwip_uc386dos.c +248 -0
  12. freedos_micro_python/port/lwipopts.h +117 -0
  13. freedos_micro_python/port/math_gamma.c +63 -0
  14. freedos_micro_python/port/modtime_uc386dos.c +60 -0
  15. freedos_micro_python/port/modtls_axtls_uc386dos.c +461 -0
  16. freedos_micro_python/port/mpconfigport.h +358 -0
  17. freedos_micro_python/port/mphal_uc386dos.c +103 -0
  18. freedos_micro_python/port/mphalport.h +11 -0
  19. freedos_micro_python/port/os_uc386dos.c +264 -0
  20. freedos_micro_python/port/path_uc386dos.c +307 -0
  21. freedos_micro_python/port/pktdrv_uc386dos.c +650 -0
  22. freedos_micro_python/port/qstrdefsport.h +2 -0
  23. freedos_micro_python/port/shutil_uc386dos.c +111 -0
  24. freedos_micro_python/port/tempfile_uc386dos.c +129 -0
  25. freedos_micro_python/port/time_real_uc386dos.c +77 -0
  26. freedos_micro_python/port/uc386_net_uc386dos.c +126 -0
  27. freedos_micro_python/port/urllib_parse_uc386dos.c +360 -0
  28. freedos_micro_python/port/urllib_uc386dos.c +29 -0
  29. freedos_micro_python/scripts/build.sh +641 -0
  30. freedos_micro_python/scripts/build_port.sh +241 -0
  31. freedos_micro_python/scripts/fetch.sh +238 -0
  32. freedos_micro_python-0.1.0.dist-info/METADATA +131 -0
  33. freedos_micro_python-0.1.0.dist-info/RECORD +37 -0
  34. freedos_micro_python-0.1.0.dist-info/WHEEL +5 -0
  35. freedos_micro_python-0.1.0.dist-info/entry_points.txt +2 -0
  36. freedos_micro_python-0.1.0.dist-info/licenses/LICENSE +25 -0
  37. freedos_micro_python-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,111 @@
1
+ // uc386-dos `shutil` module — file copy/move utilities backed by
2
+ // the libc open/read/write path (which routes through INT 21h via
3
+ // uc386's libc). Lean stdlib match — `copy` / `copyfile` / `move`
4
+ // are the everyday cases; rmtree / chown / chmod aren't useful on
5
+ // DOS so we don't ship them.
6
+ //
7
+ // `move` tries os.rename first (atomic for same-volume moves under
8
+ // DOS) and falls back to copy + unlink for cross-drive moves where
9
+ // rename returns an error.
10
+
11
+ #include <string.h>
12
+ #include <stdio.h>
13
+ #include <unistd.h>
14
+ #include <fcntl.h>
15
+
16
+ #include "py/runtime.h"
17
+ #include "py/objstr.h"
18
+ #include "py/mperrno.h"
19
+
20
+ // 4 KB buffer is a reasonable middle ground — small enough to live
21
+ // on the stack inside `_copy_stream` without bloating frame size,
22
+ // large enough that the per-call read/write syscall overhead doesn't
23
+ // dominate even on slow DOS disks.
24
+ #define SHUTIL_COPY_BUF_SIZE 4096
25
+
26
+ static void copy_stream(int src_fd, int dst_fd) {
27
+ char buf[SHUTIL_COPY_BUF_SIZE];
28
+ for (;;) {
29
+ int n = read(src_fd, buf, sizeof(buf));
30
+ if (n < 0) {
31
+ mp_raise_OSError(MP_EIO);
32
+ }
33
+ if (n == 0) {
34
+ break;
35
+ }
36
+ int written = 0;
37
+ while (written < n) {
38
+ int w = write(dst_fd, buf + written, n - written);
39
+ if (w <= 0) {
40
+ mp_raise_OSError(MP_EIO);
41
+ }
42
+ written += w;
43
+ }
44
+ }
45
+ }
46
+
47
+ // `shutil.copyfile(src, dst)` — overwrites dst if it exists.
48
+ // Returns dst (matching CPython).
49
+ static mp_obj_t shutil_copyfile(mp_obj_t src_in, mp_obj_t dst_in) {
50
+ const char *src = mp_obj_str_get_str(src_in);
51
+ const char *dst = mp_obj_str_get_str(dst_in);
52
+
53
+ int src_fd = open(src, 0); // O_RDONLY
54
+ if (src_fd < 0) {
55
+ mp_raise_OSError(MP_ENOENT);
56
+ }
57
+ // Open dst write+truncate. Our libc routes a writable open
58
+ // through INT 21h AH=0x3C (CREATE), which truncates if the
59
+ // file exists.
60
+ int dst_fd = open(dst, 1); // O_WRONLY -> our libc handles create-or-truncate
61
+ if (dst_fd < 0) {
62
+ close(src_fd);
63
+ mp_raise_OSError(MP_EIO);
64
+ }
65
+ copy_stream(src_fd, dst_fd);
66
+ close(src_fd);
67
+ close(dst_fd);
68
+ return dst_in;
69
+ }
70
+ static MP_DEFINE_CONST_FUN_OBJ_2(shutil_copyfile_obj, shutil_copyfile);
71
+
72
+ // `shutil.copy(src, dst)` — alias for copyfile here. CPython
73
+ // preserves permissions through this call but DOS has none worth
74
+ // preserving, so the simpler form suffices.
75
+ static mp_obj_t shutil_copy(mp_obj_t src_in, mp_obj_t dst_in) {
76
+ return shutil_copyfile(src_in, dst_in);
77
+ }
78
+ static MP_DEFINE_CONST_FUN_OBJ_2(shutil_copy_obj, shutil_copy);
79
+
80
+ // `shutil.move(src, dst)` — atomic rename when both ends sit on
81
+ // the same DOS volume; falls back to copy + unlink across volumes
82
+ // (which DOS rejects with INT 21h AH=0x56 → CF set, error 17).
83
+ static mp_obj_t shutil_move(mp_obj_t src_in, mp_obj_t dst_in) {
84
+ const char *src = mp_obj_str_get_str(src_in);
85
+ const char *dst = mp_obj_str_get_str(dst_in);
86
+
87
+ if (rename(src, dst) == 0) {
88
+ return dst_in;
89
+ }
90
+ // Cross-volume or other rename failure — fall back to
91
+ // copy + unlink.
92
+ shutil_copyfile(src_in, dst_in);
93
+ if (unlink(src) != 0) {
94
+ mp_raise_OSError(MP_EIO);
95
+ }
96
+ return dst_in;
97
+ }
98
+ static MP_DEFINE_CONST_FUN_OBJ_2(shutil_move_obj, shutil_move);
99
+
100
+ static const mp_rom_map_elem_t mp_module_shutil_globals_table[] = {
101
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_shutil) },
102
+ { MP_ROM_QSTR(MP_QSTR_copyfile), MP_ROM_PTR(&shutil_copyfile_obj) },
103
+ { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&shutil_copy_obj) },
104
+ { MP_ROM_QSTR(MP_QSTR_move), MP_ROM_PTR(&shutil_move_obj) },
105
+ };
106
+ static MP_DEFINE_CONST_DICT(mp_module_shutil_globals, mp_module_shutil_globals_table);
107
+
108
+ const mp_obj_module_t mp_module_shutil = {
109
+ .base = { &mp_type_module },
110
+ .globals = (mp_obj_dict_t *)&mp_module_shutil_globals,
111
+ };
@@ -0,0 +1,129 @@
1
+ // uc386-dos `tempfile` module — minimal CPython-compat shim.
2
+ //
3
+ // Surface:
4
+ // tempfile.gettempdir() → str (TEMP env var, falls back to "C:\\")
5
+ // tempfile.mktemp(suffix='', prefix='tmp', dir=None)
6
+ // → str path that doesn't exist yet
7
+ //
8
+ // We deliberately don't ship `mkstemp` (returns an fd) or
9
+ // `NamedTemporaryFile` (context manager) — both want to atomically
10
+ // create-and-open and DOS doesn't have O_EXCL semantics worth
11
+ // relying on. The CPython gotcha "mktemp is unsafe" applies here
12
+ // too, but the htget pattern that motivated the addition (download
13
+ // to a temp path, validate, rename) doesn't care: only one process
14
+ // is running at a time.
15
+
16
+ #include <string.h>
17
+ #include <stdio.h>
18
+
19
+ #include "py/runtime.h"
20
+ #include "py/objstr.h"
21
+ #include "py/mperrno.h"
22
+
23
+ // libc lookups — getenv comes from lib/i386_dos_libc.asm.
24
+ extern const char *getenv(const char *name);
25
+ // stat() probe to avoid handing out an existing path.
26
+ #include <sys/stat.h>
27
+
28
+ // Counter ratchets across mktemp() calls within a single REPL
29
+ // session. Combined with the BIOS-tick seed we get from PID-less
30
+ // DOS, this is enough collision avoidance for single-user
31
+ // scripting.
32
+ static unsigned tmp_counter = 0;
33
+
34
+ static mp_obj_t tempfile_gettempdir(void) {
35
+ const char *t = getenv("TEMP");
36
+ if (!t) {
37
+ t = getenv("TMP");
38
+ }
39
+ if (!t || !*t) {
40
+ // Fallback: root of the boot drive. Most FreeDOS systems
41
+ // boot off C:; if that's wrong the user can SET TEMP=...
42
+ t = "C:\\";
43
+ }
44
+ return mp_obj_new_str(t, strlen(t));
45
+ }
46
+ static MP_DEFINE_CONST_FUN_OBJ_0(tempfile_gettempdir_obj, tempfile_gettempdir);
47
+
48
+ // `tempfile.mktemp(suffix='', prefix='tmp', dir=None)` — return
49
+ // a string path that doesn't currently exist. Doesn't create the
50
+ // file (intentionally — caller decides open() flags).
51
+ static mp_obj_t tempfile_mktemp(size_t n_args, const mp_obj_t *pos_args,
52
+ mp_map_t *kw_args) {
53
+ static const mp_arg_t allowed[] = {
54
+ { MP_QSTR_suffix, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_)} },
55
+ { MP_QSTR_prefix, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_tmp)} },
56
+ { MP_QSTR_dir, MP_ARG_OBJ, {.u_obj = mp_const_none} },
57
+ };
58
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed)];
59
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed),
60
+ allowed, args);
61
+ const char *suffix = mp_obj_str_get_str(args[0].u_obj);
62
+ const char *prefix = mp_obj_str_get_str(args[1].u_obj);
63
+ const char *dir;
64
+ if (args[2].u_obj == mp_const_none) {
65
+ const char *t = getenv("TEMP");
66
+ if (!t) t = getenv("TMP");
67
+ if (!t || !*t) t = "C:\\";
68
+ dir = t;
69
+ } else {
70
+ dir = mp_obj_str_get_str(args[2].u_obj);
71
+ }
72
+
73
+ // Loop probing names until we find one stat() rejects.
74
+ char name[80];
75
+ struct stat st;
76
+ for (int attempt = 0; attempt < 1024; attempt++) {
77
+ unsigned n = ++tmp_counter;
78
+ // Build "<dir>\\<prefix><N><suffix>". Cap dir so the result
79
+ // fits the DOS 8.3-ish filesystem comfortably.
80
+ size_t dir_len = strlen(dir);
81
+ if (dir_len > 60) dir_len = 60;
82
+ memcpy(name, dir, dir_len);
83
+ size_t pos = dir_len;
84
+ if (pos > 0 && name[pos - 1] != '\\' && name[pos - 1] != '/') {
85
+ name[pos++] = '\\';
86
+ }
87
+ size_t prefix_len = strlen(prefix);
88
+ if (prefix_len > 8) prefix_len = 8;
89
+ memcpy(name + pos, prefix, prefix_len);
90
+ pos += prefix_len;
91
+ // 5-digit decimal counter.
92
+ char digits[6];
93
+ int dlen = 0;
94
+ unsigned v = n;
95
+ do {
96
+ digits[dlen++] = '0' + (v % 10);
97
+ v /= 10;
98
+ } while (v && dlen < 5);
99
+ // Pad to 5.
100
+ while (dlen < 5) digits[dlen++] = '0';
101
+ for (int i = dlen - 1; i >= 0; i--) {
102
+ name[pos++] = digits[i];
103
+ }
104
+ size_t suffix_len = strlen(suffix);
105
+ if (pos + suffix_len + 1 > sizeof(name)) {
106
+ mp_raise_OSError(MP_E2BIG);
107
+ }
108
+ memcpy(name + pos, suffix, suffix_len);
109
+ pos += suffix_len;
110
+ name[pos] = '\0';
111
+ if (stat(name, &st) != 0) {
112
+ return mp_obj_new_str(name, pos);
113
+ }
114
+ }
115
+ mp_raise_OSError(MP_EEXIST);
116
+ }
117
+ static MP_DEFINE_CONST_FUN_OBJ_KW(tempfile_mktemp_obj, 0, tempfile_mktemp);
118
+
119
+ static const mp_rom_map_elem_t mp_module_tempfile_globals_table[] = {
120
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tempfile) },
121
+ { MP_ROM_QSTR(MP_QSTR_gettempdir), MP_ROM_PTR(&tempfile_gettempdir_obj) },
122
+ { MP_ROM_QSTR(MP_QSTR_mktemp), MP_ROM_PTR(&tempfile_mktemp_obj) },
123
+ };
124
+ static MP_DEFINE_CONST_DICT(mp_module_tempfile_globals, mp_module_tempfile_globals_table);
125
+
126
+ const mp_obj_module_t mp_module_tempfile = {
127
+ .base = { &mp_type_module },
128
+ .globals = (mp_obj_dict_t *)&mp_module_tempfile_globals,
129
+ };
@@ -0,0 +1,77 @@
1
+ // Real time() / mktime() / gettimeofday() backed by the DOS RTC
2
+ // (INT 21h AH=0x2A + 0x2C via libc's _dos_get_datetime). axtls's
3
+ // cert verification path needs both:
4
+ // - mktime() to convert each cert's parsed notBefore/notAfter
5
+ // calendar fields into a Unix epoch second count
6
+ // - gettimeofday() to get the current epoch second to compare
7
+ // against those bounds (x509.c:506,513)
8
+ //
9
+ // The libc stubs we shipped at SSL bringup (returning 0 / a fake
10
+ // counter) made every cert look "currently valid forever," which
11
+ // is fine for CONFIG_SSL_CERT_VERIFICATION=undef but obviously
12
+ // wrong once the flag is on.
13
+ //
14
+ // Calendar→epoch uses Howard Hinnant's "days from civil"
15
+ // algorithm (no table lookups, no leap-year branches; works for
16
+ // any Gregorian year). For DOS dates (1980–2099) the year is
17
+ // always positive so we skip the negative-y branch.
18
+ //
19
+ // We replace libc.asm's `_time`, `_mktime`, `_gettimeofday`
20
+ // (those stubs are removed). The libc wrappers compiled into
21
+ // every TU's bundle now `extern` to these symbols.
22
+
23
+ #include <time.h>
24
+ #include <sys/time.h>
25
+
26
+ extern void dos_get_datetime(unsigned char out[7]);
27
+
28
+ // Returns days since 1970-01-01 for the given (year, month, day).
29
+ // Month is 1-12, day is 1-31. Assumes year >= 0 (DOS minimum is 1980).
30
+ static long days_from_civil(int y, unsigned m, unsigned d) {
31
+ y -= (m <= 2);
32
+ long era = y / 400;
33
+ unsigned yoe = (unsigned)(y - era * 400); // [0, 399]
34
+ unsigned m_adj = (m > 2) ? (m - 3) : (m + 9); // [0, 11], March=0
35
+ unsigned doy = (153u * m_adj + 2u) / 5u + d - 1u; // [0, 365]
36
+ unsigned doe = yoe * 365u + yoe / 4u - yoe / 100u + doy;
37
+ return era * 146097L + (long)doe - 719468L;
38
+ }
39
+
40
+ static time_t epoch_now(void) {
41
+ unsigned char raw[7];
42
+ dos_get_datetime(raw);
43
+ int year = (int)(raw[0] | (raw[1] << 8));
44
+ long days = days_from_civil(year, raw[2], raw[3]);
45
+ long secs_today = (long)raw[4] * 3600L + (long)raw[5] * 60L + (long)raw[6];
46
+ return (time_t)(days * 86400L + secs_today);
47
+ }
48
+
49
+ time_t time(time_t *t) {
50
+ time_t now = epoch_now();
51
+ if (t) {
52
+ *t = now;
53
+ }
54
+ return now;
55
+ }
56
+
57
+ time_t mktime(struct tm *tm) {
58
+ if (tm == 0) {
59
+ return (time_t)-1;
60
+ }
61
+ long days = days_from_civil(tm->tm_year + 1900,
62
+ (unsigned)(tm->tm_mon + 1),
63
+ (unsigned)tm->tm_mday);
64
+ long secs_today = (long)tm->tm_hour * 3600L
65
+ + (long)tm->tm_min * 60L
66
+ + (long)tm->tm_sec;
67
+ return (time_t)(days * 86400L + secs_today);
68
+ }
69
+
70
+ int gettimeofday(struct timeval *tv, void *tz) {
71
+ (void)tz;
72
+ if (tv) {
73
+ tv->tv_sec = epoch_now();
74
+ tv->tv_usec = 0; // DOS clock is second-precision
75
+ }
76
+ return 0;
77
+ }
@@ -0,0 +1,126 @@
1
+ // uc386-dos `uc386_net` module — control surface for the lwIP eth
2
+ // netif sitting on top of the INT 0x83 packet-driver shim.
3
+ //
4
+ // Surface (Python):
5
+ // uc386_net.eth_init(use_dhcp=True) -> rc:int
6
+ // Bring up the virtual eth netif. If use_dhcp, kicks off DHCP
7
+ // discovery; the address won't be ready until enough
8
+ // `lwip.callback()` ticks have run for the DHCP server to
9
+ // respond. Returns 0 on success, negative on error.
10
+ // uc386_net.eth_status() -> (ip, netmask, gateway, up:bool)
11
+ // IP/netmask/gateway as dotted-quad strings (zero-string when
12
+ // unset). `up` reflects netif_is_up() AND init has run.
13
+
14
+ #include <stdio.h>
15
+ #include <string.h>
16
+
17
+ #include "py/runtime.h"
18
+ #include "py/obj.h"
19
+
20
+ extern int uc386dos_eth_start(int dhcp_start_now);
21
+ extern void uc386dos_eth_set_addr(unsigned int ip, unsigned int mask, unsigned int gw);
22
+ extern unsigned int uc386dos_eth_ip(void);
23
+ extern unsigned int uc386dos_eth_netmask(void);
24
+ extern unsigned int uc386dos_eth_gateway(void);
25
+ extern int uc386dos_eth_is_up(void);
26
+ extern int uc386dos_eth_driver(void);
27
+ extern volatile unsigned int pktdrv_thunk_invocations;
28
+ extern volatile unsigned int pktdrv_thunk_phase0_count;
29
+ extern volatile unsigned int pktdrv_thunk_phase1_count;
30
+ extern unsigned int pktdrv_last_handle;
31
+ extern unsigned int pktdrv_dpmi_seg;
32
+ extern unsigned int pktdrv_dpmi_off;
33
+
34
+ static unsigned int parse_ip4(const char *s) {
35
+ unsigned int parts[4] = {0};
36
+ int idx = 0;
37
+ while (*s && idx < 4) {
38
+ unsigned int v = 0;
39
+ while (*s >= '0' && *s <= '9') {
40
+ v = v * 10 + (*s - '0');
41
+ s++;
42
+ }
43
+ parts[idx++] = v & 0xff;
44
+ if (*s == '.') s++;
45
+ }
46
+ return parts[0] | (parts[1] << 8) | (parts[2] << 16) | (parts[3] << 24);
47
+ }
48
+
49
+ static mp_obj_t mod_uc386_net_ip4_to_str(unsigned int addr) {
50
+ char buf[16];
51
+ int n = snprintf(buf, sizeof(buf), "%u.%u.%u.%u",
52
+ (unsigned)(addr & 0xff),
53
+ (unsigned)((addr >> 8) & 0xff),
54
+ (unsigned)((addr >> 16) & 0xff),
55
+ (unsigned)((addr >> 24) & 0xff));
56
+ if (n < 0 || (size_t)n >= sizeof(buf)) {
57
+ n = 0;
58
+ }
59
+ return mp_obj_new_str(buf, (size_t)n);
60
+ }
61
+
62
+ static mp_obj_t mod_uc386_net_eth_init(size_t n_args, const mp_obj_t *args) {
63
+ int use_dhcp = 1;
64
+ if (n_args > 0) {
65
+ use_dhcp = mp_obj_is_true(args[0]) ? 1 : 0;
66
+ }
67
+ int rc = uc386dos_eth_start(use_dhcp);
68
+ return MP_OBJ_NEW_SMALL_INT(rc);
69
+ }
70
+ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
71
+ mod_uc386_net_eth_init_obj, 0, 1, mod_uc386_net_eth_init);
72
+
73
+ static mp_obj_t mod_uc386_net_eth_status(void) {
74
+ mp_obj_t items[5];
75
+ items[0] = mod_uc386_net_ip4_to_str(uc386dos_eth_ip());
76
+ items[1] = mod_uc386_net_ip4_to_str(uc386dos_eth_netmask());
77
+ items[2] = mod_uc386_net_ip4_to_str(uc386dos_eth_gateway());
78
+ items[3] = uc386dos_eth_is_up() ? mp_const_true : mp_const_false;
79
+ // 0=none, 1="int83-sim", 2="pktdrv"
80
+ int drv = uc386dos_eth_driver();
81
+ const char *drv_name =
82
+ (drv == 2) ? "pktdrv" :
83
+ (drv == 1) ? "int83-sim" : "none";
84
+ items[4] = mp_obj_new_str(drv_name, strlen(drv_name));
85
+ return mp_obj_new_tuple(5, items);
86
+ }
87
+ static MP_DEFINE_CONST_FUN_OBJ_0(
88
+ mod_uc386_net_eth_status_obj, mod_uc386_net_eth_status);
89
+
90
+ static mp_obj_t mod_uc386_net_eth_set_static(mp_obj_t ip_obj, mp_obj_t mask_obj, mp_obj_t gw_obj) {
91
+ const char *ip_s = mp_obj_str_get_str(ip_obj);
92
+ const char *mask_s = mp_obj_str_get_str(mask_obj);
93
+ const char *gw_s = mp_obj_str_get_str(gw_obj);
94
+ uc386dos_eth_set_addr(parse_ip4(ip_s), parse_ip4(mask_s), parse_ip4(gw_s));
95
+ return mp_const_none;
96
+ }
97
+ static MP_DEFINE_CONST_FUN_OBJ_3(
98
+ mod_uc386_net_eth_set_static_obj, mod_uc386_net_eth_set_static);
99
+
100
+ static mp_obj_t mod_uc386_net_pktdrv_diag(void) {
101
+ mp_obj_t items[6];
102
+ items[0] = MP_OBJ_NEW_SMALL_INT(pktdrv_thunk_invocations);
103
+ items[1] = MP_OBJ_NEW_SMALL_INT(pktdrv_thunk_phase0_count);
104
+ items[2] = MP_OBJ_NEW_SMALL_INT(pktdrv_thunk_phase1_count);
105
+ items[3] = MP_OBJ_NEW_SMALL_INT(pktdrv_last_handle);
106
+ items[4] = MP_OBJ_NEW_SMALL_INT(pktdrv_dpmi_seg);
107
+ items[5] = MP_OBJ_NEW_SMALL_INT(pktdrv_dpmi_off);
108
+ return mp_obj_new_tuple(6, items);
109
+ }
110
+ static MP_DEFINE_CONST_FUN_OBJ_0(
111
+ mod_uc386_net_pktdrv_diag_obj, mod_uc386_net_pktdrv_diag);
112
+
113
+ static const mp_rom_map_elem_t mp_module_uc386_net_globals_table[] = {
114
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uc386_net) },
115
+ { MP_ROM_QSTR(MP_QSTR_eth_init), MP_ROM_PTR(&mod_uc386_net_eth_init_obj) },
116
+ { MP_ROM_QSTR(MP_QSTR_eth_status), MP_ROM_PTR(&mod_uc386_net_eth_status_obj) },
117
+ { MP_ROM_QSTR(MP_QSTR_eth_set_static), MP_ROM_PTR(&mod_uc386_net_eth_set_static_obj) },
118
+ { MP_ROM_QSTR(MP_QSTR_pktdrv_diag), MP_ROM_PTR(&mod_uc386_net_pktdrv_diag_obj) },
119
+ };
120
+ static MP_DEFINE_CONST_DICT(
121
+ mp_module_uc386_net_globals, mp_module_uc386_net_globals_table);
122
+
123
+ const mp_obj_module_t mp_module_uc386_net = {
124
+ .base = { &mp_type_module },
125
+ .globals = (mp_obj_dict_t *)&mp_module_uc386_net_globals,
126
+ };