* 82559-fast-ethernet-multifunciton-pci-datasheet.pdf
*/
#include <acess.h>
-#include <IPStack/include/adapter_api.h>
+#include <IPStack/include/adapters_api.h>
#include <modules.h>
+#include <drv_pci.h>
+#include <timers.h>
+#include "pro100.h"
// === CONSTANTS ===
+#define NUM_STATIC_CARDS 2
const Uint16 caSupportedCards[][2] = {
{0x8086, 0x103D},
};
// === PROTOTYPES ===
int PRO100_Install(char **Arguments);
int PRO100_InitCard(tCard *Card);
-void PRO100_Cleanup(void);
+ int PRO100_Cleanup(void);
tIPStackBuffer *PRO100_WaitForPacket(void *Ptr);
int PRO100_SendPacket(void *Ptr, tIPStackBuffer *Buffer);
void PRO100_IRQHandler(int Num, void *Ptr);
-size_t PRO100_int_ReadEEPROM(tCard *Card, size_t Ofs, size_t Len, void *Buffer);
+Uint16 PRO100_int_ReadEEPROM(tCard *Card, size_t Ofs);
+
+static void _Write16(tCard *Card, int Ofs, Uint16 Val);
+static void _Write32(tCard *Card, int Ofs, Uint32 Val);
+static Uint16 _Read16(tCard *Card, int Ofs);
+static Uint32 _Read32(tCard *Card, int Ofs);
+static void _FlushWait(tCard *Card, int Delay);
+
// === GLOBALS ===
-MODULE_DEFINE(0, PRO100, PRO100_Install, PRO100_Cleanup, "IPStack", NULL);
+MODULE_DEFINE(0, 0x100, PRO100, PRO100_Install, PRO100_Cleanup, "IPStack", NULL);
tIPStack_AdapterType gPRO100_AdapterType = {
.Name = "PRO/100",
.Type = ADAPTERTYPE_ETHERNET_100M,
.Flags = 0,
.SendPacket = PRO100_SendPacket,
.WaitForPacket = PRO100_WaitForPacket
-
};
+tCard gaPRO100_StaticCards[NUM_STATIC_CARDS];
// === CODE ===
int PRO100_Install(char **Arguments)
{
+ int cardidx = 0;
+ for( int i = 0; i < ciNumSupportedCards; i ++ )
+ {
+ const Uint16 *ven_dev = caSupportedCards[i];
+ int pciid = -1;
+ while( -1 != (pciid = PCI_GetDevice(ven_dev[0], ven_dev[1], pciid)) )
+ {
+ Uint32 base = PCI_GetValidBAR(pciid, 0, PCI_BARTYPE_MEM32);
+ tCard *card;
+ if( cardidx < NUM_STATIC_CARDS ) {
+ card = &gaPRO100_StaticCards[cardidx++];
+ }
+ else {
+ card = malloc(sizeof(tCard));
+ }
+
+ card->MMIO = MM_MapHWPages(base, 1);
+
+ // TODO: Error check
+ PRO100_InitCard(card);
+
+ IPStack_Adapter_Add(&gPRO100_AdapterType, card, card->MAC.Bytes);
+ }
+ }
return MODULE_ERR_OK;
}
int PRO100_InitCard(tCard *Card)
{
// Card reset
- Card->MMIO->Port = PORT_SELECTIVERESET;
- // - Write Flush, wait 20us
- Card->MMIO->Port = PORT_SOFTWARERESET;
- // - Write Flush, wait 20us
+ _Write32(Card, REG_Port, PORT_SELECTIVERESET);
+ _FlushWait(Card, 20); // - Write Flush, wait 20us
+ _Write32(Card, REG_Port, PORT_SOFTWARERESET);
+ _FlushWait(Card, 20); // - Write Flush, wait 20us
// Read MAC address
Card->MAC.Words[0] = PRO100_int_ReadEEPROM(Card, 0);
Card->MAC.Words[1] = PRO100_int_ReadEEPROM(Card, 1);
Card->MAC.Words[2] = PRO100_int_ReadEEPROM(Card, 2);
+
+ // Create RX Descriptors
+
+ // Set RX Buffer base
+ _Write32(Card, REG_GenPtr, rx_desc_phys);
+ _Write32(Card, REG_Command, RX_CMD_ADDR_LOAD);
+
+ _Write32(Card, REG_GenPtr, 0);
+ _Write32(Card, REG_Command, RX_CMD_START);
return 0;
}
-void PRO100_Cleanup(void)
+int PRO100_Cleanup(void)
{
return 0;
}
-tIPStackBuffer *PRO100_WaitForPacket(void *Ptr)
+tIPStackBuffer *PRO100_WaitForPacket(void *Ptr)
{
+ return NULL;
}
int PRO100_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
{
-
+ return -1;
}
void PRO100_IRQHandler(int Num, void *Ptr)
Uint8 addr_len = 8;
Uint32 addr_data = ((EEPROM_OP_READ << addr_len) | Ofs) << 16;
- Card->MMIO->EEPROMCtrl = EEPROM_CTRL_CS | EEPROM_CTRL_SK;
- // Flush + 4us
-
+ _Write16( Card, REG_EEPROMCtrl, EEPROM_CTRL_CS | EEPROM_CTRL_SK );
+ _FlushWait(Card, 4); // Flush + 4us
+
+ Uint32 data = 0;
+
for( int i = 32; i --; )
{
- Uint8 ctrl = EEPROM_CTRL_CS | ((addr_data & (1 << i)) ? EEPROM_CTRL_DI : 0);
- Card->MMIO->EEPROMCtrl = ctrl;
- // Flush + 4us
- Card->MMIO->EEPROMCtrl = ctrl | EEPROM_CTRL_SK;
- // Flush + 4us
+ Uint16 ctrl = EEPROM_CTRL_CS | ((addr_data & (1 << i)) ? EEPROM_CTRL_DI : 0);
+ _Write16( Card, REG_EEPROMCtrl, ctrl );
+ _FlushWait(Card, 4); // Flush + 4us
+ _Write16( Card, REG_EEPROMCtrl, ctrl | EEPROM_CTRL_SK );
+ _FlushWait(Card, 4); // Flush + 4us
- ctrl = Card->MMIO->EEPROMCtrl;
+ ctrl = _Read16( Card, REG_EEPROMCtrl );
// Once the address is fully recieved, the card emits a zero bit
if( !(ctrl & EEPROM_CTRL_DO) && i > 16 )
{
i = 17;
}
- data = (data << 1) | (ctrl & EEPROM_CTRL_DO ? 1 : 0)
+ data = (data << 1) | (ctrl & EEPROM_CTRL_DO ? 1 : 0);
}
// Deslect chip
- Card->MMIO->EEPROMCtrl = 0;
- // Flush + 4us
+ _Write16( Card, REG_EEPROMCtrl, 0 );
+ _FlushWait(Card, 4); // Flush + 4us
return (data & 0xFFFF);
}
+
+static void _Write16(tCard *Card, int Ofs, Uint16 Val) { outw(Card->IOBase + Ofs, Val); }
+static void _Write32(tCard *Card, int Ofs, Uint32 Val) { outd(Card->IOBase + Ofs, Val); }
+static Uint16 _Read16(tCard *Card, int Ofs) { return inw(Card->IOBase + Ofs); }
+static Uint32 _Read32(tCard *Card, int Ofs) { return ind(Card->IOBase + Ofs); }
+
+static void _FlushWait(tCard *Card, int Delay)
+{
+ _Read16( Card, REG_Status );
+ if(Delay > 0)
+ {
+ Time_MicroSleep(Delay);
+ }
+}
+
/*
-
+ * Acess2 PRO/100 Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * pro100.h
+ * - Hardware header
*/
#ifndef _PRO100_H_
#define _PRO100_H_
-struct sCSR
-{
- Uint16 Status;
- Uint16 Command;
-
- Uint32 GenPtr;
- Uint32 Port;
-
- Uint16 FlashCtrl;
- Uint16 EEPROMCtrl;
-
- Uint32 MDICtrl;
- Uint32 RXDMACount;
-};
-
-#define STATUS_RUS_MASK 0x003C // Receive Unit Status
-#define STATUS_CUS_MASK 0x00C0 // Comamnd Unit Status
-#define STATUS_FCP 0x0100 // Flow Control Pause
-#define STATUS_ER 0x0200 // Early Recieve
-#define STATUS_SWI 0x0400 // Software Interrupt
-#define STATUS_MDI 0x0800 // Management Data Interrupt
-#define STATUS_RNR 0x1000 // Receive Not Ready
-#define STATUS_CNA 0x2000 // Command Unit not active
-#define STATUS_FR 0x4000 // Frame Recieved
-#define STATUS_CX 0x8000 // Command Unit executed
+#include "pro100_hw.h"
-#define CMD_RUC 0x0007
-#define CMD_CUC 0x00F0
-#define CMD_M 0x0100 // Interrupt Mask
-#define CMD_SI 0x0200 // Software Interrupt
+typedef struct sCard tCard;
-#define MDI_IE (1 << 29)
-#define MDI_RDY (1 << 28)
-
-#define EEPROM_CTRL_SK 0x01 //
-#define EEPROM_CTRL_CS 0x02
-#define EEPROM_CTRL_DI 0x04
-#define EEPROM_CTRL_DO 0x08
-
-enum ePortCommands {
- PORT_SOFTWARERESET = 0,
- PORT_SELFTEST = 1,
- PORT_SELECTIVERESET = 2,
-};
-
-struct sCommandBuffer
+struct sCard
{
- Uint16 Status;
- Uint16 Command;
- Uint32 Link;
+ Uint16 IOBase;
+ struct sCSR *MMIO;
- tIPStackBuffer *Buffer;
- tCommandBuffer *Next;
-} __align__(4);
+ union {
+ Uint8 Bytes[6];
+ Uint16 Words[3]; // Used to read the MAC from EEPROM
+ } MAC;
+
+ //tIPStackBuffer *TXBuffers[NUM_TX];
+};
#endif
--- /dev/null
+/*
+ * Acess2 PRO/100 Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * pro100_hw.h
+ * - Hardware header
+ */
+#ifndef _PRO100_HW_H_
+#define _PRO100_HW_H_
+
+enum ePro100_Regs {
+ REG_Status,
+ REG_Ack,
+ REG_Command,
+ REG_IntMask,
+
+ REG_GenPtr = 4,
+ REG_Port = 8,
+
+ REG_FlashCtrl = 12,
+ REG_EEPROMCtrl = 14,
+
+ REG_MDICtrl = 16,
+ REG_RXDMACnt = 20,
+};
+struct sCSR
+{
+ Uint16 Status;
+ Uint16 Command;
+
+ Uint32 GenPtr;
+ Uint32 Port;
+
+ Uint16 FlashCtrl;
+ Uint16 EEPROMCtrl;
+
+ Uint32 MDICtrl;
+ Uint32 RXDMACount;
+};
+
+#define STATUS_RUS_MASK 0x003C // Receive Unit Status
+#define STATUS_CUS_MASK 0x00C0 // Comamnd Unit Status
+#define STATUS_FCP 0x0100 // Flow Control Pause
+#define STATUS_ER 0x0200 // Early Recieve
+#define STATUS_SWI 0x0400 // Software Interrupt
+#define STATUS_MDI 0x0800 // Management Data Interrupt
+#define STATUS_RNR 0x1000 // Receive Not Ready
+#define STATUS_CNA 0x2000 // Command Unit not active
+#define STATUS_FR 0x4000 // Frame Recieved
+#define STATUS_CX 0x8000 // Command Unit executed
+
+#define CMD_RUC 0x0007
+#define CMD_CUC 0x00F0
+#define CMD_M 0x0100 // Interrupt Mask
+#define CMD_SI 0x0200 // Software Interrupt
+
+#define MDI_IE (1 << 29)
+#define MDI_RDY (1 << 28)
+
+#define EEPROM_CTRL_SK 0x01 //
+#define EEPROM_CTRL_CS 0x02
+#define EEPROM_CTRL_DI 0x04
+#define EEPROM_CTRL_DO 0x08
+
+#define EEPROM_OP_READ 0x06
+
+enum ePortCommands {
+ PORT_SOFTWARERESET = 0,
+ PORT_SELFTEST = 1,
+ PORT_SELECTIVERESET = 2,
+};
+
+enum eRXCommands {
+ RX_CMD_NOP,
+ RX_CMD_START,
+ RX_CMD_RESUME,
+ _RX_CMD_3,
+ RX_CMD_ABORT,
+ _RX_CMD_5,
+ RX_CMD_ADDR_LOAD,
+ RX_CMD_RESUMENR,
+};
+enum eCUCommands {
+ CU_CMD_NOP = 0<<4,
+ CU_CMD_START = 1<<4,
+ CU_CMD_RESUME = 2<<4,
+ CU_CMD_BASE = 6<<4,
+};
+
+enum eCommands {
+ CMD_Nop,
+ CMD_IAddrSetup,
+ CMD_Configure,
+ CMD_MulticastList,
+ CMD_Tx,
+};
+
+typedef struct sCommandUnit
+{
+ Uint16 Status;
+ Uint16 Command;
+ Uint32 Link;
+};
+
+typedef struct sRXBuffer tRXBuffer;
+
+struct sRXBuffer
+{
+ Uint16 Status;
+ Uint16 Command;
+ Uint32 Link; // Base from RX base
+
+ Uint32 RXBufAddr; // Unused according to qemu source
+ Uint16 Count;
+ Uint16 Size;
+} ALIGN(4);
+
+#endif
+