8255.c revision c5efe58b83bc5c1d5811800faf03b1089d1ef054
16ca2733471190dd93b627a58148c1aeab5e0d797David Schleef/* 26ca2733471190dd93b627a58148c1aeab5e0d797David Schleef comedi/drivers/8255.c 36ca2733471190dd93b627a58148c1aeab5e0d797David Schleef Driver for 8255 46ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 56ca2733471190dd93b627a58148c1aeab5e0d797David Schleef COMEDI - Linux Control and Measurement Device Interface 66ca2733471190dd93b627a58148c1aeab5e0d797David Schleef Copyright (C) 1998 David A. Schleef <ds@schleef.org> 76ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 86ca2733471190dd93b627a58148c1aeab5e0d797David Schleef This program is free software; you can redistribute it and/or modify 96ca2733471190dd93b627a58148c1aeab5e0d797David Schleef it under the terms of the GNU General Public License as published by 106ca2733471190dd93b627a58148c1aeab5e0d797David Schleef the Free Software Foundation; either version 2 of the License, or 116ca2733471190dd93b627a58148c1aeab5e0d797David Schleef (at your option) any later version. 126ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 136ca2733471190dd93b627a58148c1aeab5e0d797David Schleef This program is distributed in the hope that it will be useful, 146ca2733471190dd93b627a58148c1aeab5e0d797David Schleef but WITHOUT ANY WARRANTY; without even the implied warranty of 156ca2733471190dd93b627a58148c1aeab5e0d797David Schleef MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 166ca2733471190dd93b627a58148c1aeab5e0d797David Schleef GNU General Public License for more details. 176ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 186ca2733471190dd93b627a58148c1aeab5e0d797David Schleef You should have received a copy of the GNU General Public License 196ca2733471190dd93b627a58148c1aeab5e0d797David Schleef along with this program; if not, write to the Free Software 206ca2733471190dd93b627a58148c1aeab5e0d797David Schleef Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 216ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 226ca2733471190dd93b627a58148c1aeab5e0d797David Schleef*/ 236ca2733471190dd93b627a58148c1aeab5e0d797David Schleef/* 246ca2733471190dd93b627a58148c1aeab5e0d797David SchleefDriver: 8255 256ca2733471190dd93b627a58148c1aeab5e0d797David SchleefDescription: generic 8255 support 266ca2733471190dd93b627a58148c1aeab5e0d797David SchleefDevices: [standard] 8255 (8255) 276ca2733471190dd93b627a58148c1aeab5e0d797David SchleefAuthor: ds 286ca2733471190dd93b627a58148c1aeab5e0d797David SchleefStatus: works 296ca2733471190dd93b627a58148c1aeab5e0d797David SchleefUpdated: Fri, 7 Jun 2002 12:56:45 -0700 306ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 316ca2733471190dd93b627a58148c1aeab5e0d797David SchleefThe classic in digital I/O. The 8255 appears in Comedi as a single 326ca2733471190dd93b627a58148c1aeab5e0d797David Schleefdigital I/O subdevice with 24 channels. The channel 0 corresponds 336ca2733471190dd93b627a58148c1aeab5e0d797David Schleefto the 8255's port A, bit 0; channel 23 corresponds to port C, bit 346ca2733471190dd93b627a58148c1aeab5e0d797David Schleef7. Direction configuration is done in blocks, with channels 0-7, 356ca2733471190dd93b627a58148c1aeab5e0d797David Schleef8-15, 16-19, and 20-23 making up the 4 blocks. The only 8255 mode 366ca2733471190dd93b627a58148c1aeab5e0d797David Schleefsupported is mode 0. 376ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 386ca2733471190dd93b627a58148c1aeab5e0d797David SchleefYou should enable compilation this driver if you plan to use a board 396ca2733471190dd93b627a58148c1aeab5e0d797David Schleefthat has an 8255 chip. For multifunction boards, the main driver will 406ca2733471190dd93b627a58148c1aeab5e0d797David Schleefconfigure the 8255 subdevice automatically. 416ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 426ca2733471190dd93b627a58148c1aeab5e0d797David SchleefThis driver also works independently with ISA and PCI cards that 436ca2733471190dd93b627a58148c1aeab5e0d797David Schleefdirectly map the 8255 registers to I/O ports, including cards with 446ca2733471190dd93b627a58148c1aeab5e0d797David Schleefmultiple 8255 chips. To configure the driver for such a card, the 456ca2733471190dd93b627a58148c1aeab5e0d797David Schleefoption list should be a list of the I/O port bases for each of the 466ca2733471190dd93b627a58148c1aeab5e0d797David Schleef8255 chips. For example, 476ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 486ca2733471190dd93b627a58148c1aeab5e0d797David Schleef comedi_config /dev/comedi0 8255 0x200,0x204,0x208,0x20c 496ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 506ca2733471190dd93b627a58148c1aeab5e0d797David SchleefNote that most PCI 8255 boards do NOT work with this driver, and 516ca2733471190dd93b627a58148c1aeab5e0d797David Schleefneed a separate driver as a wrapper. For those that do work, the 526ca2733471190dd93b627a58148c1aeab5e0d797David SchleefI/O port base address can be found in the output of 'lspci -v'. 536ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 546ca2733471190dd93b627a58148c1aeab5e0d797David Schleef*/ 556ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 566ca2733471190dd93b627a58148c1aeab5e0d797David Schleef/* 576ca2733471190dd93b627a58148c1aeab5e0d797David Schleef This file contains an exported subdevice for driving an 8255. 586ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 596ca2733471190dd93b627a58148c1aeab5e0d797David Schleef To use this subdevice as part of another driver, you need to 606ca2733471190dd93b627a58148c1aeab5e0d797David Schleef set up the subdevice in the attach function of the driver by 616ca2733471190dd93b627a58148c1aeab5e0d797David Schleef calling: 626ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 636ca2733471190dd93b627a58148c1aeab5e0d797David Schleef subdev_8255_init(device, subdevice, callback_function, arg) 646ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 656ca2733471190dd93b627a58148c1aeab5e0d797David Schleef device and subdevice are pointers to the device and subdevice 666ca2733471190dd93b627a58148c1aeab5e0d797David Schleef structures. callback_function will be called to provide the 676ca2733471190dd93b627a58148c1aeab5e0d797David Schleef low-level input/output to the device, i.e., actual register 686ca2733471190dd93b627a58148c1aeab5e0d797David Schleef access. callback_function will be called with the value of arg 696ca2733471190dd93b627a58148c1aeab5e0d797David Schleef as the last parameter. If the 8255 device is mapped as 4 706ca2733471190dd93b627a58148c1aeab5e0d797David Schleef consecutive I/O ports, you can use NULL for callback_function 716ca2733471190dd93b627a58148c1aeab5e0d797David Schleef and the I/O port base for arg, and an internal function will 726ca2733471190dd93b627a58148c1aeab5e0d797David Schleef handle the register access. 736ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 746ca2733471190dd93b627a58148c1aeab5e0d797David Schleef In addition, if the main driver handles interrupts, you can 756ca2733471190dd93b627a58148c1aeab5e0d797David Schleef enable commands on the subdevice by calling subdev_8255_init_irq() 766ca2733471190dd93b627a58148c1aeab5e0d797David Schleef instead. Then, when you get an interrupt that is likely to be 776ca2733471190dd93b627a58148c1aeab5e0d797David Schleef from the 8255, you should call subdev_8255_interrupt(), which 786ca2733471190dd93b627a58148c1aeab5e0d797David Schleef will copy the latched value to a Comedi buffer. 796ca2733471190dd93b627a58148c1aeab5e0d797David Schleef */ 806ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 816ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#include "../comedidev.h" 826ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 836ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#include <linux/ioport.h> 845a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 85c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartman#include "8255.h" 866ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 876ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define _8255_SIZE 4 886ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 896ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define _8255_DATA 0 906ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define _8255_CR 3 916ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 926ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CR_C_LO_IO 0x01 936ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CR_B_IO 0x02 946ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CR_B_MODE 0x04 956ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CR_C_HI_IO 0x08 966ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CR_A_IO 0x10 976ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CR_A_MODE(a) ((a)<<5) 986ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CR_CW 0x80 996ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1006ca2733471190dd93b627a58148c1aeab5e0d797David Schleefstruct subdev_8255_struct { 1016ca2733471190dd93b627a58148c1aeab5e0d797David Schleef unsigned long cb_arg; 1026ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int (*cb_func) (int, int, int, unsigned long); 1036ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int have_irq; 1046ca2733471190dd93b627a58148c1aeab5e0d797David Schleef}; 1056ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1066ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CALLBACK_ARG (((struct subdev_8255_struct *)s->private)->cb_arg) 1076ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define CALLBACK_FUNC (((struct subdev_8255_struct *)s->private)->cb_func) 1086ca2733471190dd93b627a58148c1aeab5e0d797David Schleef#define subdevpriv ((struct subdev_8255_struct *)s->private) 1096ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dev_8255_attach(struct comedi_device *dev, 1110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 11271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dev_8255_detach(struct comedi_device *dev); 113139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_8255 = { 11468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "8255", 11568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 11668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = dev_8255_attach, 11768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = dev_8255_detach, 1186ca2733471190dd93b627a58148c1aeab5e0d797David Schleef}; 1196ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1206ca2733471190dd93b627a58148c1aeab5e0d797David SchleefCOMEDI_INITCLEANUP(driver_8255); 1216ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void do_config(struct comedi_device *dev, struct comedi_subdevice *s); 1236ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 124c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartmanvoid subdev_8255_interrupt(struct comedi_device *dev, 125c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartman struct comedi_subdevice *s) 1266ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 127790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton short d; 1286ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1296ca2733471190dd93b627a58148c1aeab5e0d797David Schleef d = CALLBACK_FUNC(0, _8255_DATA, 0, CALLBACK_ARG); 1306ca2733471190dd93b627a58148c1aeab5e0d797David Schleef d |= (CALLBACK_FUNC(0, _8255_DATA + 1, 0, CALLBACK_ARG) << 8); 1316ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1326ca2733471190dd93b627a58148c1aeab5e0d797David Schleef comedi_buf_put(s->async, d); 1336ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->async->events |= COMEDI_CB_EOS; 1346ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1356ca2733471190dd93b627a58148c1aeab5e0d797David Schleef comedi_event(dev, s); 1366ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 137228ec3402130b158ccd0e690ac5c4a0b27317786Ben KeroEXPORT_SYMBOL(subdev_8255_interrupt); 1386ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1396ca2733471190dd93b627a58148c1aeab5e0d797David Schleefstatic int subdev_8255_cb(int dir, int port, int data, unsigned long arg) 1406ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 1416ca2733471190dd93b627a58148c1aeab5e0d797David Schleef unsigned long iobase = arg; 1426ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1436ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (dir) { 1446ca2733471190dd93b627a58148c1aeab5e0d797David Schleef outb(data, iobase + port); 1456ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 1466ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } else { 1476ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return inb(iobase + port); 1486ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 1496ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 1506ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_8255_insn(struct comedi_device *dev, 1520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1546ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 1556ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (data[0]) { 1566ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->state &= ~data[0]; 1576ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->state |= (data[0] & data[1]); 1586ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1596ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (data[0] & 0xff) 1606ca2733471190dd93b627a58148c1aeab5e0d797David Schleef CALLBACK_FUNC(1, _8255_DATA, s->state & 0xff, 1610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral CALLBACK_ARG); 1626ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (data[0] & 0xff00) 1636ca2733471190dd93b627a58148c1aeab5e0d797David Schleef CALLBACK_FUNC(1, _8255_DATA + 1, (s->state >> 8) & 0xff, 1640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral CALLBACK_ARG); 1656ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (data[0] & 0xff0000) 1666ca2733471190dd93b627a58148c1aeab5e0d797David Schleef CALLBACK_FUNC(1, _8255_DATA + 2, 1670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->state >> 16) & 0xff, CALLBACK_ARG); 1686ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 1696ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1706ca2733471190dd93b627a58148c1aeab5e0d797David Schleef data[1] = CALLBACK_FUNC(0, _8255_DATA, 0, CALLBACK_ARG); 1716ca2733471190dd93b627a58148c1aeab5e0d797David Schleef data[1] |= (CALLBACK_FUNC(0, _8255_DATA + 1, 0, CALLBACK_ARG) << 8); 1726ca2733471190dd93b627a58148c1aeab5e0d797David Schleef data[1] |= (CALLBACK_FUNC(0, _8255_DATA + 2, 0, CALLBACK_ARG) << 16); 1736ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1746ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 2; 1756ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 1766ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_8255_insn_config(struct comedi_device *dev, 1780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 1806ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 1816ca2733471190dd93b627a58148c1aeab5e0d797David Schleef unsigned int mask; 1826ca2733471190dd93b627a58148c1aeab5e0d797David Schleef unsigned int bits; 1836ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1846ca2733471190dd93b627a58148c1aeab5e0d797David Schleef mask = 1 << CR_CHAN(insn->chanspec); 185228ec3402130b158ccd0e690ac5c4a0b27317786Ben Kero if (mask & 0x0000ff) 1866ca2733471190dd93b627a58148c1aeab5e0d797David Schleef bits = 0x0000ff; 187228ec3402130b158ccd0e690ac5c4a0b27317786Ben Kero else if (mask & 0x00ff00) 1886ca2733471190dd93b627a58148c1aeab5e0d797David Schleef bits = 0x00ff00; 189228ec3402130b158ccd0e690ac5c4a0b27317786Ben Kero else if (mask & 0x0f0000) 1906ca2733471190dd93b627a58148c1aeab5e0d797David Schleef bits = 0x0f0000; 191228ec3402130b158ccd0e690ac5c4a0b27317786Ben Kero else 1926ca2733471190dd93b627a58148c1aeab5e0d797David Schleef bits = 0xf00000; 1936ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 1946ca2733471190dd93b627a58148c1aeab5e0d797David Schleef switch (data[0]) { 1956ca2733471190dd93b627a58148c1aeab5e0d797David Schleef case INSN_CONFIG_DIO_INPUT: 1966ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->io_bits &= ~bits; 1976ca2733471190dd93b627a58148c1aeab5e0d797David Schleef break; 1986ca2733471190dd93b627a58148c1aeab5e0d797David Schleef case INSN_CONFIG_DIO_OUTPUT: 1996ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->io_bits |= bits; 2006ca2733471190dd93b627a58148c1aeab5e0d797David Schleef break; 2016ca2733471190dd93b627a58148c1aeab5e0d797David Schleef case INSN_CONFIG_DIO_QUERY: 2026ca2733471190dd93b627a58148c1aeab5e0d797David Schleef data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT; 2036ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return insn->n; 2046ca2733471190dd93b627a58148c1aeab5e0d797David Schleef break; 2056ca2733471190dd93b627a58148c1aeab5e0d797David Schleef default: 2066ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return -EINVAL; 2076ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 2086ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2096ca2733471190dd93b627a58148c1aeab5e0d797David Schleef do_config(dev, s); 2106ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2116ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 1; 2126ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 2136ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void do_config(struct comedi_device *dev, struct comedi_subdevice *s) 2156ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 2166ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int config; 2176ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2186ca2733471190dd93b627a58148c1aeab5e0d797David Schleef config = CR_CW; 2196ca2733471190dd93b627a58148c1aeab5e0d797David Schleef /* 1 in io_bits indicates output, 1 in config indicates input */ 2206ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!(s->io_bits & 0x0000ff)) 2216ca2733471190dd93b627a58148c1aeab5e0d797David Schleef config |= CR_A_IO; 2226ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!(s->io_bits & 0x00ff00)) 2236ca2733471190dd93b627a58148c1aeab5e0d797David Schleef config |= CR_B_IO; 2246ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!(s->io_bits & 0x0f0000)) 2256ca2733471190dd93b627a58148c1aeab5e0d797David Schleef config |= CR_C_LO_IO; 2266ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!(s->io_bits & 0xf00000)) 2276ca2733471190dd93b627a58148c1aeab5e0d797David Schleef config |= CR_C_HI_IO; 2286ca2733471190dd93b627a58148c1aeab5e0d797David Schleef CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG); 2296ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 2306ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_8255_cmdtest(struct comedi_device *dev, 2320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 2330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_cmd *cmd) 2346ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 2356ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int err = 0; 2366ca2733471190dd93b627a58148c1aeab5e0d797David Schleef unsigned int tmp; 2376ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2386ca2733471190dd93b627a58148c1aeab5e0d797David Schleef /* step 1 */ 2396ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2406ca2733471190dd93b627a58148c1aeab5e0d797David Schleef tmp = cmd->start_src; 2416ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->start_src &= TRIG_NOW; 2426ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!cmd->start_src || tmp != cmd->start_src) 2436ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2446ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2456ca2733471190dd93b627a58148c1aeab5e0d797David Schleef tmp = cmd->scan_begin_src; 2466ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->scan_begin_src &= TRIG_EXT; 2476ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 2486ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2496ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2506ca2733471190dd93b627a58148c1aeab5e0d797David Schleef tmp = cmd->convert_src; 2516ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->convert_src &= TRIG_FOLLOW; 2526ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!cmd->convert_src || tmp != cmd->convert_src) 2536ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2546ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2556ca2733471190dd93b627a58148c1aeab5e0d797David Schleef tmp = cmd->scan_end_src; 2566ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->scan_end_src &= TRIG_COUNT; 2576ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 2586ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2596ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2606ca2733471190dd93b627a58148c1aeab5e0d797David Schleef tmp = cmd->stop_src; 2616ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->stop_src &= TRIG_NONE; 2626ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!cmd->stop_src || tmp != cmd->stop_src) 2636ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2646ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2656ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (err) 2666ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 1; 2676ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2686ca2733471190dd93b627a58148c1aeab5e0d797David Schleef /* step 2 */ 2696ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2706ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (err) 2716ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 2; 2726ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2736ca2733471190dd93b627a58148c1aeab5e0d797David Schleef /* step 3 */ 2746ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2756ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (cmd->start_arg != 0) { 2766ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->start_arg = 0; 2776ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2786ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 2796ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (cmd->scan_begin_arg != 0) { 2806ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->scan_begin_arg = 0; 2816ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2826ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 2836ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (cmd->convert_arg != 0) { 2846ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->convert_arg = 0; 2856ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2866ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 2876ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (cmd->scan_end_arg != 1) { 2886ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->scan_end_arg = 1; 2896ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2906ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 2916ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (cmd->stop_arg != 0) { 2926ca2733471190dd93b627a58148c1aeab5e0d797David Schleef cmd->stop_arg = 0; 2936ca2733471190dd93b627a58148c1aeab5e0d797David Schleef err++; 2946ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 2956ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2966ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (err) 2976ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 3; 2986ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 2996ca2733471190dd93b627a58148c1aeab5e0d797David Schleef /* step 4 */ 3006ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3016ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (err) 3026ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 4; 3036ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3046ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 3056ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 3066ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_8255_cmd(struct comedi_device *dev, 3080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 3096ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 3106ca2733471190dd93b627a58148c1aeab5e0d797David Schleef /* FIXME */ 3116ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3126ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 3136ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 3146ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int subdev_8255_cancel(struct comedi_device *dev, 3160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s) 3176ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 3186ca2733471190dd93b627a58148c1aeab5e0d797David Schleef /* FIXME */ 3196ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3206ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 3216ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 3226ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 323c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartmanint subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, 324c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartman int (*cb) (int, int, int, unsigned long), 325c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartman unsigned long arg) 3266ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 3276ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->type = COMEDI_SUBD_DIO; 3286ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 3296ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->n_chan = 24; 3306ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->range_table = &range_digital; 3316ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->maxdata = 1; 3326ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3336ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->private = kmalloc(sizeof(struct subdev_8255_struct), GFP_KERNEL); 3346ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!s->private) 3356ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return -ENOMEM; 3366ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3376ca2733471190dd93b627a58148c1aeab5e0d797David Schleef CALLBACK_ARG = arg; 338228ec3402130b158ccd0e690ac5c4a0b27317786Ben Kero if (cb == NULL) 3396ca2733471190dd93b627a58148c1aeab5e0d797David Schleef CALLBACK_FUNC = subdev_8255_cb; 340228ec3402130b158ccd0e690ac5c4a0b27317786Ben Kero else 3416ca2733471190dd93b627a58148c1aeab5e0d797David Schleef CALLBACK_FUNC = cb; 3426ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->insn_bits = subdev_8255_insn; 3436ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->insn_config = subdev_8255_insn_config; 3446ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3456ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->state = 0; 3466ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->io_bits = 0; 3476ca2733471190dd93b627a58148c1aeab5e0d797David Schleef do_config(dev, s); 3486ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3496ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 3506ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 351228ec3402130b158ccd0e690ac5c4a0b27317786Ben KeroEXPORT_SYMBOL(subdev_8255_init); 3526ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 353c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartmanint subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s, 354c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartman int (*cb) (int, int, int, unsigned long), 355c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartman unsigned long arg) 3566ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 3576ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int ret; 3586ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3596ca2733471190dd93b627a58148c1aeab5e0d797David Schleef ret = subdev_8255_init(dev, s, cb, arg); 3606ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (ret < 0) 3616ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return ret; 3626ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3636ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->do_cmdtest = subdev_8255_cmdtest; 3646ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->do_cmd = subdev_8255_cmd; 3656ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s->cancel = subdev_8255_cancel; 3666ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3676ca2733471190dd93b627a58148c1aeab5e0d797David Schleef subdevpriv->have_irq = 1; 3686ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3696ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 3706ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 371228ec3402130b158ccd0e690ac5c4a0b27317786Ben KeroEXPORT_SYMBOL(subdev_8255_init_irq); 3726ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 373c5efe58b83bc5c1d5811800faf03b1089d1ef054Greg Kroah-Hartmanvoid subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s) 3746ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 3756ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (s->private) { 376c4d30ee861c3a3a361f934e6f96b1d07a2889976Bill Pemberton /* this test does nothing, so comment it out 377c4d30ee861c3a3a361f934e6f96b1d07a2889976Bill Pemberton * if (subdevpriv->have_irq) { 378c4d30ee861c3a3a361f934e6f96b1d07a2889976Bill Pemberton * } 379c4d30ee861c3a3a361f934e6f96b1d07a2889976Bill Pemberton */ 3806ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3816ca2733471190dd93b627a58148c1aeab5e0d797David Schleef kfree(s->private); 3826ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 3836ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 384228ec3402130b158ccd0e690ac5c4a0b27317786Ben KeroEXPORT_SYMBOL(subdev_8255_cleanup); 3856ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3866ca2733471190dd93b627a58148c1aeab5e0d797David Schleef/* 3876ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3886ca2733471190dd93b627a58148c1aeab5e0d797David Schleef Start of the 8255 standalone device 3896ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3906ca2733471190dd93b627a58148c1aeab5e0d797David Schleef */ 3916ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dev_8255_attach(struct comedi_device *dev, 3930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it) 3946ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 3956ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int ret; 3966ca2733471190dd93b627a58148c1aeab5e0d797David Schleef unsigned long iobase; 3976ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int i; 3986ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 3996ca2733471190dd93b627a58148c1aeab5e0d797David Schleef printk("comedi%d: 8255:", dev->minor); 4006ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4016ca2733471190dd93b627a58148c1aeab5e0d797David Schleef dev->board_name = "8255"; 4026ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4036ca2733471190dd93b627a58148c1aeab5e0d797David Schleef for (i = 0; i < COMEDI_NDEVCONFOPTS; i++) { 4046ca2733471190dd93b627a58148c1aeab5e0d797David Schleef iobase = it->options[i]; 4056ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!iobase) 4066ca2733471190dd93b627a58148c1aeab5e0d797David Schleef break; 4076ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 4086ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (i == 0) { 4096ca2733471190dd93b627a58148c1aeab5e0d797David Schleef printk(" no devices specified\n"); 4106ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return -EINVAL; 4116ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 4126ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 413c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton ret = alloc_subdevices(dev, i); 414c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (ret < 0) 4156ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return ret; 4166ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4176ca2733471190dd93b627a58148c1aeab5e0d797David Schleef for (i = 0; i < dev->n_subdevices; i++) { 4186ca2733471190dd93b627a58148c1aeab5e0d797David Schleef iobase = it->options[i]; 4196ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4206ca2733471190dd93b627a58148c1aeab5e0d797David Schleef printk(" 0x%04lx", iobase); 4216ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (!request_region(iobase, _8255_SIZE, "8255")) { 4226ca2733471190dd93b627a58148c1aeab5e0d797David Schleef printk(" (I/O port conflict)"); 4236ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4246ca2733471190dd93b627a58148c1aeab5e0d797David Schleef dev->subdevices[i].type = COMEDI_SUBD_UNUSED; 4256ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } else { 4266ca2733471190dd93b627a58148c1aeab5e0d797David Schleef subdev_8255_init(dev, dev->subdevices + i, NULL, 4270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral iobase); 4286ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 4296ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 4306ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4316ca2733471190dd93b627a58148c1aeab5e0d797David Schleef printk("\n"); 4326ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4336ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 4346ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 4356ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 43671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dev_8255_detach(struct comedi_device *dev) 4376ca2733471190dd93b627a58148c1aeab5e0d797David Schleef{ 4386ca2733471190dd93b627a58148c1aeab5e0d797David Schleef int i; 4396ca2733471190dd93b627a58148c1aeab5e0d797David Schleef unsigned long iobase; 44034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 4416ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4426ca2733471190dd93b627a58148c1aeab5e0d797David Schleef printk("comedi%d: 8255: remove\n", dev->minor); 4436ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4446ca2733471190dd93b627a58148c1aeab5e0d797David Schleef for (i = 0; i < dev->n_subdevices; i++) { 4456ca2733471190dd93b627a58148c1aeab5e0d797David Schleef s = dev->subdevices + i; 4466ca2733471190dd93b627a58148c1aeab5e0d797David Schleef if (s->type != COMEDI_SUBD_UNUSED) { 4476ca2733471190dd93b627a58148c1aeab5e0d797David Schleef iobase = CALLBACK_ARG; 4486ca2733471190dd93b627a58148c1aeab5e0d797David Schleef release_region(iobase, _8255_SIZE); 4496ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 4506ca2733471190dd93b627a58148c1aeab5e0d797David Schleef subdev_8255_cleanup(dev, s); 4516ca2733471190dd93b627a58148c1aeab5e0d797David Schleef } 4526ca2733471190dd93b627a58148c1aeab5e0d797David Schleef 4536ca2733471190dd93b627a58148c1aeab5e0d797David Schleef return 0; 4546ca2733471190dd93b627a58148c1aeab5e0d797David Schleef} 455