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 */ 96static struct bus_space cs_rsbus_bs_tag; 97 98int cs_pioc_probe __P((struct device *, struct cfdata *, void *)); 99void cs_pioc_attach __P((struct device *, struct device *, void *)); 100 101static u_int8_t cs_rbus_read_1(struct cs_softc *, bus_size_t); 102 103CFATTACH_DECL(cs_rsbus, sizeof(struct cs_softc), 104 cs_pioc_probe, cs_pioc_attach, NULL, NULL); 105 106/* Available media */ 107int cs_rbus_media [] = { 108 IFM_ETHER|IFM_10_T, 109 IFM_ETHER|IFM_10_T|IFM_FDX 110}; 111 112 113int 114cs_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 261void 262cs_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 387static u_int8_t 388cs_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