X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/62c38bb3d6fe5ca4d22fa0e552d4eeeef0e2b61e..04ac67cc3cac14cd601daacd0592121ec0b84012:/lincan/src/tscan1.c diff --git a/lincan/src/tscan1.c b/lincan/src/tscan1.c index 049fb8d..0f8fb33 100644 --- a/lincan/src/tscan1.c +++ b/lincan/src/tscan1.c @@ -1,19 +1,42 @@ -/* tscan1.c - * Linux CAN-bus device driver. - * Written by Arnaud Westenberg email:arnaud@wanadoo.nl - * Rewritten for new CAN queues by Pavel Pisa - OCERA team member - * email:pisa@cmp.felk.cvut.cz - * This software is released under the GPL-License. - * Version lincan-0.3 17 Jun 2004 - * - * The support for TS-CAN1 and TS-7KV provided by Ronald Gomes - * from Technologic Systems - */ +/**************************************************************************/ +/* File: tscan1.c - support for TS-CAN1 PC104 card from */ +/* Technologic Systems */ +/* */ +/* LinCAN - (Not only) Linux CAN bus driver */ +/* Copyright (C) 2002-2009 DCE FEE CTU Prague */ +/* Copyright (C) 2002-2009 Pavel Pisa */ +/* Funded by OCERA and FRESCOR IST projects */ +/* Based on CAN driver code by Arnaud Westenberg */ +/* */ +/* LinCAN is free software; you can redistribute it and/or modify it */ +/* under terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2, or (at your option) any */ +/* later version. LinCAN is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */ +/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. You should have received a */ +/* copy of the GNU General Public License along with LinCAN; see file */ +/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/* To allow use of LinCAN in the compact embedded systems firmware */ +/* and RT-executives (RTEMS for example), main authors agree with next */ +/* special exception: */ +/* */ +/* Including LinCAN header files in a file, instantiating LinCAN generics */ +/* or templates, or linking other files with LinCAN objects to produce */ +/* an application image/executable, does not by itself cause the */ +/* resulting application image/executable to be covered by */ +/* the GNU General Public License. */ +/* This exception does not however invalidate any other reasons */ +/* why the executable file might be covered by the GNU Public License. */ +/* Publication of enhanced or derived LinCAN files is required although. */ +/**************************************************************************/ + #include "../include/can.h" #include "../include/can_sysdep.h" #include "../include/main.h" -#include "../include/pcm3680.h" #include "../include/sja1000p.h" #include @@ -22,18 +45,38 @@ #include "../include/tscan1.h" -short clock[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1}; -MODULE_PARM(clock, "1-" __MODULE_STRING(MAX_HW_CARDS)"i"); -MODULE_PARM_DESC(clock,"clock frequency for each board in step of 1kHz"); +unsigned long tscanio[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1}; +unsigned int tscanio_specified; + +#if defined(TSXXX_BASE_IO) +unsigned long tsxxx_base=TSXXX_BASE_IO; +#else +unsigned long tsxxx_base=0; +#endif -long canio[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1}; -MODULE_PARM(canio, "1-" __MODULE_STRING(MAX_HW_CARDS)"i"); -MODULE_PARM_DESC(canio,"CAN controller IO address for each board"); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)) +MODULE_PARM(tscanio, "1-" __MODULE_STRING(MAX_HW_CARDS)"i"); +MODULE_PARM(tsxxx_base, "1i"); +#else /* LINUX_VERSION_CODE >= 2,6,12 */ +module_param_array(tscanio, ulong, &tscanio_specified, 0); +module_param(tsxxx_base, ulong, 0); +#endif /* LINUX_VERSION_CODE >= 2,6,12 */ -long remap_io_addr[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1}; -long remap_can_addr[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1}; +MODULE_PARM_DESC(tscanio,"TSCAN CAN controller IO address for each board"); +MODULE_PARM_DESC(tsxxx_base,"The base of the ISA/8-bit IO space for TSxxx CAN peripherals in the system"); + +static unsigned long tscan1_tscanio_ranges[] = + { 0x100, 0x120, 0x180, 0x1A0, 0x200, 0x240, 0x280, 0x320}; + +static inline unsigned tscan1_read_pld_register(struct candevice_t *candev, can_ioptr_t address) +{ + return candev->hwspecops->read_register(address); +} -unsigned short isused = 0x0; +static inline void tscan1_write_pld_register(struct candevice_t *candev, unsigned data, can_ioptr_t address) +{ + candev->hwspecops->write_register(data, address); +} /** * tscan1_request_io: - reserve io or memory range for can board @@ -51,22 +94,83 @@ unsigned short isused = 0x0; */ int tscan1_request_io(struct candevice_t *candev) { - unsigned long remap_can_io_addr; + unsigned long can_io_addr; + unsigned long rebased_can_io_addr; + can_ioptr_t remap_can_io_addr; + can_ioptr_t remap_pld_io_addr; + unsigned char mode; + int i, j; + + + if (!can_request_io_region(candev->io_addr, TSCAN1_IO_RANGE, "tscan1-base")) { + CANMSG("Unable to request base IO port: 0x%lx\n", candev->io_addr); + return -ENODEV; + } else { + DEBUGMSG("Registered base IO port: 0x%lx - 0x%lx\n", + candev->io_addr, candev->io_addr+TSCAN1_IO_RANGE-1); + } + + can_io_addr = tscanio[candev->candev_idx]; + + if(can_io_addr && (can_io_addr != (unsigned long)-1)) { + rebased_can_io_addr = tsxxx_base + can_io_addr; + + if (!can_request_io_region(rebased_can_io_addr, TSCAN1_CAN_RANGE, "tscan1-can")) { + CANMSG("Unable to request CAN IO port: 0x%lx\n", rebased_can_io_addr); + can_release_io_region(candev->io_addr, TSCAN1_IO_RANGE); + return -ENODEV; + } else { + DEBUGMSG("Registered CAN IO port: 0x%lx - 0x%lx\n", + rebased_can_io_addr, rebased_can_io_addr+TSCAN1_CAN_RANGE-1); + } + } else { + for(i = 0; 1; i++) { + + if(i>=8) { + CANMSG("Unable find range for CAN IO port\n"); + can_release_io_region(candev->io_addr, TSCAN1_IO_RANGE); + return -ENODEV; + } + + can_io_addr = tscan1_tscanio_ranges[i]; + for (j = 0; j < MAX_HW_CARDS; j++) { + if(tscanio[j] == can_io_addr) { + j = -1; + break; + } + } + if(j<0) + continue; + + rebased_can_io_addr = tsxxx_base + can_io_addr; + + if (can_request_io_region(rebased_can_io_addr, TSCAN1_CAN_RANGE, "tscan1-can")) + break; + } - remap_io_addr[candev->candev_idx] = tscan1_getmappedaddr(candev->io_addr); - remap_can_io_addr = tscan1_getmappedaddr(canio[candev->candev_idx]); + tscanio[candev->candev_idx] = can_io_addr; + + DEBUGMSG("Found free range and registered CAN IO port: 0x%lx - 0x%lx\n", + rebased_can_io_addr, rebased_can_io_addr+TSCAN1_CAN_RANGE-1); + } + + remap_can_io_addr = can_ulong2ioptr(rebased_can_io_addr); - candev->dev_base_addr = remap_can_io_addr; candev->chip[0]->chip_base_addr = remap_can_io_addr; + candev->chip[0]->msgobj[0]->obj_base_addr = remap_can_io_addr; + + mode = 0x60; + for(i = 0; i < 8; i++) { + if (can_io_addr == tscan1_tscanio_ranges[i]) { + mode |= i; + break; + } + } - remap_can_addr[candev->candev_idx] = remap_can_io_addr; + remap_pld_io_addr = can_ulong2ioptr(candev->io_addr); - DEBUGMSG("IO-mem for %s: 0x%lx - 0x%lx mapped to 0x%lx\n", - candev->hwname, candev->io_addr, - candev->io_addr + TSXXX_IO_RANGE - 1, remap_io_addr[candev->candev_idx]); - DEBUGMSG("CAN-IO-mem for %s: 0x%lx - 0x%lx mapped to 0x%lx\n", - candev->hwname, canio[candev->candev_idx], - canio[candev->candev_idx] + TSXXX_CAN_RANGE - 1, candev->dev_base_addr); + tscan1_write_pld_register(candev, 0x00, remap_pld_io_addr+TSCAN1_WIN_REG); + tscan1_write_pld_register(candev, mode, remap_pld_io_addr+TSCAN1_MOD_REG); return 0; } @@ -85,6 +189,18 @@ int tscan1_request_io(struct candevice_t *candev) */ int tscan1_release_io(struct candevice_t *candev) { + unsigned long rebased_can_io_addr; + can_ioptr_t remap_pld_io_addr = can_ulong2ioptr(candev->io_addr); + + if(candev->chip[0]){ + rebased_can_io_addr = candev->chip[0]->chip_base_addr; + if(rebased_can_io_addr != (unsigned long)-1) + can_release_io_region(rebased_can_io_addr, TSCAN1_CAN_RANGE); + } + + tscan1_write_pld_register(candev, 0x20, remap_pld_io_addr+TSCAN1_MOD_REG); + + can_release_io_region(candev->io_addr, TSCAN1_IO_RANGE); return 0; } @@ -107,19 +223,19 @@ int tscan1_reset(struct candevice_t *candev) for(chipnr=0;chipnrnr_sja1000_chips;chipnr++) { chip=candev->chip[chipnr]; - tscan1_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD); + can_write_reg(chip, sjaMOD_RM, SJAMOD); udelay(1000); - tscan1_write_register(0x00, chip->chip_base_addr + SJAIER); + can_write_reg(chip, 0x00, SJAIER); udelay(1000); i=20; - while (tscan1_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){ + while (can_read_reg(chip, SJAMOD)&sjaMOD_RM){ if(!i--) return -ENODEV; udelay(1000); - tscan1_write_register(0, chip->chip_base_addr+SJAMOD); + can_write_reg(chip, 0, SJAMOD); } udelay(1000); - tscan1_write_register(sjaCDR_PELICAN, chip->chip_base_addr+SJACDR); - tscan1_write_register(0x00, chip->chip_base_addr + SJAIER); + can_write_reg(chip, sjaCDR_PELICAN, SJACDR); + can_write_reg(chip, 0x00, SJAIER); } return 0; @@ -129,6 +245,36 @@ int tscan1_reset(struct candevice_t *candev) #define NR_82527 0 #define NR_SJA1000 1 +int tscan1_check_presence(struct candevice_t *candev, unsigned long rebased_pld_io_addr, int *pjmp) +{ + can_ioptr_t remap_pld_io_addr; + int result = -ENODEV; + + if (!can_request_io_region(rebased_pld_io_addr, TSCAN1_IO_RANGE, "tscan1-probe")) + return -ENODEV; + + do { + remap_pld_io_addr = can_ulong2ioptr(rebased_pld_io_addr); + + if (tscan1_read_pld_register(candev, remap_pld_io_addr+TSCAN1_ID0_REG)!=TSCAN1_ID0 || + tscan1_read_pld_register(candev, remap_pld_io_addr+TSCAN1_ID1_REG)!=TSCAN1_ID1) + break; + + tscan1_write_pld_register(candev, 0x00, remap_pld_io_addr+TSCAN1_WIN_REG); + tscan1_write_pld_register(candev, 0x20, remap_pld_io_addr+TSCAN1_MOD_REG); + + if(pjmp) + *pjmp = tscan1_read_pld_register(candev, remap_pld_io_addr+TSCAN1_JMP_REG); + + result = 0; + } while (0); + + can_release_io_region(rebased_pld_io_addr, TSCAN1_IO_RANGE); + + return result; +} + + /** * tscan1_init_hw_data - Initialize hardware cards * @candev: Pointer to candevice/board structure @@ -146,142 +292,68 @@ int tscan1_reset(struct candevice_t *candev) int tscan1_init_hw_data(struct candevice_t *candev) { - short i, jmp; - unsigned long tsxxx_base_io = 0, io_mapped =0; - unsigned short mode; + int i, j, jmp; + unsigned long io_addr; + unsigned long rebased_pld_io_addr; - candev->io_addr = -1; - if (!strcmp(hw[candev->candev_idx],"tscan1")) - { - DEBUGMSG("Scanning bus for TS-CAN1 boards...\n"); - for (i=0;i<4;i++) - { - tsxxx_base_io = TSCAN1_BASE_IO + i*TSXXX_IO_RANGE; - io_mapped = tscan1_getmappedaddr(TSXXX_BASE_IO + tsxxx_base_io); - if (inb(io_mapped+TSXXX_ID0_REG)==TSCAN1_ID0 && - inb(io_mapped+TSXXX_ID1_REG)==TSCAN1_ID1) - { - if (isused & 1<candev_idx]!=-1 && io[candev->candev_idx]!=tsxxx_base_io) - continue; - io[candev->candev_idx] = tsxxx_base_io; - candev->io_addr = tsxxx_base_io; - candev->hwname="tscan1"; - DEBUGMSG("TS-CAN1 board was found at 0x%lx for driver %d/%s\n", tsxxx_base_io, - candev->candev_idx, candev->hwname); - isused |= 1<io_addr; + + if(io_addr && (io_addr != (unsigned long)-1)) { + rebased_pld_io_addr = io_addr + tsxxx_base; + + if(tscan1_check_presence(candev, rebased_pld_io_addr, &jmp)){ + CANMSG("No TSCAN1 card found at address 0x%lx\n", + rebased_pld_io_addr); + return -ENODEV; } - } - if (!strcmp(hw[candev->candev_idx],"ts7kv")) - { - DEBUGMSG("Scanning bus for TS-7KV boards...\n"); - for (i=4;i<8;i++) + } else { + DEBUGMSG("Scanning bus for TS-CAN1 boards...\n"); + + for (i=0; 1;i++) { - tsxxx_base_io = TS7KV_BASE_IO + (i-4)*TSXXX_IO_RANGE; - io_mapped = tscan1_getmappedaddr(TSXXX_BASE_IO + tsxxx_base_io); - if (inb(io_mapped+TSXXX_ID0_REG)==TS7KV_ID0 && - inb(io_mapped+TSXXX_ID1_REG)==TS7KV_ID1) - { - if (isused & 1<candev_idx]!=-1 && io[candev->candev_idx]!=tsxxx_base_io) - continue; - io[candev->candev_idx] = tsxxx_base_io; - candev->io_addr = tsxxx_base_io; - candev->hwname="ts7kv"; - DEBUGMSG("TS-7KV board was found at 0x%lx for driver %d/%s\n", - tsxxx_base_io, candev->candev_idx, candev->hwname); - isused |= 1<= 4) { + CANMSG("No TS-CAN1 boards found for slot %d\n", candev->candev_idx); + return -ENODEV; } - } - } - if (candev->io_addr==-1) { - DEBUGMSG("No board was found for driver %d/%s.\n", candev->candev_idx, candev->hwname); - return -1; - } + io_addr = TSCAN1_BASE_IO + i*TSCAN1_IO_RANGE; + rebased_pld_io_addr = io_addr + tsxxx_base; - if (!strcmp(candev->hwname,"tscan1")) - { - if (clock[candev->candev_idx] == -1) - clock[candev->candev_idx] = 16000; - if (irq[candev->candev_idx] == -1) - { - jmp = inb(io_mapped+TSCAN1_JMP_REG); - irq[candev->candev_idx]=0; - if (jmp&0x10 && jmp&0x20) irq[candev->candev_idx]=TSXXX_IRQ5; - else if (jmp&0x10) irq[candev->candev_idx]=TSXXX_IRQ6; - else if (jmp&0x20) irq[candev->candev_idx]=TSXXX_IRQ7; - } - if (canio[candev->candev_idx] == -1) - { - switch(candev->io_addr) { - case (TSCAN1_BASE_IO+0*TSXXX_IO_RANGE): - canio[candev->candev_idx] = 0x180; break; - case (TSCAN1_BASE_IO+1*TSXXX_IO_RANGE): - canio[candev->candev_idx] = 0x1A0; break; - case (TSCAN1_BASE_IO+2*TSXXX_IO_RANGE): - canio[candev->candev_idx] = 0x240; break; - case (TSCAN1_BASE_IO+3*TSXXX_IO_RANGE): - canio[candev->candev_idx] = 0x280; break; + for (j = 0; j < MAX_HW_CARDS; j++) { + if(io[j] == io_addr){ + j = -1; + break; + } } - } + if(j<0) + continue; - //Reseting... - switch(canio[candev->candev_idx]) { - case 0x100: mode=0x60; break; - case 0x120: mode=0x61; break; - case 0x180: mode=0x62; break; - case 0x1A0: mode=0x63; break; - case 0x200: mode=0x64; break; - case 0x240: mode=0x65; break; - case 0x280: mode=0x66; break; - case 0x320: mode=0x67; break; - default: mode=0x60; break; - } - outb(0x00, io_mapped+TSCAN1_WIN_REG); - outb(mode, io_mapped+TSCAN1_MOD_REG); - } + if(!tscan1_check_presence(candev, rebased_pld_io_addr, &jmp)) + break; - else if (!strcmp(candev->hwname,"ts7kv")) - { - if (clock[candev->candev_idx] == -1) - clock[candev->candev_idx] = 24000; - if (irq[candev->candev_idx] == -1) - { - jmp = inb(io_mapped+TS7KV_JMP_REG); - irq[candev->candev_idx]=0; - if (jmp&0x10) irq[candev->candev_idx]=TSXXX_IRQ6; - if (jmp&0x20) irq[candev->candev_idx]=TSXXX_IRQ7; } - canio[candev->candev_idx] = ((candev->io_addr>>3)&0x03)*0x20; - } + DEBUGMSG("TS-CAN1 board was found at 0x%lx for driver slot %d\n", + io_addr, candev->candev_idx); - if (baudrate[candev->candev_idx] == -1) - baudrate[candev->candev_idx] = 1000; - - io[candev->candev_idx] += TSXXX_BASE_IO; - candev->io_addr = io[candev->candev_idx]; - canio[candev->candev_idx] += TSXXX_BASE_IO; + io[candev->candev_idx] = io_addr; + } - DEBUGMSG("Memory region at 0x%lx assigned to sja1000 of driver %d/%s\n", - canio[candev->candev_idx], candev->candev_idx, candev->hwname); + candev->io_addr = rebased_pld_io_addr; + /* unused reset address is used to store jumper setting */ + candev->res_addr = jmp; - candev->res_addr=RESET_ADDR; candev->nr_82527_chips=NR_82527; candev->nr_sja1000_chips=NR_SJA1000; candev->nr_all_chips=NR_82527+NR_SJA1000; candev->flags &= ~CANDEV_PROGRAMMABLE_IRQ; + DEBUGMSG("Memory region at 0x%lx assigned to sja1000 of driver %d/%s\n", + candev->io_addr, candev->candev_idx, candev->hwname); + return 0; } + /** * tscan1_init_chip_data - Initialize chips * @candev: Pointer to candevice/board structure @@ -313,14 +385,37 @@ int tscan1_init_hw_data(struct candevice_t *candev) */ int tscan1_init_chip_data(struct candevice_t *candev, int chipnr) { + unsigned long default_clk = 16000 * 1000; + int jmp; + int irq = -1; + + /* unused reset address is used to store jumper setting */ + jmp = candev->res_addr; + + if (jmp&0x10 && jmp&0x20) irq=TSXXX_IRQ5; + else if (jmp&0x10) irq=TSXXX_IRQ6; + else if (jmp&0x20) irq=TSXXX_IRQ7; + + if(irq<0) { + CANMSG("Jumpers select no IRQ for TSCAN1 at 0x%lx of driver %d/%s\n", + candev->io_addr, candev->candev_idx, candev->hwname); + return -ENODEV; + } + candev->chip[chipnr]->chip_irq = irq; + sja1000p_fill_chipspecops(candev->chip[chipnr]); - candev->chip[chipnr]->clock = clock[candev->candev_idx]*1000; + if(candev->chip[chipnr]->clock <= 0) + candev->chip[chipnr]->clock = default_clk; candev->chip[chipnr]->int_clk_reg = 0x0; candev->chip[chipnr]->int_bus_reg = 0x0; candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF; - candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH; - candev->chip[chipnr]->chip_base_addr = candev->io_addr; + candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH; + /* + * The address is assigned during tscan1_request_io() + * according to found free ranges or tscanio option + */ + candev->chip[chipnr]->chip_base_addr = (unsigned long)-1; return 0; } @@ -376,19 +471,17 @@ int tscan1_program_irq(struct candevice_t *candev) * Return Value: The function does not return a value * File: src/tscan1.c */ -void tscan1_write_register(unsigned data, unsigned long address) +void tscan1_write_register(unsigned data, can_ioptr_t address) { - signed short nwinbak=-1; - unsigned long winaddr; - address = tscan1_setpage_getaddr(address, &nwinbak, &winaddr); - DEBUGMSG("outb(0x%x,0x%lx)\n", data, address); - outb(data, address); - if (nwinbak!=-1) { - DEBUGMSG("restore win outb(0x%x,0x%lx) \n", nwinbak, winaddr); - outb(nwinbak, winaddr); - } + can_outb(data, address); } +void tscan1mmio_write_register(unsigned data, can_ioptr_t address) +{ + can_writeb(data, address); +} + + /** * tscan1_read_register - Low level read register routine * @address: memory address to read from @@ -399,22 +492,16 @@ void tscan1_write_register(unsigned data, unsigned long address) * Return Value: The function returns the value stored in @address * File: src/tscan1.c */ -unsigned tscan1_read_register(unsigned long address) +unsigned tscan1_read_register(can_ioptr_t address) { - unsigned short data; - signed short nwinbak=-1; - unsigned long winaddr; - address = tscan1_setpage_getaddr(address, &nwinbak, &winaddr); - data = inb(address); - DEBUGMSG("inb(0x%lx) = 0x%x\n", address, data); - if (nwinbak!=-1) { - DEBUGMSG("restore win outb(0x%x,0x%lx) \n", nwinbak, winaddr); - outb(nwinbak, winaddr); - } - return data; + return can_inb(address); +} + +unsigned tscan1mmio_read_register(can_ioptr_t address) +{ + return can_readb(address); } -/* !!! Don't change this function !!! */ int tscan1_register(struct hwspecops_t *hwspecops) { hwspecops->request_io = tscan1_request_io; @@ -429,64 +516,16 @@ int tscan1_register(struct hwspecops_t *hwspecops) return 0; } -unsigned long tscan1_getmappedaddr(unsigned long address) -{ - return (unsigned long)TS7XXX_IO8_BASE + address; -} - -unsigned short tscan1_getcandevidx(unsigned long address) -{ - ///?FIXME Consider addresses beyond 32bytes range - unsigned short i; - for (i=0;i= remap_can_addr[i]) && - (address < remap_can_addr[i]+TSXXX_CAN_RANGE) ) - return i; - return -1; -} - -unsigned long tscan1_setpage_getaddr(unsigned long address, - signed short *nwinbak, unsigned long *winaddr) +int tscan1mmio_register(struct hwspecops_t *hwspecops) { - unsigned long offset_addr; - unsigned short candev_idx; - char nwin; - - if ((candev_idx = tscan1_getcandevidx(address)) < 0) - return address; - - offset_addr = address; - nwin = 0x0; - - if (!strcmp(hardware_p->candevice[candev_idx]->hwname,"tscan1")) { - while ((offset_addr - remap_can_addr[candev_idx]) > 0x1f) { - offset_addr -= 0x20; - nwin += 0x1; - } - DEBUGMSG("%s win outb(0x%x,0x%lx) of address 0x%lx\n", - hardware_p->candevice[candev_idx]->hwname, - nwin, remap_io_addr[candev_idx]|TSCAN1_WIN_REG, address); - outb(nwin, remap_io_addr[candev_idx]|TSCAN1_WIN_REG); - } - - else if (!strcmp(hardware_p->candevice[candev_idx]->hwname,"ts7kv")) { - while ((offset_addr - remap_can_addr[candev_idx]) > 0x1d) { - offset_addr -= 0x10; - nwin += 0x1; - } - - *winaddr = (unsigned long)remap_can_addr[candev_idx]|TS7KV_WIN_REG; - *nwinbak = inb(*winaddr); - DEBUGMSG("inb(0x%lx)=0x%x bak\n", *winaddr, *nwinbak); - if (*nwinbak != (nwin|0x10)) { - DEBUGMSG("%s win outb(0x%x,0x%lx) of address 0x%lx\n", - hardware_p->candevice[candev_idx]->hwname, - nwin|0x10, *winaddr, address); - outb(nwin|0x10, *winaddr); - } - if ( 0x10 == ((*nwinbak)&0xF0) ) *nwinbak = -1; - } - - return offset_addr; + hwspecops->request_io = tscan1_request_io; + hwspecops->release_io = tscan1_release_io; + hwspecops->reset = tscan1_reset; + hwspecops->init_hw_data = tscan1_init_hw_data; + hwspecops->init_chip_data = tscan1_init_chip_data; + hwspecops->init_obj_data = tscan1_init_obj_data; + hwspecops->write_register = tscan1mmio_write_register; + hwspecops->read_register = tscan1mmio_read_register; + hwspecops->program_irq = tscan1_program_irq; + return 0; }