Пример #1
0
/*
 * Update the location of the hardware cursor.
 */
static void Update_Cursor(void) {
    /*
     * The cursor location is a character offset from the beginning
     * of page memory (I think).
     */
    uint_t characterPos = (s_cons.row * NUMCOLS) + s_cons.col;
    uchar_t origAddr;

    /*
     * Save original contents of CRT address register.
     * It is considered good programming practice to restore
     * it to its original value after modifying it.
     */
    origAddr = In_Byte(CRT_ADDR_REG);
    IO_Delay();

    /* Set the high cursor location byte */
    Out_Byte(CRT_ADDR_REG, CRT_CURSOR_LOC_HIGH_REG);
    IO_Delay();
    Out_Byte(CRT_DATA_REG, (characterPos >> 8) & 0xff);
    IO_Delay();

    /* Set the low cursor location byte */
    Out_Byte(CRT_ADDR_REG, CRT_CURSOR_LOC_LOW_REG);
    IO_Delay();
    Out_Byte(CRT_DATA_REG, characterPos & 0xff);
    IO_Delay();

    /* Restore contents of the CRT address register */
    Out_Byte(CRT_ADDR_REG, origAddr);
}
Пример #2
0
/* called when an interrupt tells us to. */
static void NE2000_Do_Receive(struct Net_Device *device) {
    uchar_t currentBuffer;
    ulong_t baseAddr = device->baseAddr;
    ushort_t ringBufferPage;


    Out_Byte(baseAddr + NE2K_CR, NE2K_CR_PAGE1 + NE2K_CR_NODMA + NE2K_CR_STA);
    currentBuffer = In_Byte(baseAddr + NE2K1W_CURR);
    Out_Byte(baseAddr + NE2K_CR, NE2K_CR_PAGE0 + NE2K_CR_NODMA + NE2K_CR_STA);

    while (currentBuffer != In_Byte(baseAddr + NE2K0R_BNRY)) {
        ringBufferPage = In_Byte(baseAddr + NE2K0R_BNRY) << 8;

        /* Receive as a packet; enqueue for further processing */
        Net_Device_Receive(device, ringBufferPage);

        /* Read the current buffer register */
        Out_Byte(baseAddr + NE2K_CR,
                 NE2K_CR_PAGE1 + NE2K_CR_NODMA + NE2K_CR_STA);
        currentBuffer = In_Byte(baseAddr + NE2K1W_CURR);
        Out_Byte(baseAddr + NE2K_CR,
                 NE2K_CR_PAGE0 + NE2K_CR_NODMA + NE2K_CR_STA);

        //Print("Current buffer: %x\n", currentBuffer);
        //Print("Boundary pointer: %x\n", In_Byte(baseAddr + NE2K0R_BNRY));
    }
}
Пример #3
0
void  readDriveConfig(int drive)
{
    int i;
    short info[256];

    Out_Byte(IDE_DRIVE_HEAD_REGISTER, (drive == 0) ? IDE_DRIVE_0 : IDE_DRIVE_1);
    Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_IDENTIFY_DRIVE);

    while (In_Byte(IDE_STATUS_REGISTER) != 0x58);

    for (i=0; i < 256; i++) {
        info[i] = In_Word(IDE_DATA_REGISTER);
    }

    drives[drive].num_Cylinders = info[IDE_INDENTIFY_NUM_CYLINDERS];
    drives[drive].num_Heads = info[IDE_INDENTIFY_NUM_HEADS];
    drives[drive].num_SectorsPerTrack = info[IDE_INDENTIFY_NUM_SECTORS_TRACK];
    drives[drive].num_BytesPerSector = info[IDE_INDENTIFY_NUM_BYTES_SECTOR];

    Print ("Found IDE: Drive %d\n", drive);
    Print ("    %d cylinders, %d heads, %d sectors/tack, %d bytes/sector\n", 
        drives[drive].num_Cylinders, drives[drive].num_Heads,
        drives[drive].num_SectorsPerTrack, drives[drive].num_BytesPerSector);
    Print ("    Disk has %d blocks\n", IDE_getNumBlocks(drive));
}
Пример #4
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? */
Пример #5
0
/*
 * Put one character to the screen using the current cursor position
 * and attribute, scrolling if needed.  The caller should update
 * the cursor position once all characters have been written.
 */
static void Output_Literal_Character(int c) {
    int numSpaces;

    switch (c) {
        case '\n':
            Clear_To_EOL();
            Newline();
            break;

        case '\t':
            numSpaces = TABWIDTH - (s_cons.col % TABWIDTH);
            while (numSpaces-- > 0)
                Put_Graphic_Char(' ');
            break;

        default:
            Put_Graphic_Char(c);
            break;
    }

#ifndef NDEBUG
    /*
     * When compiled with --enable-port-e9-hack, Bochs will send writes
     * to port E9 to the console.  This helps tremendously with debugging,
     * because it allows debug Print() statements to be visible after
     * Bochs has exited.
     */
    Out_Byte(0xE9, c);
#endif
}
Пример #6
0
void shutMeDown() {
    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');
}
Пример #7
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');
}
Пример #8
0
void Init_IDE(void) {
    int errorCode;

    Print("Initializing IDE controller...\n");

    /* Reset the controller and drives */
    Out_Byte(IDE_DEVICE_CONTROL_REGISTER,
             IDE_DCR_NOINTERRUPT | IDE_DCR_RESET);
    Micro_Delay(100);
    Out_Byte(IDE_DEVICE_CONTROL_REGISTER, IDE_DCR_NOINTERRUPT);

/*
 * FIXME: This code doesn't work on Bochs 2.0.
 *    while ((In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_READY) == 0)
 *	;
 */

    /* This code does work on Bochs 2.0. */
    while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY) ;

    if(ideDebug)
        Print("About to run drive Diagnosis\n");

    Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_DIAGNOSTIC);
    while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY) ;
    errorCode = In_Byte(IDE_ERROR_REGISTER);
    if(ideDebug > 1)
        Print("ide: ide error register = %x\n", errorCode);

    /* Probe and register drives */
    int i;
    for(i = 0; i < IDE_MAX_DRIVES; i++) {
        if(readDriveConfig(i) == 0)
            ++numDrives;
    }
    if(ideDebug)
        Print("Found %d IDE drives\n", numDrives);

    /* Start request thread */
    if(numDrives > 0)
        Start_Kernel_Thread(IDE_Request_Thread, 0, PRIORITY_NORMAL, true,
                            "{IDE}");
}
Пример #9
0
static void NE2000_Interrupt_Handler(struct Interrupt_State *state) {
    struct Net_Device *device;
    ulong_t baseAddr;
    unsigned char isrMask;
    int rc;

    Begin_IRQ(state);
    DEBUG_NE2K("Handling NE2000 interrupt\n");

    rc = Get_Net_Device_By_IRQ(state->intNum - FIRST_EXTERNAL_INT, &device);
    if (rc != 0) {
        Print("NE2000: Could not identify interrupt number %d\n",
              state->intNum);
        goto fail;
    }

    baseAddr = device->baseAddr;
    isrMask = In_Byte(NE2K0R_ISR + baseAddr);

    // DEBUG_NE2K("ISR Mask: %x\n" , isrMask);

    if (isrMask & NE2K_ISR_RXE) {
        //Print("RSR: %x\n", In_Byte(NE2K0R_RSR + baseAddr));
        ++device->rxPacketErrors;
    }

    if (isrMask & NE2K_ISR_TXE) {
        //Print("TSR: %x\n", In_Byte(NE2K0R_TSR + baseAddr));
        ++device->txPacketErrors;
    }

    if (isrMask & NE2K_ISR_OVW) {
        //Print("Ring Buffer Overflow Encountered!!\n");
        NE2000_Handle_Ring_Buffer_Overflow(device);
    }

    if (isrMask & NE2K_ISR_PRX) {
        DEBUG_NE2K("Receiving packet\n");
        NE2000_Do_Receive(device);
        ++device->rxPackets;
    }

    if (isrMask & NE2K_ISR_PTX) {
        //Print("Packet transmitted\n");
        DEBUG_NE2K("Transmitted.\n");
        //Print("TSR: %x\n", In_Byte(NE2K0R_TSR + baseAddr));
        ++device->txPackets;
    }

  fail:

    Out_Byte(baseAddr + NE2K0R_ISR, isrMask);

    End_IRQ(state);
}
Пример #10
0
void NE2000_Reset(struct Net_Device *device) {
    ulong_t baseAddr = device->baseAddr;

    KASSERT(!Interrupts_Enabled());

    Out_Byte(baseAddr + NE2K_RESET_PORT, In_Byte(NE2K_RESET_PORT));

    while (In_Byte(baseAddr + NE2K0R_ISR) & NE2K_ISR_RST) {
        Print("NIC has not reset yet\n");
    }
}
Пример #11
0
void NE2000_Get_Dev_Hdr(struct Net_Device *device,
                        struct Net_Device_Header *hdr, ulong_t pageOffset) {
    unsigned int i;
    ulong_t baseAddr = device->baseAddr;
    ulong_t size = sizeof(struct Net_Device_Header) >> 1;
    ushort_t *buffer = (ushort_t *) hdr;

    /* Set the Command Register */
    Out_Byte(baseAddr + NE2K_CR, 0x22);

    /* Load the packet size into the registers */
    Out_Byte(baseAddr + NE2K0W_RBCR0, sizeof(struct Net_Device_Header));
    Out_Byte(baseAddr + NE2K0W_RBCR1, 0);

    /* Load the page start  into the RSARX registers */
    Out_Byte(baseAddr + NE2K0W_RSAR0, 0x00);
    Out_Byte(baseAddr + NE2K0W_RSAR1, pageOffset);

    /* Start the remote write */
    Out_Byte(baseAddr + NE2K_CR, NE2K_CR_DMA_RREAD | NE2K_CR_STA);

    /* Read the data in through the I/O port */
    for (i = 0; i < size; ++i) {
        buffer[i] = In_Word(baseAddr + NE2K_IO_PORT);
    }

}
Пример #12
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");
}
Пример #13
0
void Init_Timer(void) {
    /*
     * TODO: reprogram the timer to set the frequency.
     * In bochs, it defaults to 18Hz, which is actually pretty
     * reasonable.
     */

    Print("Initializing timer...\n");

    /* configure for default clock */
    Out_Byte(0x43, 0x36);
    Out_Byte(0x40, 0x00);
    Out_Byte(0x40, 0x00);

    /* Calibrate for delay loop */
    Calibrate_Delay();
    Print("Delay loop: %d iterations per tick\n", s_spinCountPerTick);

    /* Install an interrupt handler for the timer IRQ */
    Install_IRQ(TIMER_IRQ, &Timer_Interrupt_Handler);
    Enable_IRQ(TIMER_IRQ);
}
Пример #14
0
/*****************************************************************************
 *                                dump_proc
 *****************************************************************************/
PUBLIC void dump_proc(struct proc* p)
{
	Pixel color_err = {31,0,0,0};
	char info[STR_DEFAULT_LEN];
	int i;

	int dump_len = sizeof(struct proc);

	Out_Byte(CRTC_ADDR_REG, START_ADDR_H);
	Out_Byte(CRTC_DATA_REG, 0);
	Out_Byte(CRTC_ADDR_REG, START_ADDR_L);
	Out_Byte(CRTC_DATA_REG, 0);

	sprintf(info, "byte dump of proc_table[%d]:\n", p - proc_table); //printf(info, color_err);
	for (i = 0; i < dump_len; i++) {
		sprintf(info, "%x.", ((unsigned char *)p)[i]);
		printf(info);
	}

	printf("^^");

	printf("\n\n");
	sprintf(info, "ANY: 0x%x.\n", ANY); printf(info);
	sprintf(info, "NO_TASK: 0x%x.\n", NO_TASK); printf(info);
	printf("\n", color_err);

	sprintf(info, "ldt_sel: 0x%x.  ", p->ldt_sel); printf(info);
	sprintf(info, "ticks: 0x%x.  ", p->ticks); printf(info);
	sprintf(info, "priority: 0x%x.  ", p->priority); printf(info);
	sprintf(info, "pid: 0x%x.  ", p->pid); printf(info);
	sprintf(info, "name: %s.  ", p->name); printf(info);
	printf("\n");
	sprintf(info, "p_flags: 0x%x.  ", p->p_flags); printf(info);
	sprintf(info, "p_recvfrom: 0x%x.  ", p->p_recvfrom);printf(info);
	sprintf(info, "p_sendto: 0x%x.  ", p->p_sendto);printf(info);
	sprintf(info, "nr_tty: 0x%x.  ", p->nr_tty); printf(info);
	printf("\n");
	sprintf(info, "has_int_msg: 0x%x.  ", p->has_int_msg); printf(info);
}
Пример #15
0
void NE2000_Handle_Ring_Buffer_Overflow(struct Net_Device *device) {
    int txp, resend;
    ulong_t baseAddr = device->baseAddr;
    /* 1. Read and store the value of the TXP bit */
    txp = In_Byte(baseAddr + NE2K_CR) & NE2K_CR_TXP;

    /* 2. Issue the STOP command to the NIC */
    Out_Byte(baseAddr + NE2K_CR, 0x21);

    /* 3. Wait for at least 1.6 ms */
    IO_Delay();

    /* 4. Clear the NIC’s Remote Byte Count */
    Out_Byte(baseAddr + NE2K0W_RBCR0, 0x00);
    Out_Byte(baseAddr + NE2K0W_RBCR1, 0x00);

    /* 5. Handle resend */
    if (!txp) {
        resend = 0;
    } else {
        int isr = In_Byte(baseAddr + NE2K0R_ISR);
        if ((isr & NE2K_ISR_PTX) || (isr & NE2K_ISR_TXE)) {
            resend = 0;
        } else {
            resend = 1;
        }
    }

    /* 6. Place the NIC into loopback mode */
    Out_Byte(baseAddr + NE2K0W_TCR, 0x02);

    /* 7. Issue START command to the NIC */
    Out_Byte(baseAddr + NE2K_CR, 0x22);

    /* 8. Remove one or more packets from the receive buffer ring */
    NE2000_Do_Receive(device);

    /* 9. Reset the overwrite warning (OVW) bit in the ISR */
    Out_Byte(baseAddr + NE2K0R_ISR, NE2K_ISR_OVW);

    /* 10. Take the NIC out of loopback */
    Out_Byte(baseAddr + NE2K0W_TCR, 0x00);

    /* 11. Restart the interrupted transmit if resend = 1 */
    if (resend) {
        Out_Byte(baseAddr + NE2K_CR, 0x26);
    }
}
Пример #16
0
/*
 * Reset and calibrate the controller.
 * Return true is successful, false otherwise.
 */
static bool Reset_Controller(void)
{
    /* Reset */
    Out_Byte(FDC_DOR_REG, 0);
    /*Micro_Delay(1000); */

    /*
     * Enable fd0
     * TODO: we might want to support drives other than 0 eventually
     */
    Start_Motor(0);

    return Calibrate(0);
}
Пример #17
0
/*
 * Initialize the floppy controller.
 */
void Init_Floppy(void)
{
    uchar_t floppyByte;
    bool ready = false;
    bool good;

    Print("Initializing floppy controller...\n");

    /* Allocate memory for DMA transfers */
    s_transferBuf = (uchar_t*) Alloc_Page();

    /* Use CMOS to get floppy configuration */
    Out_Byte(CMOS_OUT, CMOS_FLOPPY_INDEX);
    floppyByte = In_Byte(CMOS_IN);
    Setup_Drive_Parameters(0, (floppyByte >> 4) & 0xF);
    Setup_Drive_Parameters(1, floppyByte & 0xF);

    /* Install floppy interrupt handler */
    Install_IRQ(FDC_IRQ, &Floppy_Interrupt_Handler);
    Enable_IRQ(FDC_IRQ);

    /* Reset and calibrate the controller. */
    Disable_Interrupts();
    good = Reset_Controller();
    Enable_Interrupts();
    if (!good) {
	Print("  Failed to reset controller!\n");
	goto done;
    }

    /* Reserve DMA channel 2. */
    if (!Reserve_DMA(FDC_DMA)) {
	Print("  Failed to reserve DMA channel\n");
	goto done;
    }

    /*
     * Driver is now ready for requests.
     * Start the request processing thread.
     */
    ready = true;
    Start_Kernel_Thread(Floppy_Request_Thread, 0, PRIORITY_NORMAL, true);

done:
    if (!ready)
	Print("  Floppy controller initialization FAILED\n");
}
Пример #18
0
/**
 * Reserve given DMA channel.
 * @param chan the channel to reserve
 * @return true if successful, false if not
 */
bool Reserve_DMA(int chan) {
    bool iflag = Begin_Int_Atomic();
    bool result = false;

    KASSERT(VALID_CHANNEL(chan));

    if (!IS_RESERVED(chan)) {
        /* Channel is available; unmask it. */
        Out_Byte(DMA_MASK_ONE_REG(chan), chan & 3);

        /* Mask channel as allocated */
        s_allocated |= (1 << chan);
        result = true;
    }

    End_Int_Atomic(iflag);

    return result;
}
Пример #19
0
void Init_IDE()
{
    int errorCode;

    while (In_Byte(IDE_STATUS_REGISTER) != 0x50);

    if (ideDebug) Print("About to run drive Diagnosis\n");

    Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_DIAGNOSTIC);
    while (!(In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_READY));
    errorCode = In_Byte(IDE_ERROR_REGISTER);

    readDriveConfig(0);
    if (errorCode & 0x80) {
        numDrives = 1;
    } else {
        numDrives = 2;
	readDriveConfig(1);
    }
}
Пример #20
0
/* actually reads the data out of the device */
void NE2000_Receive(struct Net_Device *device, void *buffer, ulong_t length,
                    ulong_t pageOffset) {
    ulong_t baseAddr = device->baseAddr;

    KASSERT(!Interrupts_Enabled());

    int i;
    int newLength = length >> 1;
    unsigned short *newBuffer = (unsigned short *)buffer;

    /* Set the Command Register */
    Out_Byte(baseAddr + NE2K_CR, 0x22);

    Out_Byte(baseAddr + NE2K0W_RCR, 0x0C);

    /* Load the packet size into the registers */
    Out_Byte(baseAddr + NE2K0W_RBCR0, length & 0xFF);
    Out_Byte(baseAddr + NE2K0W_RBCR1, length >> 8);

    /* Load the page start  into the RSARX registers */
    Out_Byte(baseAddr + NE2K0W_RSAR0, pageOffset & 0xFF);
    Out_Byte(baseAddr + NE2K0W_RSAR1, pageOffset >> 8);

    /* Start the remote write */
    Out_Byte(baseAddr + NE2K_CR, NE2K_CR_DMA_RREAD | NE2K_CR_STA);

    /* Read the data in through the I/O port */
    for (i = 0; i < newLength; ++i) {
        newBuffer[i] = In_Word(baseAddr + NE2K_IO_PORT);
    }

    /* Receive the last byte of data if we have an odd length */
    if (length & 0x1) {
        ((uchar_t *) buffer)[length - 1] = In_Byte(baseAddr + NE2K_IO_PORT);
    }

    /* Ack the remote DMA interrupt */
    Out_Byte(baseAddr + NE2K0R_ISR, NE2K_ISR_RDC);

    device->rxBytes += length;
}
Пример #21
0
void Init_8139()
{
	cur_tx = 0;
	cur_rx = 0;

	/* Reset the chip */
	Out_Byte(RTL8139_CR, CmdReset);

	//while( In_Byte(RTL8139_CR) != 0 )
		/*udelay(10)*/;

	/* Unlock Config[01234] and BMCR register writes */
	Out_Byte(RTL8139_9346CR, Cfg9346_Unlock);

	/* Enable Tx/Rx before setting transfer thresholds */
	Out_Byte(RTL8139_CR, CmdRxEnb | CmdTxEnb);

	/* Using 32K ring */
	Out_DWord(RTL8139_RCR, RxCfgRcv32K | RxNoWrap | (7 << RxCfgFIFOShift) | (7 << RxCfgDMAShift)
				 | AcceptBroadcast | AcceptMyPhys);

//	Out_DWord(RTL8139_TCR, RxCfgRcv32K | RxNoWrap | (7 << RxCfgFIFOShift) | (7 << RxCfgDMAShift));

	Out_DWord(RTL8139_TCR, TxIFG96 | (6 << TxDMAShift) | (8 << TxRetryShift));

	/* Lock Config[01234] and BMCR register writes */
	Out_Byte(RTL8139_9346CR, Cfg9346_Lock);

	/* init Rx ring buffer DMA address */
	rx_buf = Malloc(RX_BUF_LEN);
	Out_DWord(RTL8139_RBSTART, (uint_t)rx_buf);

	/* init Tx buffer DMA addresses (4 registers) */
	tx_buf = Malloc(TX_BUF_SIZE * 4);
	int i;
	for(i = 0; i < 4; i++)
		Out_DWord(RTL8139_TSAD0 + (i * 4), ((uint_t)tx_buf) + (i * TX_BUF_SIZE));

	/* missed packet counter */
	Out_DWord(RTL8139_MPC, 0);

	// rtl8139_set_rx_mode does some stuff here.
	Out_DWord(RTL8139_RCR, In_DWord(RTL8139_RCR) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
				AcceptAllPhys);

	for(i = 0; i < 8; i++)
		Out_Byte(RTL8139_MAR0 + i, 0xff);

	/* no early-rx interrupts */
	Out_Word(RTL8139_MULINT, In_Word(RTL8139_MULINT) & MultiIntrClear);

	/* make sure RxTx has started */
	if(!(In_Byte(RTL8139_CR) & CmdRxEnb) || !(In_Byte(RTL8139_CR) & CmdTxEnb))
		Out_Byte(RTL8139_CR, CmdRxEnb | CmdTxEnb);

	/* Enable all known interrupts by setting the interrupt mask. */
	Out_Word(RTL8139_IMR, rtl8139_intr_mask);

	Install_IRQ(RTL8139_IRQ, rtl8139_interrupt);
  	Enable_IRQ(RTL8139_IRQ);

	PrintBoth("8139 initialized\n");
}
Пример #22
0
/*
 * Write a block at the logical block number indicated.
 */
static int IDE_Write(int driveNum, int blockNum, char *buffer) {
    int i;
    int head;
    int sector;
    int cylinder;
    short *bufferW;
    int reEnable = 0;

    if (driveNum < 0 || driveNum > (numDrives - 1)) {
        return IDE_ERROR_BAD_DRIVE;
    }

    if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) {
        return IDE_ERROR_INVALID_BLOCK;
    }

    if (Interrupts_Enabled()) {
        Disable_Interrupts();
        reEnable = 1;
    }

    /* now compute the head, cylinder, and sector */
    sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1;
    cylinder = blockNum / (drives[driveNum].num_Heads *
                           drives[driveNum].num_SectorsPerTrack);
    head = (blockNum / drives[driveNum].num_SectorsPerTrack) %
           drives[driveNum].num_Heads;

    if (ideDebug) {
        Print("request to write block %d\n", blockNum);
        Print("    head %d\n", head);
        Print("    cylinder %d\n", cylinder);
        Print("    sector %d\n", sector);
    }

    Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1);
    Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector);
    Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder));
    Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder));
    Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(driveNum) | head);

    Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_WRITE_SECTORS);


    /* wait for the drive */
    while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);

    bufferW = (short *)buffer;
    for (i = 0; i < 256; i++) {
        Out_Word(IDE_DATA_REGISTER, bufferW[i]);
    }

    if (ideDebug)
        Print("About to wait for Write \n");

    /* wait for the drive */
    while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);

    if (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) {
        Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER));
        return IDE_ERROR_DRIVE_ERROR;
    }

    if (reEnable)
        Enable_Interrupts();

    return IDE_ERROR_NO_ERROR;
}
Пример #23
0
/*
 * Read a block at the logical block number indicated.
 */
static int IDE_Read(int driveNum, int blockNum, char *buffer) {
    int i;
    int head;
    int sector;
    int cylinder;
    short *bufferW;
    int reEnable = 0;

    if(driveNum < 0 || driveNum > (numDrives - 1)) {
        if(ideDebug)
            Print("ide: invalid drive %d\n", driveNum);
        return IDE_ERROR_BAD_DRIVE;
    }

    if(blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) {
        if(ideDebug)
            Print("ide: invalid block %d\n", blockNum);
        return IDE_ERROR_INVALID_BLOCK;
    }

    /* now compute the head, cylinder, and sector */
    sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1;
    cylinder = blockNum / (drives[driveNum].num_Heads *
                           drives[driveNum].num_SectorsPerTrack);
    head = (blockNum / drives[driveNum].num_SectorsPerTrack) %
        drives[driveNum].num_Heads;

    if(ideDebug >= 2) {
        Print("request to read block %d\n", blockNum);
        Print("    head %d, cylinder %d, sector %d\n", head, cylinder,
              sector);
        // Print ("    cylinder %d\n", cylinder);
        // Print ("    sector %d\n", sector);
    }
#ifndef NS_INTERRUPTABLE_NO_GLOBAL_LOCK
    reEnable = Begin_Int_Atomic();
#endif

    Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1);
    Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector);
    Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder));
    Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder));
    Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(driveNum) | head);

    Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_READ_SECTORS);

    if(ideDebug > 2)
        Print("About to wait for Read \n");

    /* wait for the drive */
    while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY) ;
    if(In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) {
        Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER));
        return IDE_ERROR_DRIVE_ERROR;
    }

    if(ideDebug > 2)
        Print("got buffer \n");

    bufferW = (short *)buffer;
    for(i = 0; i < 256; i++) {
        bufferW[i] = In_Word(IDE_DATA_REGISTER);
    }
    if(ideDebug > 2)
        Print("read buffer \n");

#ifndef NS_INTERRUPTABLE_NO_GLOBAL_LOCK
    End_Int_Atomic(reEnable);
#endif

    return IDE_ERROR_NO_ERROR;
}
Пример #24
0
void NE2000_Transmit(struct Net_Device *device, void *buffer, ulong_t length) {

    ulong_t baseAddr = device->baseAddr;

    KASSERT(!Interrupts_Enabled());

    unsigned int i;
    unsigned int newLength = length >> 1;
    unsigned short *newBuffer = (unsigned short *)buffer;

    /* Make sure we aren't currently transmitting */
    if (In_Byte(baseAddr + NE2K_CR) & NE2K_CR_TXP) {
        Print("ERROR - Currently transmitting\n");
        return;
    }

    /* Reset the card */
    NE2000_Reset(device);

    /* Set the Command Register */
    Out_Byte(baseAddr + NE2K_CR, 0x22);

    /* Handle the read before write bug */
    Out_Byte(baseAddr + NE2K0W_RBCR0, 0x42);
    Out_Byte(baseAddr + NE2K0W_RBCR1, 0x00);
    Out_Byte(baseAddr + NE2K0W_RSAR0, 0x42);
    Out_Byte(baseAddr + NE2K0W_RSAR1, 0x00);
    Out_Byte(baseAddr + NE2K_CR, NE2K_CR_DMA_RREAD + NE2K_CR_STA);
    Out_Byte(baseAddr + NE2K0R_ISR, NE2K_ISR_RDC);

    /* Load the packet size into the registers */
    Out_Byte(baseAddr + NE2K0W_RBCR0, length & 0xFF);
    Out_Byte(baseAddr + NE2K0W_RBCR1, length >> 8);

    /* Load the page start  into the RSARX registers */
    Out_Byte(baseAddr + NE2K0W_RSAR0, 0x00);
    Out_Byte(baseAddr + NE2K0W_RSAR1, NE2K_TRANSMIT_PAGE);

    /* Start the remote write */
    Out_Byte(baseAddr + NE2K_CR, NE2K_CR_DMA_RWRITE | NE2K_CR_STA);

    /* Write the data to the I/O port */
    for (i = 0; i < newLength; ++i) {
        Out_Word(baseAddr + NE2K_IO_PORT, newBuffer[i]);
    }

    /* Send the last byte of data if we have an odd length */
    if (length & 0x1) {
        Out_Word(baseAddr + NE2K_IO_PORT, ((uchar_t *) buffer)[length - 1]);
    }


    /* Wait for transmit remote DMA */
    while ((In_Byte(baseAddr + NE2K0R_ISR) & NE2K_ISR_RDC) == 0) {
        Print("Waiting on remote DMA for transmit \n");
    }

    /* Ack the interrupt */
    Out_Byte(baseAddr + NE2K0R_ISR, NE2K_ISR_RDC);

    /* Now that Remote DMA is complete, set up the transmit */

    /* Store the transmit page in the transmit register */
    Out_Byte(baseAddr + NE2K0W_TPSR, NE2K_TRANSMIT_PAGE);

    /* Set transmit byte count */
    Out_Byte(baseAddr + NE2K0W_TBCR0, length & 0xFF);
    Out_Byte(baseAddr + NE2K0W_TBCR1, length >> 8);

    /* Issue transmit command */
    Out_Byte(baseAddr + NE2K_CR, NE2K_CR_NODMA | NE2K_CR_STA | NE2K_CR_TXP);

    device->txBytes += length;
}
Пример #25
0
static int readDriveConfig(int drive) {
    int i;
    int status;
    short info[256];
    char devname[BLOCKDEV_MAX_NAME_LEN];
    int rc;

    if (ideDebug > 1)
        Print("ide: about to read drive config for drive #%d\n", drive);

    Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(drive));
    Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_IDENTIFY_DRIVE);
    while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);

    status = In_Byte(IDE_STATUS_REGISTER);
    /*
     * simulate failure
     * status = 0x50;
     */
    if ((status & IDE_STATUS_DRIVE_DATA_REQUEST)) {
        Print("ide: probe found ATA drive\n");
        /* drive responded to ATA probe */
        for (i = 0; i < 256; i++) {
            info[i] = In_Word(IDE_DATA_REGISTER);
        }

        drives[drive].num_Cylinders = info[IDE_INDENTIFY_NUM_CYLINDERS];
        drives[drive].num_Heads = info[IDE_INDENTIFY_NUM_HEADS];
        drives[drive].num_SectorsPerTrack =
            info[IDE_INDENTIFY_NUM_SECTORS_TRACK];
        drives[drive].num_BytesPerSector =
            info[IDE_INDENTIFY_NUM_BYTES_SECTOR];
    } else {
        /* try for ATAPI */
        Out_Byte(IDE_FEATURE_REG, 0);   /* disable dma & overlap */

        Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(drive));
        Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_ATAPI_IDENT_DRIVE);
        while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
        status = In_Byte(IDE_STATUS_REGISTER);
        Print("status is %x\n", status);
        if ((status & IDE_STATUS_DRIVE_DATA_REQUEST)) {
            Print("ide: found atapi drive\n");
        } else {
            Print("ide: found no drive %d\n", drive);
        }
        return -1;
    }

    Print("    ide%d: cyl=%d, heads=%d, sectors=%d\n", drive,
          drives[drive].num_Cylinders, drives[drive].num_Heads,
          drives[drive].num_SectorsPerTrack);

    /* Register the drive as a block device */
    snprintf(devname, sizeof(devname), "ide%d", drive);
    rc = Register_Block_Device(devname, &s_ideDeviceOps, drive, 0,
                               &s_ideWaitQueue, &s_ideRequestQueue);
    if (rc != 0)
        Print("  Error: could not create block device for %s\n", devname);

    return 0;
}
Пример #26
0
static void Stop_Motor(int drive)
{
    Out_Byte(FDC_DOR_REG,
	FDC_DOR_DMA_ENABLE | FDC_DOR_RESET_DISABLE | FDC_DOR_DRIVE_SELECT(0));
}
Пример #27
0
/*
 * Write a byte to the data register.
 */
static void Floppy_Out(uchar_t val)
{
    Wait_For_MRQ(FDC_STATUS_READY_WRITE);
    Out_Byte(FDC_DATA_REG, val);
}
Пример #28
0
void NE2000_Complete_Receive(struct Net_Device *device,
                             struct Net_Device_Header *hdr) {
    /* Advance the boundary pointer */
    Out_Byte(device->baseAddr + NE2K0W_BNRY, hdr->next);
}
Пример #29
0
/*
 * Read a block at the logical block number indicated.
 */
int IDE_Read(int driveNum, int blockNum, char *buffer)
{
    int i;
    int head;
    int sector;
    int cylinder;
    short *bufferW;

    if (driveNum < 0 || driveNum > (numDrives-1)) {
        return IDE_ERROR_BAD_DRIVE;
    }

    if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) {
        return IDE_ERROR_INVALID_BLOCK;
    }

    /* now compute the head, cylinder, and sector */
    sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1;
    cylinder = blockNum / (drives[driveNum].num_Heads * 
     	drives[driveNum].num_SectorsPerTrack);
    head = (blockNum / drives[driveNum].num_SectorsPerTrack) % 
        drives[driveNum].num_Heads;

    if (ideDebug) {
	Print ("request to read block %d\n", blockNum);
	Print ("    head %d\n", head);
	Print ("    cylinder %d\n", cylinder);
	Print ("    sector %d\n", sector);
    }

    Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1);
    Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector);
    Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder));
    Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder));
    if (driveNum == 0) {
	Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_0 | head);
    } else if (driveNum == 1) {
	Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_1 | head);
    }

    Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_READ_SECTORS);

    if (ideDebug) Print("About to wait for Read \n");

    /* wait for the drive */
    while (!(In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_READY));

    if (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) {
	Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER));
	return IDE_ERROR_DRIVE_ERROR;
    }

    if (ideDebug) Print("got buffer \n");

    bufferW = (short *) buffer;
    for (i=0; i < 256; i++) {
        bufferW[i] = In_Word(IDE_DATA_REGISTER);
    }

    return IDE_ERROR_NO_ERROR;
}
Пример #30
0
/**
 * Initialize the DMA controllers.
 */
void Init_DMA(void) {
    Print("Initializing DMA Controller...\n");

    /* Reset the controller */
    Out_Byte(DMA_MASTER_CLEAR_REG, 0);
}