Home | History | Annotate | Line # | Download | only in eb7500atx
if_cs.c revision 1.1
      1 /*	$NetBSD: if_cs.c,v 1.1 2004/01/03 14:31:28 chris Exp $	*/
      2 
      3 /*
      4  * Copyright 1997
      5  * Digital Equipment Corporation. All rights reserved.
      6  *
      7  * This software is furnished under license and may be used and
      8  * copied only in accordance with the following terms and conditions.
      9  * Subject to these conditions, you may download, copy, install,
     10  * use, modify and distribute this software in source and/or binary
     11  * form. No title or ownership is transferred hereby.
     12  *
     13  * 1) Any source code used, modified or distributed must reproduce
     14  *    and retain this copyright notice and list of conditions as
     15  *    they appear in the source file.
     16  *
     17  * 2) No right is granted to use any trade name, trademark, or logo of
     18  *    Digital Equipment Corporation. Neither the "Digital Equipment
     19  *    Corporation" name nor any trademark or logo of Digital Equipment
     20  *    Corporation may be used to endorse or promote products derived
     21  *    from this software without the prior written permission of
     22  *    Digital Equipment Corporation.
     23  *
     24  * 3) This software is provided "AS-IS" and any express or implied
     25  *    warranties, including but not limited to, any implied warranties
     26  *    of merchantability, fitness for a particular purpose, or
     27  *    non-infringement are disclaimed. In no event shall DIGITAL be
     28  *    liable for any damages whatsoever, and in particular, DIGITAL
     29  *    shall not be liable for special, indirect, consequential, or
     30  *    incidental damages or damages for lost profits, loss of
     31  *    revenue or loss of use, whether such damages arise in contract,
     32  *    negligence, tort, under statute, in equity, at law or otherwise,
     33  *    even if advised of the possibility of such damage.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: if_cs.c,v 1.1 2004/01/03 14:31:28 chris Exp $");
     38 
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/socket.h>
     42 #include <sys/device.h>
     43 
     44 #include "rnd.h"
     45 #if NRND > 0
     46 #include <sys/rnd.h>
     47 #endif
     48 
     49 #include <net/if.h>
     50 #include <net/if_ether.h>
     51 #include <net/if_media.h>
     52 
     53 #include <machine/bus.h>
     54 #include <machine/intr.h>
     55 
     56 #include <sys/queue.h>
     57 #include <uvm/uvm.h>
     58 #include <machine/pmap.h>
     59 
     60 #include <acorn32/eb7500atx/rsbus.h>
     61 
     62 #include <dev/ic/cs89x0reg.h>
     63 #include <dev/ic/cs89x0var.h>
     64 
     65 /*
     66  * the CS network interface is accessed at the following address locations:
     67  * 030104f1 		CS8920 PNP Low
     68  * 03010600 03010640	CS8920 Default I/O registers
     69  * 030114f1 		CS8920 PNP High
     70  * 03014000 03016000	CS8920 Default Memory
     71  *
     72  * IRQ is mapped as:
     73  * CS8920 IRQ 3 	INT5
     74  *
     75  * It must be configured as the following:
     76  * The CS8920 PNP address should be configured for ISA base at 0x300
     77  * to achieve the default register mapping as specified.
     78  * Note memory addresses are all have bit 23 tied high in hardware.
     79  * This only effects the value programmed into the CS8920 memory offset
     80  * registers.
     81  *
     82  * Just to add to the fun the I/O registers are layed out as:
     83  * xxxxR1R0
     84  * xxxxR3R2
     85  * xxxxR5R4
     86  *
     87  * This makes access to single registers hard (which does happen on a reset,
     88  * as we've got to toggle the chip into 16bit mode)
     89  *
     90  * Network DRQ is connected to DRQ5
     91  */
     92 
     93 /*
     94  * make a private tag so that we can use mainbus's map/unmap
     95  */
     96 static struct bus_space cs_rsbus_bs_tag;
     97 
     98 int	cs_pioc_probe __P((struct device *, struct cfdata *, void *));
     99 void	cs_pioc_attach __P((struct device *, struct device *, void *));
    100 
    101 static u_int8_t cs_rbus_read_1(struct cs_softc *, bus_size_t);
    102 
    103 CFATTACH_DECL(cs_rsbus, sizeof(struct cs_softc),
    104 	cs_pioc_probe, cs_pioc_attach, NULL, NULL);
    105 
    106 /* Available media */
    107 int cs_rbus_media [] = {
    108 	IFM_ETHER|IFM_10_T,
    109 	IFM_ETHER|IFM_10_T|IFM_FDX
    110 };
    111 
    112 
    113 int
    114 cs_pioc_probe(parent, cf, aux)
    115 	struct device *parent;
    116 	struct cfdata *cf;
    117 	void *aux;
    118 {
    119 	/* for now it'll always attach */
    120 	return 1;
    121 }
    122 #if 0
    123 	struct isa_attach_args *ia = aux;
    124 	bus_space_tag_t iot = ia->ia_iot;
    125 	bus_space_tag_t memt = ia->ia_memt;
    126 	bus_space_handle_t ioh, memh;
    127 	struct cs_softc sc;
    128 	int rv = 0, have_io = 0, have_mem = 0;
    129 	u_int16_t isa_cfg, isa_membase;
    130 	int maddr, irq;
    131 
    132 	if (ia->ia_nio < 1)
    133 		return (0);
    134 	if (ia->ia_nirq < 1)
    135 		return (0);
    136 
    137 	if (ISA_DIRECT_CONFIG(ia))
    138 		return (0);
    139 
    140 	/*
    141 	 * Disallow wildcarded I/O base.
    142 	 */
    143 	if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
    144 		return (0);
    145 
    146 	if (ia->ia_niomem > 0)
    147 		maddr = ia->ia_iomem[0].ir_addr;
    148 	else
    149 		maddr = ISACF_IOMEM_DEFAULT;
    150 
    151 	/*
    152 	 * Map the I/O space.
    153 	 */
    154 	if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, CS8900_IOSIZE,
    155 	    0, &ioh))
    156 		goto out;
    157 	have_io = 1;
    158 
    159 	memset(&sc, 0, sizeof sc);
    160 	sc.sc_iot = iot;
    161 	sc.sc_ioh = ioh;
    162 	/* Verify that it's a Crystal product. */
    163 	if (CS_READ_PACKET_PAGE_IO(&sc, PKTPG_EISA_NUM) !=
    164 	    EISA_NUM_CRYSTAL)
    165 		goto out;
    166 
    167 	/*
    168 	 * Verify that it's a supported chip.
    169 	 */
    170 	switch (CS_READ_PACKET_PAGE_IO(&sc, PKTPG_PRODUCT_ID) &
    171 	    PROD_ID_MASK) {
    172 	case PROD_ID_CS8900:
    173 #ifdef notyet
    174 	case PROD_ID_CS8920:
    175 	case PROD_ID_CS8920M:
    176 #endif
    177 		rv = 1;
    178 	}
    179 
    180 	/*
    181 	 * If the IRQ or memory address were not specified, read the
    182 	 * ISA_CFG EEPROM location.
    183 	 */
    184 	if (maddr == ISACF_IOMEM_DEFAULT ||
    185 	    ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT) {
    186 		if (cs_verify_eeprom(&sc) == CS_ERROR) {
    187 			printf("cs_isa_probe: EEPROM bad or missing\n");
    188 			goto out;
    189 		}
    190 		if (cs_read_eeprom(&sc, EEPROM_ISA_CFG, &isa_cfg)
    191 		    == CS_ERROR) {
    192 			printf("cs_isa_probe: unable to read ISA_CFG\n");
    193 			goto out;
    194 		}
    195 	}
    196 
    197 	/*
    198 	 * If the IRQ wasn't specified, get it from the EEPROM.
    199 	 */
    200 	if (ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT) {
    201 		irq = isa_cfg & ISA_CFG_IRQ_MASK;
    202 		if (irq == 3)
    203 			irq = 5;
    204 		else
    205 			irq += 10;
    206 	} else
    207 		irq = ia->ia_irq[0].ir_irq;
    208 
    209 	/*
    210 	 * If the memory address wasn't specified, get it from the EEPROM.
    211 	 */
    212 	if (maddr == ISACF_IOMEM_DEFAULT) {
    213 		if ((isa_cfg & ISA_CFG_MEM_MODE) == 0) {
    214 			/* EEPROM says don't use memory mode. */
    215 			goto out;
    216 		}
    217 		if (cs_read_eeprom(&sc, EEPROM_MEM_BASE, &isa_membase)
    218 		    == CS_ERROR) {
    219 			printf("cs_isa_probe: unable to read MEM_BASE\n");
    220 			goto out;
    221 		}
    222 
    223 		isa_membase &= MEM_BASE_MASK;
    224 		maddr = (int)isa_membase << 8;
    225 	}
    226 
    227 	/*
    228 	 * We now have a valid mem address; attempt to map it.
    229 	 */
    230 	if (bus_space_map(ia->ia_memt, maddr, CS8900_MEMSIZE, 0, &memh)) {
    231 		/* Can't map it; fall back on i/o-only mode. */
    232 		printf("cs_isa_probe: unable to map memory space\n");
    233 		maddr = ISACF_IOMEM_DEFAULT;
    234 	} else
    235 		have_mem = 1;
    236 
    237  out:
    238 	if (have_io)
    239 		bus_space_unmap(iot, ioh, CS8900_IOSIZE);
    240 	if (have_mem)
    241 		bus_space_unmap(memt, memh, CS8900_MEMSIZE);
    242 
    243 	if (rv) {
    244 		ia->ia_nio = 1;
    245 		ia->ia_io[0].ir_size = CS8900_IOSIZE;
    246 
    247 		if (maddr == ISACF_IOMEM_DEFAULT)
    248 			ia->ia_niomem = 0;
    249 		else {
    250 			ia->ia_niomem = 1;
    251 			ia->ia_iomem[0].ir_addr = maddr;
    252 			ia->ia_iomem[0].ir_size = CS8900_MEMSIZE;
    253 		}
    254 
    255 		ia->ia_nirq = 1;
    256 		ia->ia_irq[0].ir_irq = irq;
    257 	}
    258 	return (rv);
    259 }
    260 #endif
    261 void
    262 cs_pioc_attach(parent, self, aux)
    263 	struct device *parent, *self;
    264 	void *aux;
    265 {
    266 	struct cs_softc *sc = (struct cs_softc *)self;
    267 	struct rsbus_attach_args *rs = (void *)aux;
    268 	u_int iobase;
    269 
    270 	/* member copy */
    271 	cs_rsbus_bs_tag = *rs->sa_iot;
    272 
    273 	/* registers are 4 byte aligned */
    274 	cs_rsbus_bs_tag.bs_cookie = (void *) 1;
    275 
    276 	sc->sc_iot = sc->sc_memt = &cs_rsbus_bs_tag;
    277 
    278 	/*
    279 	 * Do DMA later
    280 	if (ia->ia_ndrq > 0)
    281 		isc->sc_drq = ia->ia_drq[0].ir_drq;
    282 	else
    283 		isc->sc_drq = -1;
    284 	*/
    285 
    286 	/* device always interrupts on 3 but that routes to IRQ 5 */
    287 	sc->sc_irq = 3;
    288 
    289 	printf("\n");
    290 
    291 	/*
    292 	 * Map the device.
    293 	 */
    294 	iobase = 0x03010600;
    295 	printf("mapping iobase=0x%08x, for 0x%08x\n", iobase, CS8900_IOSIZE * 4);
    296 	if (bus_space_map(sc->sc_iot, iobase, CS8900_IOSIZE * 4,
    297 	    0, &sc->sc_ioh)) {
    298 		printf("%s: unable to map i/o space\n", sc->sc_dev.dv_xname);
    299 		return;
    300 	}
    301 
    302 #if 0
    303 	bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, PORT_PKTPG_PTR, PKTPG_EISA_NUM);
    304 
    305 	productID = bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, PORT_PKTPG_DATA);
    306 
    307 	printf("Result ID = 0x%08x\n", productID);
    308 	printf("cookie = %p\n", sc->sc_iot->bs_cookie);
    309 	{
    310 		volatile uint32_t *ptr =  (void*) ((char *)((sc)->sc_ioh) + (PORT_PKTPG_PTR  << 1));
    311 		volatile uint32_t *data =(void *)((char *)((sc)->sc_ioh) + (PORT_PKTPG_DATA  << 1));
    312 		volatile char *pnplow = (char *)trunc_page((sc)->sc_ioh) + 0x4f1;
    313 		bus_space_handle_t tag2;
    314 		pt_entry_t *pte;
    315 
    316 		printf("ioh = %p, ptr = %p, data = %p\n", (void*)(sc)->sc_ioh, ptr, data);
    317 		*ptr = PKTPG_EISA_NUM;
    318 		productID = *data;
    319 		printf("Result ID2 = 0x%08x\n", productID);
    320 
    321 		pte = vtopte(trunc_page((sc)->sc_ioh));
    322 		printf("pte = %p, *pte =  0x%08x\n", pte, *pte);
    323 		printf("pnplow = %p, *pnplow = 0x%02x\n", pnplow, *pnplow);
    324 
    325 		if (bus_space_map(sc->sc_iot, 0x03011000, 0x1000,
    326 					0, &tag2)) {
    327 		printf("%s: unable to map i/o space\n", sc->sc_dev.dv_xname);
    328 		return;
    329 		}
    330 		pnplow = (char *)trunc_page(tag2) + 0x4f1;
    331 		printf("pnplow = %p, *pnplow = 0x%02x\n", pnplow, *pnplow);
    332 
    333 		*pnplow = 0x3;
    334 
    335 		*ptr = PKTPG_EISA_NUM;
    336 		productID = *data;
    337 		printf("Result ID2 = 0x%08x\n", productID);
    338 	}
    339 #endif
    340 
    341 #if 0
    342 	/*
    343 	 * Map the memory space if it was specified.  If we can do this,
    344 	 * we set ourselves up to use memory mode forever.  Otherwise,
    345 	 * we fall back on I/O mode.
    346 	 */
    347 	if (ia->ia_iomem[0].ir_addr != ISACF_IOMEM_DEFAULT &&
    348 	    ia->ia_iomem[0].ir_size == CS8900_MEMSIZE &&
    349 	    CS8900_MEMBASE_ISVALID(ia->ia_iomem[0].ir_addr)) {
    350 #endif
    351 #if 0
    352 	printf("mapping iobase=0x%08x, for 0x%08x\n", iobase + 0x3A00,
    353 			CS8900_MEMSIZE * 4);
    354 		if (bus_space_map(sc->sc_memt, iobase + 0x3A00,
    355 					CS8900_MEMSIZE * 4, 0, &sc->sc_memh)) {
    356 			printf("%s: unable to map memory space\n",
    357 			    sc->sc_dev.dv_xname);
    358 		} else {
    359 			sc->sc_cfgflags |= CFGFLG_MEM_MODE;
    360 			sc->sc_pktpgaddr = iobase + 0x3A00;
    361 		}
    362 #endif
    363 
    364 	printf("Claiming IRQ\n");
    365 		sc->sc_ih = intr_claim(0x0B, IPL_NET, "cs", cs_intr, sc);
    366 	if (sc->sc_ih == NULL) {
    367 		printf("%s: unable to establish interrupt\n",
    368 		    sc->sc_dev.dv_xname);
    369 		return;
    370 	}
    371 
    372 	/* DMA is for later */
    373 	sc->sc_dma_chipinit = NULL;
    374 	sc->sc_dma_attach = NULL;
    375 	sc->sc_dma_process_rx = NULL;
    376 
    377 	printf("Cs attach addr: 0x%04x\n", CS_READ_PACKET_PAGE(sc, PKTPG_IND_ADDR));
    378 
    379 	/* don't talk to the EEPROM, it seems that the cs driver doesn't use a
    380 	 * normal layout */
    381 	sc->sc_cfgflags |= CFGFLG_NOT_EEPROM;
    382 	sc->sc_io_read_1 = cs_rbus_read_1;
    383 	cs_attach(sc, NULL, cs_rbus_media, sizeof(cs_rbus_media) / sizeof(cs_rbus_media[0]),
    384 			IFM_ETHER|IFM_10_T|IFM_FDX);
    385 }
    386 
    387 static u_int8_t
    388 cs_rbus_read_1(struct cs_softc *sc, bus_size_t a)
    389 {
    390 	bus_size_t offset;
    391 	/* this is rather warped if it's an even address then just use the
    392 	 * bus_space_read_1
    393 	 */
    394 	if ((a & 1) == 0)
    395 	{
    396 		return bus_space_read_1(sc->sc_iot, sc->sc_ioh, a);
    397 	}
    398 	/* otherwise we've get to work out the aligned address and then add
    399 	 * one */
    400 	/* first work out the offset */
    401 	offset = (a & ~1) << 1;
    402 	/* add the one */
    403 	offset++;
    404 
    405 	/* and read it, with no shift */
    406 	return sc->sc_iot->bs_r_1(0, (sc)->sc_ioh, offset);
    407 }
    408