4 * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
14 } csaCOMPAT_DEVICES[] = {
15 {0x10EC, 0x8029}, // Realtek 8029
16 {0x10EC, 0x8129} // Realtek 8129
18 #define NUM_COMPAT_DEVICES (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0]))
20 enum eNe2k_Page0Read {
21 COMMAND = 0, //!< the master command register
22 CLDA0, //!< Current Local DMA Address 0
23 CLDA1, //!< Current Local DMA Address 1
24 BNRY, //!< Boundary Pointer (for ringbuffer)
25 TSR, //!< Transmit Status Register
26 NCR, //!< collisions counter
27 FIFO, //!< (for what purpose ??)
28 ISR, //!< Interrupt Status Register
29 CRDA0, //!< Current Remote DMA Address 0
30 CRDA1, //!< Current Remote DMA Address 1
31 RSR = 0xC //!< Receive Status Register
34 enum eNe2k_Page0Write {
35 PTART = 1, //!< page start (init only)
36 PSTOP, //!< page stop (init only)
37 TPSR = 4, //!< transmit page start address
38 TBCR0, //!< transmit byte count (low)
39 TBCR1, //!< transmit byte count (high)
40 RSAR0 = 8, //!< remote start address (lo)
41 RSAR1, //!< remote start address (hi)
42 RBCR0, //!< remote byte count (lo)
43 RBCR1, //!< remote byte count (hi)
44 RCR, //!< receive config register
45 TCR, //!< transmit config register
46 DCR, //!< data config register (init)
47 IMR //!< interrupt mask register (init)
51 typedef struct sNe2k_Card {
52 Uint16 IOBase; //!< IO Port Address from PCI
53 Uint8 IRQ; //!< IRQ Assigned from PCI
55 int NextMemPage; //!< Next Card Memory page to use
63 int Ne2k_Install(char **Arguments);
64 Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
67 MODULE_DEFINE(0, 0x0032, Ne2k, Ne2k_Install, NULL, NULL);
68 tDevFS_Driver gNe2k_DriverInfo = {
72 .ACLs = &gVFS_ACL_EveryoneRW,
73 .Flags = VFS_FFLAG_DIRECTORY
76 Uint16 gNe2k_BaseAddress;
77 int giNe2k_CardCount = 0;
81 * \fn int Ne2k_Install(char **Options)
82 * \brief Installs the NE2000 Driver
84 int Ne2k_Install(char **Options)
88 // --- Scan PCI Bus ---
91 for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
93 giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
98 gpNe2k_Cards = malloc( giNe2k_CardCount * sizeof(tCard) );
99 memsetd(gpNe2k_Cards, 0, giNe2k_CardCount * sizeof(tCard) / 4);
100 for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
102 count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
103 for( j = 0; j < count; j ++,k ++ )
105 id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j );
107 base = PCI_AssignPort( id, 0, 0x20 );
108 gpNe2k_Cards[ k ].IOBase = base;
109 gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
110 gpNe2k_Cards[ k ].NextMemPage = 1;
112 //Install IRQ6 Handler
113 IRQ_Set(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler);
116 outb( base + 0x1F, inb(base + 0x1F) );
117 while( (inb( base+ISR ) & 0x80) == 0 );
118 outb( base + ISR, 0x80 );
121 outb( base + COMMAND, 0x21 ); // No DMA and Stop
122 outb( base + DCR, 0x49 ); // Set WORD mode
123 outb( base + IMR, 0x00 );
124 outb( base + ISR, 0xFF );
125 outb( base + RCR, 0x20 ); // Reciever to Monitor
126 outb( base + TCR, 0x02 ); // Transmitter OFF
127 outb( base + RBCR0, 6*4 ); // Remote Byte Count
128 outb( base + RBCR1, 0 );
129 outb( base + RSAR0, 0 ); // Clear Source Address
130 outb( base + RSAR1, 0 );
131 outb( base + COMMAND, 0x0A ); // Remote Read, Start
134 gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10); inb(base+0x10);
135 gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10); inb(base+0x10);
136 gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10); inb(base+0x10);
137 gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10); inb(base+0x10);
138 gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10); inb(base+0x10);
139 gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10); inb(base+0x10);
141 outb( base+PSTART, 0x60); // Set Receive Start
142 outb( base+BNRY, 0x7F); // Set Boundary Page
143 outb( base+PSTOP, 0x80); // Set Stop Page
144 outb( base+ISR, 0xFF ); // Clear all ints
145 outb( base+CMD, 0x22 ); // No DMA, Start
146 outb( base+IMR, 0x3F ); // Set Interupt Mask
147 outb( base+RCR, 0x8F ); // Set WRAP and allow all packet matches
148 outb( base+TCR, 0x00 ); // Set Normal Transmitter mode
149 outb( base+TPSR, 0x40); // Set Transmit Start
153 Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]);
154 Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]);
155 Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]);
156 Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]);
157 Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]);
158 Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]);
161 Log("[NE2K]: Card #%i: IRQ=%i, Base=0x%x, ",
162 k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].PortBase,
163 gpNe2k_Cards[ k ].Buffer);
164 Log("MAC Address %x:%x:%x:%x:%x:%x\n",
165 gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1],
166 gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3],
167 gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5]
171 gpNe2k_Cards[ k ].Name[0] = '0'+k;
172 gpNe2k_Cards[ k ].Name[1] = '\0';
173 gpNe2k_Cards[ k ].Node.NumACLs = 1;
174 gpNe2k_Cards[ k ].Node.ACLs = gVFS_ACL_EveryoneRW;
175 gpNe2k_Cards[ k ].Node.CTime = now();
176 gpNe2k_Cards[ k ].Node.Write = Ne2k_Write;
180 DevFS_AddDevice( &gNe2k_DriverInfo );
186 * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
188 Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
190 tCard *Card = (tCard*)Node->ImplPtr;
192 // Sanity Check Length
193 if(Length > 0xFFFF) return 0;
195 outb(Card->IOBase + COMMAND, 0|0x22); // Page 0, Start, NoDMA
197 outb(Card->IOBase + RBCR0, Count & 0xFF);
198 outb(Card->IOBase + RBCR1, Count >> 8);
199 // Clear Remote DMA Flag
200 outb(Card->IOBase + ISR, 0x40); // Bit 6
202 outb(Card->IOBase + RSAR0, 0x00); // Page Offset
203 outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length)); // Page Offset
208 * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
210 Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)