Beispiel #1
0
/**
 * Set up a DMA transfer.
 * @param direction the direction of the transfer (DMA_READ or DMA_WRITE)
 * @param chan the channel
 * @param addr the address of the buffer
 * @param size number of bytes to transfer
 */
void Setup_DMA(enum DMA_Direction direction, int chan, void *addr_,
               ulong_t size) {
    uchar_t mode = 0;
    ulong_t addr = (ulong_t) addr_;

    /* Make sure parameters are sensible */
    KASSERT(direction == DMA_READ || direction == DMA_WRITE);
    KASSERT(VALID_CHANNEL(chan));
    KASSERT(IS_RESERVED(chan));
    KASSERT(VALID_MEM(addr, size));
    KASSERT(size > 0);
    /* elaborate because the otherwise working test wouldn't work if the DMA region was precisely 64K page aligned. */
    KASSERT0((((addr & 0xffff) == 0 && size <= 65536)) ||
             (size <= (0xffff - (addr & 0xffff))),
             "DMA region can't cross 64K boundary");

    /* Set up transfer mode */
    mode |= DMA_MODE_SINGLE;
    mode |= (direction == DMA_READ) ? DMA_MODE_READ : DMA_MODE_WRITE;
    mode |= (chan & 3);
    if (chan == 5)
        mode |= 0x10;           /* nspring testing, make this better if useful. */

    Debug("Setup_DMA(%s,%d,%x,%d)\n",
          direction == DMA_READ ? "DMA_READ" : "DMA_WRITE", chan, addr, size);
    Debug("Setup_DMA: mode=%02x\n", mode);
    Debug("DMA_ADDR_REG for channel is %02x\n", DMA_ADDR_REG(chan));
    Debug("DMA_PAGE_REG for channel is %02x\n", DMA_PAGE_REG(chan));
    Debug("DMA_COUNT_REG for channel is %02x\n", DMA_COUNT_REG(chan));

    /* Temporarily mask the DMA channel */
    Mask_DMA(chan);

    /* Write the transfer mode */
    Out_Byte(DMA_MODE_REG(chan), mode);

    /* Clear the byte pointer flip-flop */
    Out_Byte(DMA_CLEAR_FF_REG(chan), 0);        /* doesn't matter what value is written here */

    /* Write the transfer address (LSB, then MSB) */
    Out_Byte(DMA_ADDR_REG(chan), addr & 0xFF);
    Out_Byte(DMA_ADDR_REG(chan), (addr >> 8) & 0xFF);

    /* Write the page register */
    Out_Byte(DMA_PAGE_REG(chan), (addr >> 16) & 0xFF);

    /*
     * Write the count (LSB, then MSB)
     * Note that the count is one less that the number of bytes transferred
     */
    if (chan > 4) {
        size >>= 1;
    }                           /* words not bytes? */
Beispiel #2
0
void Hardware_Shutdown() {

    // works with > 1.3 qemu with the command line: -device isa-debug-exit,iobase=0x501
    Out_Byte(0x501, 0x00);

    // works on Bochs, and QEMU prior to 1.4
    Out_Byte(0x8900, 'S');
    Out_Byte(0x8900, 'h');
    Out_Byte(0x8900, 'u');
    Out_Byte(0x8900, 't');
    Out_Byte(0x8900, 'd');
    Out_Byte(0x8900, 'o');
    Out_Byte(0x8900, 'w');
    Out_Byte(0x8900, 'n');

    KASSERT0(false,
             "Hardware_Shutdown() failed: QEMU likely run with incorrect options.\n");
}
Beispiel #3
0
int Eth_Transmit(struct Net_Device *device, struct Net_Buf *nBuf,
                 uchar_t * destAddr, ushort_t type) {
    struct Ethernet_Header header;
    int rc;

    KASSERT(Interrupts_Enabled());

    /* all you have to do in this function is fill in the header. */
    TODO_P(PROJECT_RAW_ETHERNET,
           "construct the ethernet header for the destination, this device's address, and the type.");

    rc = Net_Buf_Prepend(nBuf, &header, sizeof(header), NET_BUF_ALLOC_COPY);
    if (rc != 0)
        return rc;

    ulong_t size = MAX(NET_BUF_SIZE(nBuf), ETH_MIN_DATA);       /* buffer size must be at least ETH_MIN_DATA, 
                                                                   even if we don't use it. */

    KASSERT0(size >= ETH_MIN_DATA, "input to Eth_Transmit should be at least ETH_MIN_DATA long");       /* paranoia. */

    void *buffer = Malloc(size);
    if (buffer == 0)
        return ENOMEM;

    rc = Net_Buf_Extract_All(nBuf, buffer);
    if (rc != 0) {
        Free(buffer);
        return rc;
    }

    Disable_Interrupts();
    device->transmit(device, buffer, size);
    Enable_Interrupts();

    return 0;
}