#include <pci/lnc.h> #include <sys/io.h> #include <ubixos/types.h> #include <sys/idt.h> #include <sys/gdt.h> #include <lib/kmalloc.h> #include <sys/video.h> #include <isa/8259.h> struct lncInfo *lnc = 0x0; static char const * const nicIdent[] = { "Unknown", "BICC", "NE2100", "DEPCA", "CNET98S", /* PC-98 */ }; static char const * const icIdent[] = { "Unknown", "LANCE", "C-LANCE", "PCnet-ISA", "PCnet-ISA+", "PCnet-ISA II", "PCnet-32 VL-Bus", "PCnet-PCI", "PCnet-PCI II", "PCnet-FAST", "PCnet-FAST+", "PCnet-Home", }; void writeCsr(struct lncInfo *lnc, uInt16 port, uInt16 val) { outportWord(lnc->rap, port); outportWord(lnc->rdp, val); } uInt16 readCsr(struct lncInfo *lnc, uInt16 port) { outportWord(lnc->rap, port); return(inportWord(lnc->rdp)); } void writeBcr(struct lncInfo *lnc, uInt16 port, uInt16 val) { outportWord(lnc->rap, port); outportWord(lnc->bdp, val); } uInt16 readBcr(struct lncInfo *sc, uInt16 port) { outportWord(sc->rap, port); return (inportWord(sc->bdp)); } void initLNC() { int i = 0x0; lnc = kmalloc(sizeof(struct lncInfo),-2); lnc->rap = 0x1000 + PCNET_RAP; lnc->rdp = 0x1000 + PCNET_RDP; lnc->bdp = 0x1000 + PCNET_BDP; lnc->nic.ic = probe(lnc); if ((lnc->nic.ic > 0) && (lnc->nic.ic >= PCnet_32)) { lnc->nic.ident = NE2100; lnc->nic.memMode = DMA_FIXED; lnc->nrdre = NRDRE; lnc->ntdre = NTDRE; /* Extract MAC address from PROM */ for (i = 0; i < ETHER_ADDR_LEN; i++) { lnc->arpcom.ac_enaddr[i] = inportByte(0x1000 + i); kprintf("[0x%X]",lnc->arpcom.ac_enaddr[i]); } } else { kprintf("LNC Init Error\n"); return; } lncAttach(lnc,0); writeCsr(lnc, CSR3, 0); writeCsr(lnc, CSR0, INIT); for (i = 0; i < 1000; i++) if (readCsr(lnc, CSR0) & IDON) break; if (readCsr(lnc, CSR0) & IDON) { writeCsr(lnc, CSR0, STRT | INEA); setVector(_lncInt,mVec+9, (dInt + dPresent + dDpl3)); enableIrq(9); //sc->arpcom.ac_if.if_flags |= IFF_RUNNING; //sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; //lnc_start(&sc->arpcom.ac_if); } else { kprintf("LNC init Error\n"); return; } return; } int probe(struct lncInfo *lnc) { uInt32 chipId = 0x0; int type = 0x0; if ((type = lanceProbe(lnc))) { chipId = readCsr(lnc, CSR89); chipId <<= 16; chipId |= readCsr(lnc, CSR88); if (chipId & AMD_MASK) { chipId >>= 12; switch (chipId & PART_MASK) { case Am79C960: return(PCnet_ISA); case Am79C961: return (PCnet_ISAplus); case Am79C961A: return (PCnet_ISA_II); case Am79C965: return (PCnet_32); case Am79C970: return (PCnet_PCI); case Am79C970A: return (PCnet_PCI_II); case Am79C971: return (PCnet_FAST); case Am79C972: case Am79C973: return (PCnet_FASTplus); case Am79C978: return (PCnet_Home); default: break; } } } return (type); } int lanceProbe(struct lncInfo *lnc) { writeCsr(lnc, CSR0, STOP); if ((inportWord(lnc->rdp) & STOP) && !(readCsr(lnc, CSR3))) { writeCsr(lnc, CSR0, INEA); if (readCsr(lnc, CSR0) & INEA) { return(C_LANCE); } else { return(LANCE); } } else { return(UNKNOWN); } } void lncInt() { uInt16 csr0 = 0x0; while ((csr0 = inportWord(lnc->rdp)) & INTR) { outportWord(lnc->rdp, csr0); kprintf("CSR0: [0x%X]\n",csr0); if (csr0 & ERR) { kprintf("Error: [0x%X]\n",csr0); } if (csr0 & RINT) { kprintf("RINT\n"); } if (csr0 & TINT) { kprintf("TINT\n"); } } kprintf("Finished!!!\n"); outportByte(0x20,0x20); return; } asm( ".global _lncInt \n" "_lncInt : \n" " pusha \n" /* Save all registers */ " pushw %ds \n" /* Set up the data segment */ " pushw %es \n" " pushw %ss \n" /* Note that ss is always valid */ " pushw %ss \n" " popw %ds \n" " popw %es \n" " call lncInt \n" " popw %es \n" " popw %ds \n" /* Restore registers */ " popa \n" " iret \n" /* Exit interrupt */ ); int lncAttach(struct lncInfo *lnc,int unit) { int lncMemSize = 0x0; lncMemSize = ((NDESC(lnc->nrdre) + NDESC(lnc->ntdre)) * sizeof(struct hostRingEntry)); if (lnc->nic.memMode != SHMEM) lncMemSize += sizeof(struct initBlock) + (sizeof(struct mds) * (NDESC(lnc->nrdre) + NDESC(lnc->ntdre))) + MEM_SLEW; if (lnc->nic.memMode == DMA_FIXED) lncMemSize += (NDESC(lnc->nrdre) * RECVBUFSIZE) + (NDESC(lnc->ntdre) * TRANSBUFSIZE); if (lnc->nic.memMode != SHMEM) { if (lnc->nic.ic < PCnet_32) { /* ISA based cards */ kprintf("ISA Board\n"); //sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT,0ul, 0xfffffful, 4ul, 0x1000000); } else { /* * For now it still needs to be below 16MB because the * descriptor's can only hold 16 bit addresses. */ //sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT,0ul, 0xfffffful, 4ul, 0x1000000); lnc->recvRing = kmalloc(lncMemSize,-2); kprintf("PCI Board\n"); } } if (!lnc->recvRing) { kprintf("lnc%d: Couldn't allocate memory for NIC\n", unit); return (0); } lnc->nic.mode = NORMAL; /* Fill in arpcom structure entries */ /* lnc->arpcom.ac_if.if_softc = sc; lnc->arpcom.ac_if.if_name = lncdriver.name; lnc->arpcom.ac_if.if_unit = unit; lnc->arpcom.ac_if.if_mtu = ETHERMTU; lnc->arpcom.ac_if.if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; lnc->arpcom.ac_if.if_timer = 0; lnc->arpcom.ac_if.if_output = ether_output; lnc->arpcom.ac_if.if_start = lnc_start; lnc->arpcom.ac_if.if_ioctl = lnc_ioctl; lnc->arpcom.ac_if.if_watchdog = lnc_watchdog; lnc->arpcom.ac_if.if_init = lnc_init; lnc->arpcom.ac_if.if_type = IFT_ETHER; lnc->arpcom.ac_if.if_addrlen = ETHER_ADDR_LEN; lnc->arpcom.ac_if.if_hdrlen = ETHER_HDR_LEN; lnc->arpcom.ac_if.if_snd.ifq_maxlen = IFQ_MAXLEN; */ //ether_ifattach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED); kprintf("lnc%d: ", unit); if (lnc->nic.ic == LANCE || lnc->nic.ic == C_LANCE) kprintf("%s (%s)",nicIdent[lnc->nic.ident], icIdent[lnc->nic.ic]); else kprintf("%s", icIdent[lnc->nic.ic]); kprintf(" address 0x%X\n", lnc->arpcom.ac_enaddr); return(1); }