【问题标题】:How to list network devices in NASM (custom OS)如何在 NASM(自定义操作系统)中列出网络设备
【发布时间】:2015-11-08 00:14:48
【问题描述】:

我有一个完全内置在 NASM 中的自定义、类似 DOS 的操作系统(没有 C 代码)。它非常简陋(它确实有一个 FAT 文件系统、几个应用程序、处于实模式等)。我想编写一个命令来列出当前连接的所有网络设备(网卡)。

我的假设是这样的:我需要为网卡编写一个驱动程序(为简单起见,我将它手动放在内核中,因此不存在动态加载),但该驱动程序只需提供卡的名称,网卡实际上不需要工作。我如何告诉操作系统将该功能精确地连接到那个网卡?这就是我所担心的,我不知道操作系统通常如何将硬件与代码(其驱动程序)相匹配。

【问题讨论】:

  • 这些设备是否在 PCI 总线上?如果是这样,您可以获得设备和供应商 ID 并将它们与驱动程序匹配。 wiki.osdev.org/PCI 。如果使用旧的 Legacy ISA 类型设备,您通常必须查询特定端口(对于大多数供应商而言不同)以确定设备是否以特定方式响应,然后将其与驱动程序匹配。
  • @MichaelPetch 我使用的是 2014 年的 Macbook Air 13",它说 这台计算机不包含任何 PCI 卡或设备。如果您安装或连接了 PCI 卡或设备,请确保它们已正确安装。
  • @MichaelPetch 我所拥有的:Interfaces: en0: Card Type: AirPort Extreme (0x14E4, 0x117) Firmware Version: Broadcom BCM43xx 1.0 (7.15.159.13.12) MAC Address: 9c:f3:87:bb:08:70 Locale: ETSI Country Code: GB Supported PHY Modes: 802.11 a/b/g/n/ac Supported Channels: ... Wake On Wireless: Supported AirDrop: Supported Status: Connected
  • 您是在 OS/X 下运行操作系统还是直接启动到您的操作系统?
  • @MichaelPetch 哇,这些信息太棒了,非常感谢!我看到NE2000有很多资源,我相信我会找到有用的。

标签: networking x86 nasm osdev real-mode


【解决方案1】:

由于您的 cmets 显示您的 Dosbox 支持 NE2000 卡,因此下面的代码应该检测到 NE2000 卡的存在(假设端口基数为 0x300)。代码是我写的一个 DOS COM 程序,应该可以用nasm ne2kchk.asm -fbin -o ne2kchk.com这样的命令编译

NS_DATAPORT    EQU    0x10    ; NatSemi-defined port window offset.
NE_DATAPORT    EQU    0x10    ; NatSemi-defined port window offset.
NS_RESET       EQU    0x1f    ; Issue a read to reset, a write to clear.

NE1SM_START_PG EQU    0x20    ; First page of TX buffer
NE1SM_STOP_PG  EQU    0x40    ; Last page +1 of RX ring
NESM_START_PG  EQU    0x40    ; First page of TX buffer
NESM_STOP_PG   EQU    0x80    ; Last page +1 of RX ring

E8390_CMD      EQU    0x00    ; The command register (for all pages)
E8390_STOP     EQU    0x01    ; Stop and reset the chip
E8390_START    EQU    0x02    ; Start the chip, clear reset
E8390_RREAD    EQU    0x08    ; Remote read
E8390_NODMA    EQU    0x20    ; Remote DMA
E8390_PAGE0    EQU    0x00    ; Select page chip registers
E8390_PAGE1    EQU    0x40    ; using the two high-order bits
E8390_PAGE2    EQU    0x80
E8390_PAGE3    EQU    0xC0    ; Page 3 is invalid on the real 8390.

E8390_RXOFF    EQU    0x20    ; EN0_RXCR: Accept no packets
E8390_TXOFF    EQU    0x02    ; EN0_TXCR: Transmitter off

               ; Page 0 register offsets.
EN0_CLDALO     EQU    0x01    ; Low byte of current local dma addr  RD
EN0_STARTPG    EQU    0x01    ; Starting page of ring bfr WR
EN0_CLDAHI     EQU    0x02    ; High byte of current local dma addr     RD
EN0_STOPPG     EQU    0x02    ; Ending page +1 of ring bfr WR
EN0_BOUNDARY   EQU    0x03    ; Boundary page of ring bfr RD WR
EN0_TSR        EQU    0x04    ; Transmit status reg RD
EN0_TPSR       EQU    0x04    ; Transmit starting page WR
EN0_NCR        EQU    0x05    ; Number of collision reg RD
EN0_TCNTLO     EQU    0x05    ; Low     byte of tx byte count WR
EN0_FIFO       EQU    0x06    ; FIFO RD
EN0_TCNTHI     EQU    0x06    ; High byte of tx byte count WR
EN0_ISR        EQU    0x07    ; Interrupt status reg RD WR
EN0_CRDALO     EQU    0x08    ; low byte of current remote dma address RD
EN0_RSARLO     EQU    0x08    ; Remote start address reg 0
EN0_CRDAHI     EQU    0x09    ; high byte, current remote dma address RD
EN0_RSARHI     EQU    0x09    ; Remote start address reg 1
EN0_RCNTLO     EQU    0x0a    ; Remote byte count reg WR
EN0_RCNTHI     EQU    0x0b    ; Remote byte count reg WR
EN0_RSR        EQU    0x0c    ; rx status reg RD
EN0_RXCR       EQU    0x0c    ; RX configuration reg WR
EN0_TXCR       EQU    0x0d    ; TX configuration reg WR
EN0_COUNTER0   EQU    0x0d    ; Rcv alignment error counter RD
EN0_DCFG       EQU    0x0e    ; Data configuration reg WR
EN0_COUNTER1   EQU    0x0e    ; Rcv CRC error counter RD
EN0_IMR        EQU    0x0f    ; Interrupt mask reg WR
EN0_COUNTER2   EQU    0x0f    ; Rcv missed frame error counter RD

PORT_BASE      EQU    0x300   ; Default base port

[BITS 16]

    org 0x100

section .text

start:
    push   cs
    pop    ds

    ; Probe for NE2000 card

    ; Try non destructive test first
    mov    dx, PORT_BASE+E8390_CMD
    in     al, dx
    cmp    al, 0xff
    jz     .s_notfound

    ; Attempt potentially destuctive tests
    mov    al, E8390_NODMA | E8390_PAGE1 | E8390_STOP
    mov    dx, PORT_BASE+E8390_CMD
    out    dx, al    ; Receive alignment error counter
    mov    dx, PORT_BASE+EN0_COUNTER0
    in     al, dx
    mov    cl, al    ; Save to REGD (CL)
    mov    al, 0xff
    out    dx, al
    mov    al, E8390_NODMA | E8390_PAGE0
    mov    dx, PORT_BASE+E8390_CMD
    out    dx, al
    mov    dx, PORT_BASE+EN0_COUNTER0
    in     al, dx    ; Clear the counter by reading.
    test   al, al
    jz     .s_found  ; If al is clear then card was found

    ; Card not found
.s_notfound:
    xchg   al, cl    ; Temporarily save al to avoid clobber
    out    dx, al
    mov    ah, 0x09
    mov    dx, notfound_str
    int    0x21
    xchg   al, cl    ; Restore al. al = error value to return
    jmp    .s_exit

    ; Card found
.s_found:
    mov    ah, 0x09
    mov    dx, found_str
    int    0x21
    xor    al, al    ; Clear the error code

    ; exit with al = errcode
.s_exit:
    mov    ah, 0x4C
    int    0x21

notfound_str db "NE2000 not found", 0x0a, 0x0d, "$"
found_str    db "NE2000 found", 0x0a, 0x0d, "$"

上面的代码是我在 Debian nictool 代码here 中找到的“C”代码的改编。它可以在文件 ne2k-diags.c 中找到。 rtl8019 似乎有更多信息 (datasheets),它是 NE2000 的克隆。这些设备的核心 8390NIC 记录在 here。 8390 文档讨论了如何发送和接收数据。我基于我的“C”代码的摘录是:

printf("Checking the ethercard at %#3x.\n", port_base);
{   int regd;
    long ioaddr = port_base;

    outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
    regd = inb_p(ioaddr + 0x0d);
    printk("  Receive alignment error counter (%#lx) is %2.2x\n",
           ioaddr + 0x0d, regd);
    outb_p(0xff, ioaddr + 0x0d);
    outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
    inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
    if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
        outb(regd, ioaddr + 0x0d);  /* Restore the old values. */
        printk("  Failed initial NE2000 probe, value %2.2x.\n",
               inb(ioaddr + EN0_COUNTER0));
    } else
        printk("  Passed initial NE2000 probe, value %2.2x.\n",
               inb(ioaddr + EN0_COUNTER0));

}

上面的代码是初始探测,但同一文件中有更多“C”代码试图检测某些特定变体并查询卡签名。

【讨论】:

  • 在编辑了一些东西以使其适合我的操作系统框架后,它可以完美运行!非常感谢!顺便说一句,为什么那些被称为破坏性测试?是不是因为您使用了out 指令(这可能会以不希望的方式影响卡)?
  • 我把它写成一个 COM 程序的主要原因是它可以在 Dosbox 中运行以进行测试,所以你可以很容易地测试它是否正常工作,但是我用所有 16 位代码完成了它,所以它会是相当直接地适应您的操作系统。至于破坏性测试,更正它现在以in 开头(读取不太可能导致问题的端口)。如果存在 NE2k 卡,则应返回非 0xff 值。其他设备(在 DosBox 中可能没有问题)可能会映射到 0x300,如果写入它们可能会表现不佳(挂起等)。
  • 在您的内核探测中,您可以尝试修改它以循环此代码并检查这些地址(首先是 0x300,因为它更标准) 0x300, 0x280, 0x320, 0x340, 0x360 通过使 PORT_BASE a多变的 。这些是最有可能找到卡片的地方。也有可能(不一定在 DOSBox 中)安装了 2 个或更多卡。
猜你喜欢
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
  • 2017-09-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多