# lnc.c

Go to the documentation of this file.

    00001 /*****************************************************************************************
    00002  Copyright (c) 2002 The UbixOS Project
    00003  All rights reserved.
    00004
    00005 Redistribution and use in source and binary forms, with or without modification, are
    00006 permitted provided that the following conditions are met:
    00007
    00008 Redistributions of source code must retain the above copyright notice, this list of
    00009 conditions, the following disclaimer and the list of authors.  Redistributions in binary
    00010 form must reproduce the above copyright notice, this list of conditions, the following
    00011 disclaimer and the list of authors in the documentation and/or other materials provided
    00012 with the distribution. Neither the name of the UbixOS Project nor the names of its
    00013 contributors may be used to endorse or promote products derived from this software
    00014 without specific prior written permission.
    00015
    00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
    00017 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
    00019 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
    00021 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    00022 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    00023 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    00024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00025
    00026  $Log: lnc_8c-source.html,v $
    00026  Revision 1.7  2006/12/15 17:47:06  reddawg
    00026  Updates
    00026
    00027  Revision 1.1.1.1  2006/06/01 12:46:16  reddawg
    00028  ubix2
    00029
    00030  Revision 1.2  2005/10/12 00:13:37  reddawg
    00031  Removed
    00032
    00033  Revision 1.1.1.1  2005/09/26 17:24:35  reddawg
    00034  no message
    00035
    00036  Revision 1.1.1.1  2004/04/15 12:07:15  reddawg
    00037  UbixOS v1.0
    00038
    00039  Revision 1.4  2004/04/13 16:36:33  reddawg
    00040  Changed our copyright, it is all now under a BSD-Style license
    00041
    00042
    00043
    00044  $Id: lnc_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
    00045
    00046 *****************************************************************************************/
    00047
    00048 #include <pci/lnc.h>
    00049 #include <sys/io.h>
    00050 #include <ubixos/types.h>
    00051 #include <sys/idt.h>
    00052 #include <sys/gdt.h>
    00053 #include <lib/kmalloc.h>
    00054 #include <lib/kprintf.h>
    00055 #include <sys/video.h>
    00056 #include <isa/8259.h>
    00057
    00058 struct lncInfo *lnc = 0x0;
    00059
    00060 static char const * const nicIdent[] = {
    00061   "Unknown",
    00062   "BICC",
    00063   "NE2100",
    00064   "DEPCA",
    00065   "CNET98S",      /* PC-98 */
    00066   };
    00067
    00068 static char const * const icIdent[] = {
    00069   "Unknown",
    00070   "LANCE",
    00071   "C-LANCE",
    00072   "PCnet-ISA",
    00073   "PCnet-ISA+",
    00074   "PCnet-ISA II",
    00075   "PCnet-32 VL-Bus",
    00076   "PCnet-PCI",
    00077   "PCnet-PCI II",
    00078   "PCnet-FAST",
    00079   "PCnet-FAST+",
    00080   "PCnet-Home",
    00081   };
    00082
    00083 void writeCsr(struct lncInfo *lnc, uInt16 port, uInt16 val) {
    00084   outportWord(lnc->rap, port);
    00085   outportWord(lnc->rdp, val);
    00086   }
    00087
    00088 uInt16 readCsr(struct lncInfo *lnc, uInt16 port) {
    00089   outportWord(lnc->rap, port);
    00090   return(inportWord(lnc->rdp));
    00091   }
    00092
    00093 void writeBcr(struct lncInfo *lnc, uInt16 port, uInt16 val) {
    00094   outportWord(lnc->rap, port);
    00095   outportWord(lnc->bdp, val);
    00096   }
    00097
    00098 uInt16 readBcr(struct lncInfo *sc, uInt16 port) {
    00099   outportWord(sc->rap, port);
    00100   return (inportWord(sc->bdp));
    00101   }
    00102
    00103
    00104 void initLNC() {
    00105   int            i    = 0x0;
    00106   lnc = kmalloc(sizeof(struct lncInfo),-2);
    00107
    00108   lnc->rap = 0x1000 + PCNET_RAP;
    00109   lnc->rdp = 0x1000 + PCNET_RDP;
    00110   lnc->bdp = 0x1000 + PCNET_BDP;
    00111
    00112   lnc->nic.ic = probe(lnc);
    00113   if ((lnc->nic.ic > 0) && (lnc->nic.ic >= PCnet_32)) {
    00114     lnc->nic.ident = NE2100;
    00115     lnc->nic.memMode = DMA_FIXED;
    00116
    00117     lnc->nrdre = NRDRE;
    00118     lnc->ntdre = NTDRE;
    00119
    00120     /* Extract MAC address from PROM */
    00121     for (i = 0; i < ETHER_ADDR_LEN; i++) {
    00122       lnc->arpcom.ac_enaddr[i] = inportByte(0x1000 + i);
    00123       kprintf("[0x%X]",lnc->arpcom.ac_enaddr[i]);
    00124       }
    00125     }
    00126   else {
    00127     kprintf("LNC Init Error\n");
    00128     return;
    00129     }
    00130   lncAttach(lnc,0);
    00131   writeCsr(lnc, CSR3, 0);
    00132   writeCsr(lnc, CSR0, INIT);
    00133   for (i = 0; i < 1000; i++)
    00134     if (readCsr(lnc, CSR0) & IDON)
    00135       break;
    00136
    00137   if (readCsr(lnc, CSR0) & IDON) {
    00138     writeCsr(lnc, CSR0, STRT | INEA);
    00139     setVector(_lncInt,mVec+9, (dInt + dPresent + dDpl3));
    00140     enableIrq(9);
    00141     /*
    00142      * sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
    00143      * sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    00144      * lnc_start(&sc->arpcom.ac_if);
    00145      */
    00146     }
    00147   else {
    00148     kprintf("LNC init Error\n");
    00149     return;
    00150     }
    00151   return;
    00152   }
    00153
    00154 int probe(struct lncInfo *lnc) {
    00155   uInt32 chipId = 0x0;
    00156   int    type   = 0x0;
    00157
    00158   if ((type = lanceProbe(lnc))) {
    00159     chipId = readCsr(lnc, CSR89);
    00160     chipId <<= 16;
    00161     chipId |= readCsr(lnc, CSR88);
    00162     if (chipId & AMD_MASK) {
    00163       chipId >>= 12;
    00164       switch (chipId & PART_MASK) {
    00165         case Am79C960:
    00166           return(PCnet_ISA);
    00167         case Am79C961:
    00168           return (PCnet_ISAplus);
    00169         case Am79C961A:
    00170           return (PCnet_ISA_II);
    00171         case Am79C965:
    00172           return (PCnet_32);
    00173         case Am79C970:
    00174           return (PCnet_PCI);
    00175         case Am79C970A:
    00176           return (PCnet_PCI_II);
    00177         case Am79C971:
    00178           return (PCnet_FAST);
    00179         case Am79C972:
    00180         case Am79C973:
    00181           return (PCnet_FASTplus);
    00182         case Am79C978:
    00183           return (PCnet_Home);
    00184         default:
    00185           break;
    00186         }
    00187       }
    00188     }
    00189   return (type);
    00190   }
    00191
    00192 int lanceProbe(struct lncInfo *lnc) {
    00193   writeCsr(lnc, CSR0, STOP);
    00194   if ((inportWord(lnc->rdp) & STOP) && !(readCsr(lnc, CSR3))) {
    00195     writeCsr(lnc, CSR0, INEA);
    00196     if (readCsr(lnc, CSR0) & INEA) {
    00197       return(C_LANCE);
    00198       }
    00199     else {
    00200       return(LANCE);
    00201       }
    00202     }
    00203   else {
    00204     return(UNKNOWN);
    00205     }
    00206   }
    00207
    00208 void lncInt() {
    00209   uInt16 csr0 = 0x0;
    00210   while ((csr0 = inportWord(lnc->rdp)) & INTR) {
    00211     outportWord(lnc->rdp, csr0);
    00212     kprintf("CSR0: [0x%X]\n",csr0);
    00213     if (csr0 & ERR) {
    00214       kprintf("Error: [0x%X]\n",csr0);
    00215       }
    00216     if (csr0 & RINT) {
    00217       kprintf("RINT\n");
    00218       }
    00219     if (csr0 & TINT) {
    00220       kprintf("TINT\n");
    00221       }
    00222     }
    00223   kprintf("Finished!!!\n");
    00224   outportByte(0x20,0x20);
    00225   return;
    00226   }
    00227
    00228 asm(
    00229     ".global _lncInt     \n"
    00230     "_lncInt   :         \n"
    00231
    00232   "  pusha                \n" /* Save all registers           */
    00233   "  pushw %ds            \n" /* Set up the data segment      */
    00234   "  pushw %es            \n"
    00235   "  pushw %ss            \n" /* Note that ss is always valid */
    00236   "  pushw %ss            \n"
    00237   "  popw %ds             \n"
    00238   "  popw %es             \n"
    00239   "  call lncInt \n"
    00240   "  popw %es             \n"
    00241   "  popw %ds             \n" /* Restore registers            */
    00242   "  popa                 \n"
    00243   "  iret                 \n" /* Exit interrupt               */
    00244     );
    00245
    00246 int lncAttach(struct lncInfo *lnc,int unit) {
    00247   int lncMemSize = 0x0;
    00248
    00249   lncMemSize = ((NDESC(lnc->nrdre) + NDESC(lnc->ntdre)) * sizeof(struct hostRingEntry));
    00250
    00251   if (lnc->nic.memMode != SHMEM)
    00252     lncMemSize += sizeof(struct initBlock) + (sizeof(struct mds) * (NDESC(lnc->nrdre) + NDESC(lnc->ntdre))) + MEM_SLEW;
    00253
    00254   if (lnc->nic.memMode == DMA_FIXED)
    00255     lncMemSize += (NDESC(lnc->nrdre) * RECVBUFSIZE) + (NDESC(lnc->ntdre) * TRANSBUFSIZE);
    00256
    00257   if (lnc->nic.memMode != SHMEM) {
    00258     if (lnc->nic.ic < PCnet_32) {
    00259       /* ISA based cards */
    00260       kprintf("ISA Board\n");
    00261       /* sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT,0ul, 0xfffffful, 4ul, 0x1000000); */
    00262       }
    00263     else {
    00264       /*
    00265       * For now it still needs to be below 16MB because the
    00266       * descriptor's can only hold 16 bit addresses.
    00267       */
    00268       /* sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT,0ul, 0xfffffful, 4ul, 0x1000000); */
    00269       lnc->recvRing = kmalloc(lncMemSize,-2);
    00270       kprintf("PCI Board\n");
    00271       }
    00272     }
    00273
    00274   if (!lnc->recvRing) {
    00275     kprintf("lnc%d: Couldn't allocate memory for NIC\n", unit);
    00276     return (0);
    00277     }
    00278
    00279   lnc->nic.mode = NORMAL;
    00280
    00281   /* Fill in arpcom structure entries */
    00282   /*
    00283   lnc->arpcom.ac_if.if_softc = sc;
    00284   lnc->arpcom.ac_if.if_name = lncdriver.name;
    00285   lnc->arpcom.ac_if.if_unit = unit;
    00286   lnc->arpcom.ac_if.if_mtu = ETHERMTU;
    00287   lnc->arpcom.ac_if.if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    00288   lnc->arpcom.ac_if.if_timer = 0;
    00289   lnc->arpcom.ac_if.if_output = ether_output;
    00290   lnc->arpcom.ac_if.if_start = lnc_start;
    00291   lnc->arpcom.ac_if.if_ioctl = lnc_ioctl;
    00292   lnc->arpcom.ac_if.if_watchdog = lnc_watchdog;
    00293   lnc->arpcom.ac_if.if_init = lnc_init;
    00294   lnc->arpcom.ac_if.if_type = IFT_ETHER;
    00295   lnc->arpcom.ac_if.if_addrlen = ETHER_ADDR_LEN;
    00296   lnc->arpcom.ac_if.if_hdrlen = ETHER_HDR_LEN;
    00297   lnc->arpcom.ac_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
    00298   */
    00299   /* ether_ifattach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED); */
    00300
    00301   kprintf("lnc%d: ", unit);
    00302   if (lnc->nic.ic == LANCE || lnc->nic.ic == C_LANCE)
    00303     kprintf("%s (%s)",nicIdent[lnc->nic.ident], icIdent[lnc->nic.ic]);
    00304   else
    00305     kprintf("%s", icIdent[lnc->nic.ic]);
    00306   kprintf(" address 0x%X\n", lnc->arpcom.ac_enaddr);
    00307   return(1);
    00308   }
    00309
    00310 /***
    00311  END
    00312  ***/
    00313