upd7210.c revision 156573
1141398Sphk/*- 2141398Sphk * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org> 3141398Sphk * All rights reserved. 4141398Sphk * 5141398Sphk * Redistribution and use in source and binary forms, with or without 6141398Sphk * modification, are permitted provided that the following conditions 7141398Sphk * are met: 8141398Sphk * 1. Redistributions of source code must retain the above copyright 9141398Sphk * notice, this list of conditions and the following disclaimer. 10141398Sphk * 2. Redistributions in binary form must reproduce the above copyright 11141398Sphk * notice, this list of conditions and the following disclaimer in the 12141398Sphk * documentation and/or other materials provided with the distribution. 13141398Sphk * 14141398Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15141398Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16141398Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17141398Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18141398Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19141398Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20141398Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21141398Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22141398Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23141398Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24141398Sphk * SUCH DAMAGE. 25141398Sphk * 26141398Sphk * High-level driver for �PD7210 based GPIB cards. 27141398Sphk * 28141398Sphk */ 29141398Sphk 30141398Sphk#include <sys/cdefs.h> 31141398Sphk__FBSDID("$FreeBSD: head/sys/dev/ieee488/upd7210.c 156573 2006-03-11 15:39:22Z phk $"); 32141398Sphk 33141398Sphk# define GPIB_DEBUG 34141398Sphk# undef GPIB_DEBUG 35141398Sphk 36141398Sphk#include <sys/param.h> 37141398Sphk#include <sys/systm.h> 38141398Sphk#include <sys/conf.h> 39141398Sphk#include <sys/malloc.h> 40141398Sphk#include <sys/kernel.h> 41141398Sphk#include <sys/limits.h> 42141398Sphk#include <sys/module.h> 43150525Sphk#include <sys/rman.h> 44141398Sphk#include <sys/bus.h> 45141398Sphk#include <sys/lock.h> 46141398Sphk#include <sys/mutex.h> 47141398Sphk#include <sys/uio.h> 48141398Sphk#include <sys/time.h> 49141398Sphk#include <machine/bus.h> 50141398Sphk#include <machine/resource.h> 51141398Sphk#include <isa/isavar.h> 52141398Sphk 53141747Sphk#define UPD7210_HW_DRIVER 54141747Sphk#define UPD7210_SW_DRIVER 55141398Sphk#include <dev/ieee488/upd7210.h> 56141398Sphk 57141621Sphkstatic MALLOC_DEFINE(M_GPIB, "GPIB", "GPIB"); 58141398Sphk 59141398Sphk/* upd7210 generic stuff */ 60141398Sphk 61141747Sphkvoid 62141747Sphkupd7210_print_isr(u_int isr1, u_int isr2) 63141398Sphk{ 64141398Sphk printf("isr1=0x%b isr2=0x%b", 65141398Sphk isr1, "\20\10CPT\7APT\6DET\5ENDRX\4DEC\3ERR\2DO\1DI", 66141398Sphk isr2, "\20\10INT\7SRQI\6LOK\5REM\4CO\3LOKC\2REMC\1ADSC"); 67141398Sphk} 68141398Sphk 69141747Sphku_int 70141747Sphkupd7210_rd(struct upd7210 *u, enum upd7210_rreg reg) 71141398Sphk{ 72141398Sphk u_int r; 73141398Sphk 74150525Sphk r = bus_read_1(u->reg_res[reg], u->reg_offset[reg]); 75141398Sphk u->rreg[reg] = r; 76141398Sphk return (r); 77141398Sphk} 78141398Sphk 79141747Sphkvoid 80141747Sphkupd7210_wr(struct upd7210 *u, enum upd7210_wreg reg, u_int val) 81141398Sphk{ 82150153Sphk 83150525Sphk bus_write_1(u->reg_res[reg], u->reg_offset[reg], val); 84141398Sphk u->wreg[reg] = val; 85141398Sphk if (reg == AUXMR) 86141398Sphk u->wreg[8 + (val >> 5)] = val & 0x1f; 87141398Sphk} 88141398Sphk 89141398Sphkvoid 90141398Sphkupd7210intr(void *arg) 91141398Sphk{ 92141398Sphk u_int isr1, isr2; 93141398Sphk struct upd7210 *u; 94141398Sphk 95141398Sphk u = arg; 96141398Sphk mtx_lock(&u->mutex); 97141747Sphk isr1 = upd7210_rd(u, ISR1); 98141747Sphk isr2 = upd7210_rd(u, ISR2); 99141747Sphk if (u->busy == 0 || u->irq == NULL || !u->irq(u, 1)) { 100156573Sphk#if 0 101141398Sphk printf("upd7210intr [%02x %02x %02x", 102141747Sphk upd7210_rd(u, DIR), isr1, isr2); 103141398Sphk printf(" %02x %02x %02x %02x %02x] ", 104141747Sphk upd7210_rd(u, SPSR), 105141747Sphk upd7210_rd(u, ADSR), 106141747Sphk upd7210_rd(u, CPTR), 107141747Sphk upd7210_rd(u, ADR0), 108141747Sphk upd7210_rd(u, ADR1)); 109141747Sphk upd7210_print_isr(isr1, isr2); 110141398Sphk printf("\n"); 111156573Sphk#endif 112141398Sphk } 113141398Sphk mtx_unlock(&u->mutex); 114141398Sphk} 115141398Sphk 116141747Sphkint 117141398Sphkupd7210_take_ctrl_async(struct upd7210 *u) 118141398Sphk{ 119141398Sphk int i; 120141398Sphk 121141747Sphk upd7210_wr(u, AUXMR, AUXMR_TCA); 122141398Sphk 123141747Sphk if (!(upd7210_rd(u, ADSR) & ADSR_ATN)) 124141398Sphk return (0); 125141398Sphk for (i = 0; i < 20; i++) { 126141398Sphk DELAY(1); 127141747Sphk if (!(upd7210_rd(u, ADSR) & ADSR_ATN)) 128141398Sphk return (0); 129141398Sphk } 130141398Sphk return (1); 131141398Sphk} 132141398Sphk 133141747Sphkint 134141398Sphkupd7210_goto_standby(struct upd7210 *u) 135141398Sphk{ 136141398Sphk int i; 137141398Sphk 138141747Sphk upd7210_wr(u, AUXMR, AUXMR_GTS); 139141398Sphk 140141747Sphk if (upd7210_rd(u, ADSR) & ADSR_ATN) 141141398Sphk return (0); 142141398Sphk for (i = 0; i < 20; i++) { 143141398Sphk DELAY(1); 144141747Sphk if (upd7210_rd(u, ADSR) & ADSR_ATN) 145141398Sphk return (0); 146141398Sphk } 147141398Sphk return (1); 148141398Sphk} 149141398Sphk 150141398Sphk/* Unaddressed Listen Only mode */ 151141398Sphk 152141398Sphkstatic int 153141747Sphkgpib_l_irq(struct upd7210 *u, int intr __unused) 154141398Sphk{ 155141398Sphk int i; 156141398Sphk 157141398Sphk if (u->rreg[ISR1] & 1) { 158141747Sphk i = upd7210_rd(u, DIR); 159141398Sphk u->buf[u->buf_wp++] = i; 160141398Sphk u->buf_wp &= (u->bufsize - 1); 161141398Sphk i = (u->buf_rp + u->bufsize - u->buf_wp) & (u->bufsize - 1); 162141398Sphk if (i < 8) 163141747Sphk upd7210_wr(u, IMR1, 0); 164141398Sphk wakeup(u->buf); 165141398Sphk return (1); 166141398Sphk } 167141398Sphk return (0); 168141398Sphk} 169141398Sphk 170141398Sphkstatic int 171141398Sphkgpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 172141398Sphk{ 173141398Sphk struct upd7210 *u; 174141398Sphk 175141398Sphk u = dev->si_drv1; 176141398Sphk 177141398Sphk mtx_lock(&u->mutex); 178144633Sphk if (u->busy) { 179144633Sphk mtx_unlock(&u->mutex); 180141398Sphk return (EBUSY); 181144633Sphk } 182141398Sphk u->busy = 1; 183141398Sphk u->irq = gpib_l_irq; 184141398Sphk mtx_unlock(&u->mutex); 185141398Sphk 186141398Sphk u->buf = malloc(PAGE_SIZE, M_GPIB, M_WAITOK); 187141398Sphk u->bufsize = PAGE_SIZE; 188141398Sphk u->buf_wp = 0; 189141398Sphk u->buf_rp = 0; 190141398Sphk 191141747Sphk upd7210_wr(u, AUXMR, AUXMR_CRST); 192141398Sphk DELAY(10000); 193141747Sphk upd7210_wr(u, AUXMR, C_ICR | 8); 194141398Sphk DELAY(1000); 195141747Sphk upd7210_wr(u, ADR, 0x60); 196141747Sphk upd7210_wr(u, ADR, 0xe0); 197141747Sphk upd7210_wr(u, ADMR, 0x70); 198141747Sphk upd7210_wr(u, AUXMR, AUXMR_PON); 199141747Sphk upd7210_wr(u, IMR1, 0x01); 200141398Sphk return (0); 201141398Sphk} 202141398Sphk 203141398Sphkstatic int 204141398Sphkgpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td) 205141398Sphk{ 206141398Sphk struct upd7210 *u; 207141398Sphk 208141398Sphk u = dev->si_drv1; 209141398Sphk 210141398Sphk mtx_lock(&u->mutex); 211141398Sphk u->busy = 0; 212141747Sphk upd7210_wr(u, AUXMR, AUXMR_CRST); 213141398Sphk DELAY(10000); 214141747Sphk upd7210_wr(u, IMR1, 0x00); 215141747Sphk upd7210_wr(u, IMR2, 0x00); 216141398Sphk free(u->buf, M_GPIB); 217141398Sphk u->buf = NULL; 218141398Sphk mtx_unlock(&u->mutex); 219141398Sphk return (0); 220141398Sphk} 221141398Sphk 222141398Sphkstatic int 223141398Sphkgpib_l_read(struct cdev *dev, struct uio *uio, int ioflag) 224141398Sphk{ 225141398Sphk struct upd7210 *u; 226141398Sphk int error; 227141398Sphk size_t z; 228141398Sphk 229141398Sphk u = dev->si_drv1; 230141398Sphk error = 0; 231141398Sphk 232141398Sphk mtx_lock(&u->mutex); 233141398Sphk while (u->buf_wp == u->buf_rp) { 234141398Sphk error = msleep(u->buf, &u->mutex, PZERO | PCATCH, 235141398Sphk "gpibrd", hz); 236141398Sphk if (error && error != EWOULDBLOCK) { 237141398Sphk mtx_unlock(&u->mutex); 238141398Sphk return (error); 239141398Sphk } 240141398Sphk } 241141398Sphk while (uio->uio_resid > 0 && u->buf_wp != u->buf_rp) { 242141398Sphk if (u->buf_wp < u->buf_rp) 243141398Sphk z = u->bufsize - u->buf_rp; 244141398Sphk else 245141398Sphk z = u->buf_wp - u->buf_rp; 246141398Sphk if (z > uio->uio_resid) 247141398Sphk z = uio->uio_resid; 248141398Sphk mtx_unlock(&u->mutex); 249141398Sphk error = uiomove(u->buf + u->buf_rp, z, uio); 250141398Sphk mtx_lock(&u->mutex); 251141398Sphk if (error) 252141398Sphk break; 253141398Sphk u->buf_rp += z; 254141398Sphk u->buf_rp &= (u->bufsize - 1); 255141398Sphk } 256141398Sphk if (u->wreg[IMR1] == 0) 257141747Sphk upd7210_wr(u, IMR1, 0x01); 258141398Sphk mtx_unlock(&u->mutex); 259141398Sphk return (error); 260141398Sphk} 261141398Sphk 262141621Sphkstatic struct cdevsw gpib_l_cdevsw = { 263141398Sphk .d_version = D_VERSION, 264141398Sphk .d_name = "gpib_l", 265141398Sphk .d_open = gpib_l_open, 266141398Sphk .d_close = gpib_l_close, 267141398Sphk .d_read = gpib_l_read, 268141398Sphk}; 269141398Sphk 270141398Sphk/* Housekeeping */ 271141398Sphk 272150153Sphkstatic struct unrhdr *units; 273150153Sphk 274141398Sphkvoid 275141398Sphkupd7210attach(struct upd7210 *u) 276141398Sphk{ 277141398Sphk struct cdev *dev; 278141398Sphk 279150153Sphk if (units == NULL) 280150153Sphk units = new_unrhdr(0, minor2unit(MAXMINOR), NULL); 281150153Sphk u->unit = alloc_unr(units); 282141398Sphk mtx_init(&u->mutex, "gpib", NULL, MTX_DEF); 283150153Sphk u->cdev = make_dev(&gpib_l_cdevsw, u->unit, 284141398Sphk UID_ROOT, GID_WHEEL, 0444, 285150153Sphk "gpib%ul", u->unit); 286141398Sphk u->cdev->si_drv1 = u; 287141398Sphk 288150153Sphk dev = make_dev(&gpib_ib_cdevsw, u->unit, 289141398Sphk UID_ROOT, GID_WHEEL, 0444, 290150153Sphk "gpib%uib", u->unit); 291141398Sphk dev->si_drv1 = u; 292141398Sphk dev_depends(u->cdev, dev); 293141398Sphk} 294150153Sphk 295150153Sphkvoid 296150153Sphkupd7210detach(struct upd7210 *u) 297150153Sphk{ 298150153Sphk 299150153Sphk destroy_dev(u->cdev); 300150153Sphk mtx_destroy(&u->mutex); 301150153Sphk free_unr(units, u->unit); 302150153Sphk} 303