#include <sys/types.h>
#include <lib/libsa/stand.h>
#include <libx68k.h>
#include <lib/libkern/libkern.h>
#include <dev/ic/dp8390reg.h>
#include <dev/ic/ne2000reg.h>
#include "dp8390.h"
#include "ne.h"
#define NE_BASEREG neaddr
#define NE_ASIC_BASEREG (NE_BASEREG + NE2000_ASIC_OFFSET * 2)
#define NIC_PORT(x) (NE_BASEREG + (x) * 2)
#define NIC_INB(x) inb(NIC_PORT(x))
#define NIC_OUTB(x, b) outb(NIC_PORT(x), (b))
#define NE_16BIT
#define DELAY(x) delay(x)
#define ASIC_PORT(x) (NE_ASIC_BASEREG + (x) * 2)
#define ASIC_INB(x) inb(ASIC_PORT(x))
#define ASIC_INW(x) inw(ASIC_PORT(x))
#define ASIC_OUTB(x, b) outb(ASIC_PORT(x), (b))
#define ASIC_OUTW(x, b) outw(ASIC_PORT(x), (b))
uint8_t eth_myaddr[6];
int
EtherInit(unsigned char *myadr)
{
uint8_t romdata[16];
uint8_t tmp;
int i;
printf("ne: trying iobase=0x%x\n", NE_BASEREG);
dp8390_iobase = NE_BASEREG;
dp8390_membase = 16384;
#ifdef NE_16BIT
dp8390_memsize = 16384;
#else
dp8390_memsize = 8192;
#endif
dp8390_cr_proto = ED_CR_RD2;
dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS;
#ifdef NE_16BIT
dp8390_dcr_reg |= ED_DCR_WTS;
#endif
tmp = ASIC_INB(NE2000_ASIC_RESET);
DELAY(10000);
ASIC_OUTB(NE2000_ASIC_RESET, tmp);
DELAY(5000);
NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
DELAY(5000);
tmp = NIC_INB(ED_P0_CR);
if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) !=
(ED_CR_RD2 | ED_CR_STP)) {
goto out;
}
tmp = NIC_INB(ED_P0_ISR);
if ((tmp & ED_ISR_RST) != ED_ISR_RST) {
goto out;
}
NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
for (i = 0; i < 100; i++) {
if ((NIC_INB(ED_P0_ISR) & ED_ISR_RST) == ED_ISR_RST) {
NIC_OUTB(ED_P0_ISR, ED_ISR_RST);
break;
}
DELAY(100);
}
printf("ne: found\n");
NIC_OUTB(ED_P0_RCR, ED_RCR_MON);
#ifdef NE_16BIT
NIC_OUTB(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS | ED_DCR_WTS);
#else
NIC_OUTB(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
#endif
#if 0
NIC_OUTB(ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT);
NIC_OUTB(ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT);
#endif
ne2000_readmem(0, romdata, sizeof(romdata));
for (i = 0; i < 6; i++)
myadr[i] = eth_myaddr[i] = romdata[i * 2];
if (dp8390_config())
goto out;
return 1;
out:
return 0;
}
void
EtherStop(void)
{
uint8_t tmp;
dp8390_stop();
tmp = ASIC_INB(NE2000_ASIC_RESET);
DELAY(10000);
ASIC_OUTB(NE2000_ASIC_RESET, tmp);
DELAY(5000);
NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
DELAY(5000);
}
void
ne2000_writemem(uint8_t *src, int dst, size_t len)
{
size_t i;
int maxwait = 100;
NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
NIC_OUTB(ED_P0_ISR, ED_ISR_RDC);
NIC_OUTB(ED_P0_RBCR0, len);
NIC_OUTB(ED_P0_RBCR1, len >> 8);
NIC_OUTB(ED_P0_RSAR0, dst);
NIC_OUTB(ED_P0_RSAR1, dst >> 8);
NIC_OUTB(ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
#ifdef NE_16BIT
for (i = 0; i < len; i += 2, src += 2)
ASIC_OUTW(NE2000_ASIC_DATA, *(uint16_t *)src);
#else
for (i = 0; i < len; i++)
ASIC_OUTB(NE2000_ASIC_DATA, *src++);
#endif
while (((NIC_INB(ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) && --maxwait)
DELAY(1);
if (maxwait == 0)
printf("ne2000_writemem: failed to complete\n");
}
void
ne2000_readmem(int src, uint8_t *dst, size_t amount)
{
size_t i;
NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
if (amount & 1)
++amount;
NIC_OUTB(ED_P0_RBCR0, amount);
NIC_OUTB(ED_P0_RBCR1, amount >> 8);
NIC_OUTB(ED_P0_RSAR0, src);
NIC_OUTB(ED_P0_RSAR1, src >> 8);
NIC_OUTB(ED_P0_CR, ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
#ifdef NE_16BIT
for (i = 0; i < amount; i += 2, dst += 2)
*(uint16_t *)dst = ASIC_INW(NE2000_ASIC_DATA);
#else
for (i = 0; i < amount; i++)
*dst++ = ASIC_INB(NE2000_ASIC_DATA);
#endif
}