tnt4882.c revision 150157
1/*- 2 * Copyright (c) 2005 Poul-Henning Kamp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/ieee488/tnt4882.c 150157 2005-09-15 13:27:16Z phk $ 27 */ 28 29#include <sys/param.h> 30#include <sys/kernel.h> 31#include <sys/systm.h> 32#include <sys/module.h> 33#include <sys/bus.h> 34#include <dev/pci/pcireg.h> 35#include <dev/pci/pcivar.h> 36 37#include <machine/bus.h> 38#include <machine/resource.h> 39#include <machine/stdarg.h> 40#include <sys/rman.h> 41 42/* vtophys */ 43#include <vm/vm.h> 44#include <vm/pmap.h> 45#include <machine/pmap.h> 46 47#define UPD7210_HW_DRIVER 1 48#include <dev/ieee488/upd7210.h> 49 50struct tnt_softc { 51 int foo; 52 struct upd7210 upd7210; 53 54 struct resource *res0, *res1, *res2; 55 bus_space_tag_t bt0, bt1; 56 bus_space_handle_t bh0, bh1; 57 void *intr_handler; 58}; 59 60enum tnt4882reg { 61 dir = 0x00, 62 cdor = 0x00, 63 isr1 = 0x02, 64 imr1 = 0x02, 65 isr2 = 0x04, 66 imr2 = 0x04, 67 accwr = 0x05, 68 spsr = 0x06, 69 spmr = 0x06, 70 intr = 0x07, 71 adsr = 0x08, 72 admr = 0x08, 73 cnt2 = 0x09, 74 cptr = 0x0a, 75 auxmr = 0x0a, 76 tauxcr = 0x0a, /* 9914 mode register */ 77 cnt3 = 0x0b, 78 adr0 = 0x0c, 79 adr = 0x0c, 80 hssel = 0x0d, 81 adr1 = 0x0e, 82 eosr = 0x0e, 83 sts1 = 0x10, 84 cfg = 0x10, 85 dsr = 0x11, 86 sh_cnt = 0x11, 87 imr3 = 0x12, 88 hier = 0x13, 89 cnt0 = 0x14, 90 misc = 0x15, 91 cnt1 = 0x16, 92 csr = 0x17, 93 keyreg = 0x17, 94 fifob = 0x18, 95 fifoa = 0x19, 96 isr3 = 0x1a, 97 ccr = 0x1a, 98 sasr = 0x1b, 99 dcr = 0x1b, 100 sts2 = 0x1c, 101 cmdr = 0x1c, 102 isr0 = 0x1d, 103 imr0 = 0x1d, 104 timer = 0x1e, 105 bsr = 0x1f, 106 bcr = 0x1f 107}; 108 109struct tst { 110 enum {RD, WT, xDELAY, END} 111 action; 112 enum tnt4882reg reg; 113 uint8_t val; 114}; 115 116/* 117 * From NI Application note 095: 118 * Writing Functional Self-Tests for the TNT4882 GPIB Interface Chip 119 * XXX: fill in the rest ? 120 */ 121static struct tst tst_reset[] = { 122 {WT, tauxcr, 0x80}, /* chip reset if in 9914 mode */ 123 {WT, auxmr, 0x80}, /* swrst if swapped */ 124 {WT, tauxcr, 0x99}, /* switch to 7210 mode */ 125 {WT, auxmr, 0x99}, /* switch to 7210 mode if swapped */ 126 {WT, auxmr, 0x02}, /* execute chip reset */ 127 {WT, keyreg, 0x00}, /* important! clear the swap bit */ 128 {WT, eosr, 0x00}, /* clear EOS register */ 129 {WT, cdor, 0x00}, /* clear data lines */ 130 {WT, imr1, 0x00}, /* disable all interrupts */ 131 {WT, imr2, 0x00}, 132 {WT, imr0, 0x80}, 133 {WT, adr, 0x80}, 134 {WT, adr, 0x00}, 135 {WT, admr, 0x00}, /* clear addressing modes */ 136 {WT, auxmr, 0x00}, /* release from idle state with pon */ 137 {WT, auxmr, 0x60}, /* reset ppr */ 138 {WT, bcr, 0x00}, /* reset bcr */ 139 {WT, misc, 0x04}, /* set wrap plug bit */ 140 {WT, cmdr, 0xB2}, /* issue soft reset */ 141 {WT, hssel, 0x00}, /* select two-chip mode */ 142 {END, 0, 0} 143}; 144 145static struct tst tst_read_reg[] = { 146 {RD, isr1, 0x00}, /* Verify mask registers are clear */ 147 {RD, isr2, 0x00}, 148 {RD, adsr, 0x40}, /* Verify ATN is not asserted */ 149 {RD, adr0, 0x00}, /* Verify Primary address not set */ 150 {RD, adr1, 0x00}, /* Verify Secondary address not set */ 151 {RD, sts1, 0x8B}, /* Verify DONE, STOP, HALT, and GSYNC set */ 152 {RD, isr3, 0x19}, /* Verify STOP, Not Full FIFO, & DONE set */ 153 {RD, sts2, 0x9A}, /* Verify FIFO A/B is empty */ 154 {RD, sasr, 0x00}, /* Verify clear */ 155 {RD, isr0, 0x01}, /* Verify SYNC bit is set */ 156 {END, 0, 0} 157}; 158 159static struct tst tst_bsr_dcr[] = { 160 {WT, bcr, 0x55}, /* Set DAV, NRFD, SRQ, and REN */ 161 {WT, dcr, 0xAA}, /* Write pattern to GPIB data lines */ 162 {RD, bsr, 0x55}, /* Verify DAV, NRFD, SRQ, and REN are set */ 163 {RD, dsr, 0xAA}, /* Verify data pattern written previously */ 164 {WT, bcr, 0xAA}, /* Set ATN, NDAC, EOI, & IFC */ 165 {WT, dcr, 0x55}, /* Write pattern to GPIB data lines */ 166 {RD, bsr, 0xAA}, /* Verify ATN, NDAC, EOI, & IFC are set */ 167 {RD, dsr, 0x55}, /* Verify data pattern written previously */ 168 {WT, bcr, 0x00}, /* Clear control lines */ 169 {WT, dcr, 0x00}, /* Clear data lines */ 170 {RD, bsr, 0x00}, /* Verify control lines are clear */ 171 {RD, dsr, 0x00}, /* Verify data lines are clear */ 172 {END, 0, 0} 173}; 174 175static struct tst tst_adr0_1[] = { 176 {WT, adr, 0x55}, /* Set Primary talk address */ 177 {WT, adr, 0xAA}, /* Set Secondary listen address */ 178 {RD, adr0, 0x55}, /* Read Primary address */ 179 {RD, adr1, 0x2A}, /* Read Secondary address */ 180 {WT, adr, 0x2A}, /* Set Primay listen address */ 181 {WT, adr, 0xD5}, /* Set Secondary talk address */ 182 {RD, adr0, 0x2A}, /* Read Primary address */ 183 {RD, adr1, 0x55}, /* Read Secondary address */ 184 {END, 0, 0} 185}; 186 187static struct tst tst_cdor_dir[] = { 188 {WT, admr, 0xF0}, /* program AT-GPIB as talker only and 189 * listener only */ 190 {RD, isr1, 0x02}, /* check DO bit set */ 191 {RD, adsr, 0x46}, /* check AT-GPIB is both talker active 192 * and listener active */ 193 {WT, cdor, 0xAA}, /* write out data byte */ 194 {xDELAY, 0, 1}, /* One ISA I/O Cycle (500-ns) */ 195 {RD, isr1, 0x03}, /* check DO and DI bits set */ 196 {RD, dir, 0xAA}, /* verify data received */ 197 {WT, cdor, 0x55}, /* write out data byte */ 198 {xDELAY, 0, 1}, /* One ISA I/O Cycle (500-ns) */ 199 {RD, dir, 0x55}, /* verify data received */ 200 {END, 0, 0} 201}; 202 203static struct tst tst_spmr_spsr[] = { 204 {WT, spsr, 0x00}, /* Write pattern to SPSR register */ 205 {RD, spmr, 0x00}, /* Read back previously written pattern */ 206 {WT, spsr, 0xBF}, /* Write pattern to SPSR register */ 207 {RD, spmr, 0xBF}, /* Read back previously written pattern */ 208 {END, 0, 0} 209}; 210 211static struct tst tst_count0_1[] = { 212 {WT, cnt0, 0x55}, /* Verify every other bit can be set */ 213 {WT, cnt1, 0xAA}, 214 {RD, cnt0, 0x55}, /* Read back previously written pattern */ 215 {RD, cnt1, 0xAA}, 216 {WT, cnt0, 0xAA}, /* Verify every other bit can be set */ 217 {WT, cnt1, 0x55}, 218 {RD, cnt0, 0xAA}, /* Read back previously written pattern */ 219 {RD, cnt1, 0x55}, 220 {END, 0, 0} 221}; 222 223static int 224tst_exec(struct tnt_softc *sc, struct tst *tp, const char *name) 225{ 226 uint8_t u; 227 int step; 228 229 for (step = 0; tp->action != END; tp++, step++) { 230 switch (tp->action) { 231 case WT: 232 bus_space_write_1(sc->bt1, sc->bh1, tp->reg, tp->val); 233 break; 234 case RD: 235 u = bus_space_read_1(sc->bt1, sc->bh1, tp->reg); 236 if (u != tp->val) { 237 printf( 238 "Test %s, step %d: reg(%02x) = %02x", 239 name, step, tp->reg, u); 240 printf( "should have been %02x\n", tp->val); 241 return (1); 242 } 243 break; 244 case xDELAY: 245 DELAY(tp->val); 246 break; 247 default: 248 printf("Unknown action in test %s, step %d: %d\n", 249 name, step, tp->action); 250 return (1); 251 } 252 } 253 if (bootverbose) 254 printf("Test %s passed\n", name); 255 return (0); 256} 257 258static int 259bus_dwiw(device_t dev, ...) 260{ 261 va_list ap, ap2; 262 int rid; 263 int type; 264 int flags; 265 struct resource **rp; 266 bus_space_tag_t *bt; 267 bus_space_handle_t *bh; 268 269 va_start(ap, dev); 270 va_copy(ap2, ap); 271 while (1) { 272 type = va_arg(ap, int); 273 if (type == -1) { 274 va_end(ap); 275 return (0); 276 } 277 rid = va_arg(ap, int); 278 flags = va_arg(ap, int); 279 rp = va_arg(ap, struct resource **); 280 *rp = bus_alloc_resource_any(dev, type, &rid, flags); 281 if (*rp == NULL) 282 break; 283 if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) { 284 bt = va_arg(ap, bus_space_tag_t *); 285 *bt = rman_get_bustag(*rp); 286 bh = va_arg(ap, bus_space_handle_t *); 287 *bh = rman_get_bushandle(*rp); 288 } 289 } 290 while (1) { 291 type = va_arg(ap2, int); 292 KASSERT(type != -1, ("bus_dwiw() internal mess")); 293 rid = va_arg(ap2, int); 294 flags = va_arg(ap2, int); 295 rp = va_arg(ap2, struct resource **); 296 if (*rp != NULL) 297 bus_release_resource(dev, type, rid, *rp); 298 else { 299 va_end(ap2); 300 return (ENXIO); 301 } 302 if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) { 303 bt = va_arg(ap2, bus_space_tag_t *); 304 bh = va_arg(ap2, bus_space_handle_t *); 305 } 306 } 307} 308static int 309tnt_probe(device_t dev) 310{ 311 312 if (pci_get_vendor(dev) == 0x1093 && pci_get_device(dev) == 0xc801) { 313 device_set_desc(dev, "NI PCI-GPIB"); 314 return (BUS_PROBE_DEFAULT); 315 } 316 return (ENXIO); 317} 318 319static int 320tnt_attach(device_t dev) 321{ 322 struct tnt_softc *sc; 323 int error, i; 324 325 sc = device_get_softc(dev); 326 327 error = bus_dwiw(dev, 328 SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE, 329 &sc->res0, &sc->bt0, &sc->bh0, 330 SYS_RES_MEMORY, PCIR_BAR(1), RF_ACTIVE, 331 &sc->res1, &sc->bt1, &sc->bh1, 332 SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE, &sc->res2, 333 -1); 334 if (error) 335 return (error); 336 337 error = bus_setup_intr(dev, sc->res2, INTR_TYPE_MISC | INTR_MPSAFE, 338 upd7210intr, &sc->upd7210, &sc->intr_handler); 339 340 /* Necessary magic for MITE */ 341 bus_space_write_4(sc->bt0, sc->bh0, 0xc0, vtophys(sc->bh1) | 0x80); 342 343 tst_exec(sc, tst_reset, "Reset"); 344 tst_exec(sc, tst_read_reg, "Read registers"); 345 tst_exec(sc, tst_bsr_dcr, "BSR & DCR"); 346 tst_exec(sc, tst_adr0_1, "ADR0,1"); 347 tst_exec(sc, tst_cdor_dir, "CDOR/DIR"); 348 tst_exec(sc, tst_spmr_spsr, "CPMR/SPSR"); 349 tst_exec(sc, tst_count0_1, "COUNT0:1"); 350 tst_exec(sc, tst_reset, "Reset"); 351 352 /* pass 7210 interrupts through */ 353 bus_space_write_1(sc->bt1, sc->bh1, imr3, 0x02); 354 355 for (i = 0; i < 8; i++) { 356 sc->upd7210.reg_tag[i] = sc->bt1; 357 sc->upd7210.reg_handle[i] = sc->bh1; 358 sc->upd7210.reg_offset[i] = i * 2; 359 } 360 361 /* No DMA help */ 362 sc->upd7210.dmachan = -1; 363 364 upd7210attach(&sc->upd7210); 365 366 return (0); 367} 368 369static int 370tnt_detach(device_t dev) 371{ 372 struct tnt_softc *sc; 373 374 sc = device_get_softc(dev); 375 bus_teardown_intr(dev, sc->res2, sc->intr_handler); 376 upd7210detach(&sc->upd7210); 377 378 bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), sc->res0); 379 bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(1), sc->res1); 380 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res2); 381 382 return (0); 383} 384 385static device_method_t tnt4882_methods[] = { 386 DEVMETHOD(device_probe, tnt_probe), 387 DEVMETHOD(device_attach, tnt_attach), 388 DEVMETHOD(device_detach, tnt_detach), 389 { 0, 0 } 390}; 391 392static driver_t pci_gpib_driver = { 393 "tnt4882", 394 tnt4882_methods, 395 sizeof(struct tnt_softc) 396}; 397 398static devclass_t pci_gpib_devclass; 399 400DRIVER_MODULE(pci_gpib, pci, pci_gpib_driver, pci_gpib_devclass, 0, 0); 401