tnt4882.c revision 166914
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 166914 2007-02-23 19:34:52Z imp $ 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 *res[3]; 55 void *intr_handler; 56}; 57 58static struct resource_spec tnt_res_spec[] = { 59 { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE}, 60 { SYS_RES_MEMORY, PCIR_BAR(1), RF_ACTIVE}, 61 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE}, 62 { -1, 0 } 63}; 64 65enum tnt4882reg { 66 dir = 0x00, 67 cdor = 0x00, 68 isr1 = 0x02, 69 imr1 = 0x02, 70 isr2 = 0x04, 71 imr2 = 0x04, 72 accwr = 0x05, 73 spsr = 0x06, 74 spmr = 0x06, 75 intr = 0x07, 76 adsr = 0x08, 77 admr = 0x08, 78 cnt2 = 0x09, 79 cptr = 0x0a, 80 auxmr = 0x0a, 81 tauxcr = 0x0a, /* 9914 mode register */ 82 cnt3 = 0x0b, 83 adr0 = 0x0c, 84 adr = 0x0c, 85 hssel = 0x0d, 86 adr1 = 0x0e, 87 eosr = 0x0e, 88 sts1 = 0x10, 89 cfg = 0x10, 90 dsr = 0x11, 91 sh_cnt = 0x11, 92 imr3 = 0x12, 93 hier = 0x13, 94 cnt0 = 0x14, 95 misc = 0x15, 96 cnt1 = 0x16, 97 csr = 0x17, 98 keyreg = 0x17, 99 fifob = 0x18, 100 fifoa = 0x19, 101 isr3 = 0x1a, 102 ccr = 0x1a, 103 sasr = 0x1b, 104 dcr = 0x1b, 105 sts2 = 0x1c, 106 cmdr = 0x1c, 107 isr0 = 0x1d, 108 imr0 = 0x1d, 109 timer = 0x1e, 110 bsr = 0x1f, 111 bcr = 0x1f 112}; 113 114struct tst { 115 enum {RD, WT, xDELAY, END} 116 action; 117 enum tnt4882reg reg; 118 uint8_t val; 119}; 120 121/* 122 * From NI Application note 095: 123 * Writing Functional Self-Tests for the TNT4882 GPIB Interface Chip 124 * XXX: fill in the rest ? 125 */ 126static struct tst tst_reset[] = { 127 {WT, tauxcr, 0x80}, /* chip reset if in 9914 mode */ 128 {WT, auxmr, 0x80}, /* swrst if swapped */ 129 {WT, tauxcr, 0x99}, /* switch to 7210 mode */ 130 {WT, auxmr, 0x99}, /* switch to 7210 mode if swapped */ 131 {WT, auxmr, 0x02}, /* execute chip reset */ 132 {WT, keyreg, 0x00}, /* important! clear the swap bit */ 133 {WT, eosr, 0x00}, /* clear EOS register */ 134 {WT, cdor, 0x00}, /* clear data lines */ 135 {WT, imr1, 0x00}, /* disable all interrupts */ 136 {WT, imr2, 0x00}, 137 {WT, imr0, 0x80}, 138 {WT, adr, 0x80}, 139 {WT, adr, 0x00}, 140 {WT, admr, 0x00}, /* clear addressing modes */ 141 {WT, auxmr, 0x00}, /* release from idle state with pon */ 142 {WT, auxmr, 0x60}, /* reset ppr */ 143 {WT, bcr, 0x00}, /* reset bcr */ 144 {WT, misc, 0x04}, /* set wrap plug bit */ 145 {WT, cmdr, 0xB2}, /* issue soft reset */ 146 {WT, hssel, 0x00}, /* select two-chip mode */ 147 {END, 0, 0} 148}; 149 150static struct tst tst_read_reg[] = { 151 {RD, isr1, 0x00}, /* Verify mask registers are clear */ 152 {RD, isr2, 0x00}, 153 {RD, adsr, 0x40}, /* Verify ATN is not asserted */ 154 {RD, adr0, 0x00}, /* Verify Primary address not set */ 155 {RD, adr1, 0x00}, /* Verify Secondary address not set */ 156 {RD, sts1, 0x8B}, /* Verify DONE, STOP, HALT, and GSYNC set */ 157 {RD, isr3, 0x19}, /* Verify STOP, Not Full FIFO, & DONE set */ 158 {RD, sts2, 0x9A}, /* Verify FIFO A/B is empty */ 159 {RD, sasr, 0x00}, /* Verify clear */ 160 {RD, isr0, 0x01}, /* Verify SYNC bit is set */ 161 {END, 0, 0} 162}; 163 164static struct tst tst_bsr_dcr[] = { 165 {WT, bcr, 0x55}, /* Set DAV, NRFD, SRQ, and REN */ 166 {WT, dcr, 0xAA}, /* Write pattern to GPIB data lines */ 167 {RD, bsr, 0x55}, /* Verify DAV, NRFD, SRQ, and REN are set */ 168 {RD, dsr, 0xAA}, /* Verify data pattern written previously */ 169 {WT, bcr, 0xAA}, /* Set ATN, NDAC, EOI, & IFC */ 170 {WT, dcr, 0x55}, /* Write pattern to GPIB data lines */ 171 {RD, bsr, 0xAA}, /* Verify ATN, NDAC, EOI, & IFC are set */ 172 {RD, dsr, 0x55}, /* Verify data pattern written previously */ 173 {WT, bcr, 0x00}, /* Clear control lines */ 174 {WT, dcr, 0x00}, /* Clear data lines */ 175 {RD, bsr, 0x00}, /* Verify control lines are clear */ 176 {RD, dsr, 0x00}, /* Verify data lines are clear */ 177 {END, 0, 0} 178}; 179 180static struct tst tst_adr0_1[] = { 181 {WT, adr, 0x55}, /* Set Primary talk address */ 182 {WT, adr, 0xAA}, /* Set Secondary listen address */ 183 {RD, adr0, 0x55}, /* Read Primary address */ 184 {RD, adr1, 0x2A}, /* Read Secondary address */ 185 {WT, adr, 0x2A}, /* Set Primay listen address */ 186 {WT, adr, 0xD5}, /* Set Secondary talk address */ 187 {RD, adr0, 0x2A}, /* Read Primary address */ 188 {RD, adr1, 0x55}, /* Read Secondary address */ 189 {END, 0, 0} 190}; 191 192static struct tst tst_cdor_dir[] = { 193 {WT, admr, 0xF0}, /* program AT-GPIB as talker only and 194 * listener only */ 195 {RD, isr1, 0x02}, /* check DO bit set */ 196 {RD, adsr, 0x46}, /* check AT-GPIB is both talker active 197 * and listener active */ 198 {WT, cdor, 0xAA}, /* write out data byte */ 199 {xDELAY, 0, 1}, /* One ISA I/O Cycle (500-ns) */ 200 {RD, isr1, 0x03}, /* check DO and DI bits set */ 201 {RD, dir, 0xAA}, /* verify data received */ 202 {WT, cdor, 0x55}, /* write out data byte */ 203 {xDELAY, 0, 1}, /* One ISA I/O Cycle (500-ns) */ 204 {RD, dir, 0x55}, /* verify data received */ 205 {END, 0, 0} 206}; 207 208static struct tst tst_spmr_spsr[] = { 209 {WT, spsr, 0x00}, /* Write pattern to SPSR register */ 210 {RD, spmr, 0x00}, /* Read back previously written pattern */ 211 {WT, spsr, 0xBF}, /* Write pattern to SPSR register */ 212 {RD, spmr, 0xBF}, /* Read back previously written pattern */ 213 {END, 0, 0} 214}; 215 216static struct tst tst_count0_1[] = { 217 {WT, cnt0, 0x55}, /* Verify every other bit can be set */ 218 {WT, cnt1, 0xAA}, 219 {RD, cnt0, 0x55}, /* Read back previously written pattern */ 220 {RD, cnt1, 0xAA}, 221 {WT, cnt0, 0xAA}, /* Verify every other bit can be set */ 222 {WT, cnt1, 0x55}, 223 {RD, cnt0, 0xAA}, /* Read back previously written pattern */ 224 {RD, cnt1, 0x55}, 225 {END, 0, 0} 226}; 227 228static int 229tst_exec(struct tnt_softc *sc, struct tst *tp, const char *name) 230{ 231 uint8_t u; 232 int step; 233 234 for (step = 0; tp->action != END; tp++, step++) { 235 switch (tp->action) { 236 case WT: 237 bus_write_1(sc->res[1], tp->reg, tp->val); 238 break; 239 case RD: 240 u = bus_read_1(sc->res[1], tp->reg); 241 if (u != tp->val) { 242 printf( 243 "Test %s, step %d: reg(%02x) = %02x", 244 name, step, tp->reg, u); 245 printf( "should have been %02x\n", tp->val); 246 return (1); 247 } 248 break; 249 case xDELAY: 250 DELAY(tp->val); 251 break; 252 default: 253 printf("Unknown action in test %s, step %d: %d\n", 254 name, step, tp->action); 255 return (1); 256 } 257 } 258 if (bootverbose) 259 printf("Test %s passed\n", name); 260 return (0); 261} 262 263static int 264tnt_probe(device_t dev) 265{ 266 267 if (pci_get_vendor(dev) == 0x1093 && pci_get_device(dev) == 0xc801) { 268 device_set_desc(dev, "NI PCI-GPIB"); 269 return (BUS_PROBE_DEFAULT); 270 } 271 return (ENXIO); 272} 273 274static int 275tnt_attach(device_t dev) 276{ 277 struct tnt_softc *sc; 278 int error, i; 279 280 sc = device_get_softc(dev); 281 282 error = bus_alloc_resources(dev, tnt_res_spec, sc->res); 283 if (error) 284 return (error); 285 286 error = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE, 287 NULL, upd7210intr, &sc->upd7210, &sc->intr_handler); 288 289 /* Necessary magic for MITE */ 290 bus_write_4(sc->res[0], 0xc0, rman_get_start(sc->res[1]) | 0x80); 291 292 tst_exec(sc, tst_reset, "Reset"); 293 tst_exec(sc, tst_read_reg, "Read registers"); 294 tst_exec(sc, tst_bsr_dcr, "BSR & DCR"); 295 tst_exec(sc, tst_adr0_1, "ADR0,1"); 296 tst_exec(sc, tst_cdor_dir, "CDOR/DIR"); 297 tst_exec(sc, tst_spmr_spsr, "CPMR/SPSR"); 298 tst_exec(sc, tst_count0_1, "COUNT0:1"); 299 tst_exec(sc, tst_reset, "Reset"); 300 301 /* pass 7210 interrupts through */ 302 bus_write_1(sc->res[1], imr3, 0x02); 303 304 for (i = 0; i < 8; i++) { 305 sc->upd7210.reg_res[i] = sc->res[1]; 306 sc->upd7210.reg_offset[i] = i * 2; 307 } 308 309 /* No DMA help */ 310 sc->upd7210.dmachan = -1; 311 312 upd7210attach(&sc->upd7210); 313 314 return (0); 315} 316 317static int 318tnt_detach(device_t dev) 319{ 320 struct tnt_softc *sc; 321 322 sc = device_get_softc(dev); 323 bus_teardown_intr(dev, sc->res[2], sc->intr_handler); 324 upd7210detach(&sc->upd7210); 325 326 bus_release_resources(dev, tnt_res_spec, sc->res); 327 328 return (0); 329} 330 331static device_method_t tnt4882_methods[] = { 332 DEVMETHOD(device_probe, tnt_probe), 333 DEVMETHOD(device_attach, tnt_attach), 334 DEVMETHOD(device_detach, tnt_detach), 335 { 0, 0 } 336}; 337 338static driver_t pci_gpib_driver = { 339 "tnt4882", 340 tnt4882_methods, 341 sizeof(struct tnt_softc) 342}; 343 344static devclass_t pci_gpib_devclass; 345 346DRIVER_MODULE(pci_gpib, pci, pci_gpib_driver, pci_gpib_devclass, 0, 0); 347