X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/bab3604638338226c816d432a768c23726cd918e..8d06c4e166846c170775c086d1565a0e281d6dbc:/lincan/src/tscan1.c diff --git a/lincan/src/tscan1.c b/lincan/src/tscan1.c index 049fb8d..5f7ca7a 100644 --- a/lincan/src/tscan1.c +++ b/lincan/src/tscan1.c @@ -22,18 +22,30 @@ #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"); +static CAN_DEFINE_SPINLOCK(ts7kv_win_lock); -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"); +unsigned long tscanio[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1}; +unsigned int tscanio_specified; -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}; +#if defined(TS7XXX_IO8_BASE)&&defined(TSXXX_BASE_IO) +int tsxxx_base=TS7XXX_IO8_BASE+TSXXX_BASE_IO; +#elif defined(TS7XXX_IO8_BASE) +int tsxxx_base=TS7XXX_IO8_BASE; +#else /*TS7XXX_IO8_BASE*/ +unsigned long tsxxx_base=0; +#endif /*TS7XXX_IO8_BASE*/ + +#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, int, &tscanio_specified, 0); +module_param(tsxxx_base, ulong, 0); +#endif /* LINUX_VERSION_CODE >= 2,6,12 */ + +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"); -unsigned short isused = 0x0; /** * tscan1_request_io: - reserve io or memory range for can board @@ -51,22 +63,94 @@ 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 remap_can_io_addr = 0; + unsigned char mode; + int i, j; + + + if (!can_request_io_region(candev->io_addr, TSXXX_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+TSXXX_IO_RANGE-1); + } + + can_io_addr = tscanio[candev->candev_idx]; + + if(can_io_addr && (can_io_addr != (unsigned long)-1)) { + remap_can_io_addr = tsxxx_base + can_io_addr; - remap_io_addr[candev->candev_idx] = tscan1_getmappedaddr(candev->io_addr); - remap_can_io_addr = tscan1_getmappedaddr(canio[candev->candev_idx]); + if (!can_request_io_region(remap_can_io_addr, TSXXX_CAN_RANGE, "tscan1-can")) { + CANMSG("Unable to request CAN IO port: 0x%lx\n", remap_can_io_addr); + can_release_io_region(candev->io_addr, TSXXX_IO_RANGE); + return -ENODEV; + } else { + DEBUGMSG("Registered CAN IO port: 0x%lx - 0x%lx\n", + remap_can_io_addr, remap_can_io_addr+TSXXX_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, TSXXX_IO_RANGE); + return -ENODEV; + } + + can_io_addr = 0x100 + i * TSXXX_CAN_RANGE; + for (j = 0; j < MAX_HW_CARDS; j++) { + if(tscanio[j] == can_io_addr) { + j = -1; + break; + } + } + if(j<0) + continue; + + remap_can_io_addr = tsxxx_base + can_io_addr; + + if (can_request_io_region(remap_can_io_addr, TSXXX_CAN_RANGE, "tscan1-can")) + break; + } + + tscanio[candev->candev_idx] = can_io_addr; + + DEBUGMSG("Found free range and registered CAN IO port: 0x%lx - 0x%lx\n", + remap_can_io_addr, remap_can_io_addr+TSXXX_CAN_RANGE-1); + } - 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; + + switch(can_io_addr) { + 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; + } + + can_outb(0x00, candev->io_addr+TSCAN1_WIN_REG); + can_outb(mode, candev->io_addr+TSCAN1_MOD_REG); - remap_can_addr[candev->candev_idx] = remap_can_io_addr; + return 0; +} - 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); +int ts7kv_request_io(struct candevice_t *candev) +{ + if (!can_request_io_region(candev->io_addr, TSXXX_CAN_RANGE, "ts7kv-can")) { + CANMSG("Unable to request CAN IO port: 0x%lx\n", candev->io_addr); + return -ENODEV; + } else { + DEBUGMSG("Registered CAN IO port: 0x%lx - 0x%lx\n", + candev->io_addr, candev->io_addr+TSXXX_CAN_RANGE-1); + } return 0; } @@ -85,6 +169,23 @@ int tscan1_request_io(struct candevice_t *candev) */ int tscan1_release_io(struct candevice_t *candev) { + unsigned long remap_can_io_addr; + + if(candev->chip[0]){ + remap_can_io_addr = candev->chip[0]->chip_base_addr; + if(remap_can_io_addr != (unsigned long)-1) + can_release_io_region(remap_can_io_addr, TSXXX_CAN_RANGE); + } + + can_outb(0x20, candev->io_addr+TSCAN1_MOD_REG); + + can_release_io_region(candev->io_addr, TSXXX_IO_RANGE); + return 0; +} + +int ts7kv_release_io(struct candevice_t *candev) +{ + can_release_io_region(candev->io_addr, TSXXX_CAN_RANGE); return 0; } @@ -107,19 +208,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 +230,33 @@ int tscan1_reset(struct candevice_t *candev) #define NR_82527 0 #define NR_SJA1000 1 +int tscan1_check_presence(unsigned long remap_io_addr, int *pjmp) +{ + int result = -ENODEV; + + if (!can_request_io_region(remap_io_addr, TSXXX_IO_RANGE, "tscan1-probe")) + return -ENODEV; + + do { + if (can_inb(remap_io_addr+TSXXX_ID0_REG)!=TSCAN1_ID0 || + can_inb(remap_io_addr+TSXXX_ID1_REG)!=TSCAN1_ID1) + break; + + can_outb(0x00, remap_io_addr+TSCAN1_WIN_REG); + can_outb(0x20, remap_io_addr+TSCAN1_MOD_REG); + + if(pjmp) + *pjmp = can_inb(remap_io_addr+TSCAN1_JMP_REG); + + result = 0; + } while (0); + + can_release_io_region(remap_io_addr, TSXXX_IO_RANGE); + + return result; +} + + /** * tscan1_init_hw_data - Initialize hardware cards * @candev: Pointer to candevice/board structure @@ -146,139 +274,160 @@ 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 remap_io_addr; + + io_addr = candev->io_addr; - candev->io_addr = -1; - if (!strcmp(hw[candev->candev_idx],"tscan1")) - { + if(io_addr && (io_addr != (unsigned long)-1)) { + remap_io_addr = io_addr + tsxxx_base; + + if(tscan1_check_presence(remap_io_addr, &jmp)){ + CANMSG("No TSCAN1 card found at address 0x%lx\n", + remap_io_addr); + return -ENODEV; + } + } else { DEBUGMSG("Scanning bus for TS-CAN1 boards...\n"); - for (i=0;i<4;i++) + + for (i=0; 1;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<= 4) { + CANMSG("No TS-CAN1 boards found for slot %d\n", candev->candev_idx); + return -ENODEV; } - } - } - if (!strcmp(hw[candev->candev_idx],"ts7kv")) - { - DEBUGMSG("Scanning bus for TS-7KV boards...\n"); - for (i=4;i<8;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<candev_idx); - if (candev->io_addr==-1) { - DEBUGMSG("No board was found for driver %d/%s.\n", candev->candev_idx, candev->hwname); - return -1; + io[candev->candev_idx] = io_addr; } - 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; + candev->io_addr = remap_io_addr; + /* unused reset address is used to store jumper setting */ + candev->res_addr = jmp; + + 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; +} + + +int ts7kv_check_presence(unsigned long remap_io_addr, int *pjmp) +{ + int result = -ENODEV; + + if (!can_request_io_region(remap_io_addr, TSXXX_IO_RANGE, "ts7kv-probe")) + return -ENODEV; + + do { + if (can_inb(remap_io_addr+TSXXX_ID0_REG)!=TS7KV_ID0 || + can_inb(remap_io_addr+TSXXX_ID1_REG)!=TS7KV_ID1) + break; + + if(pjmp) + *pjmp = can_inb(remap_io_addr+TS7KV_JMP_REG); + + result = 0; + } while (0); + + can_release_io_region(remap_io_addr, TSXXX_IO_RANGE); + + return result; +} + +int ts7kv_init_hw_data(struct candevice_t *candev) +{ + int i, j, jmp; + unsigned long io_addr; + unsigned long remap_io_addr; + unsigned long can_io_addr; + + io_addr = candev->io_addr; + + if(io_addr && (io_addr != (unsigned long)-1)) { + remap_io_addr = io_addr + tsxxx_base; + + if(ts7kv_check_presence(remap_io_addr, &jmp)){ + CANMSG("No TS7KV card found at address 0x%lx\n", + remap_io_addr); + return -ENODEV; } - if (canio[candev->candev_idx] == -1) + } else { + DEBUGMSG("Scanning bus for TS7KV boards...\n"); + + for (i=0; 1;i++) { - 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; + if(i >= 4) { + CANMSG("No TS7KV boards found for slot %d\n", candev->candev_idx); + return -ENODEV; } - } - //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); - } + io_addr = TS7KV_BASE_IO + i*TSXXX_IO_RANGE; + remap_io_addr = io_addr + tsxxx_base; + + for (j = 0; j < MAX_HW_CARDS; j++) { + if(io[j] == io_addr){ + j = -1; + break; + } + } + if(j<0) + continue; + + if(!ts7kv_check_presence(remap_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("TS7KV board was found at 0x%lx for driver slot %d\n", + io_addr, candev->candev_idx); + + io[candev->candev_idx] = io_addr; } - if (baudrate[candev->candev_idx] == -1) - baudrate[candev->candev_idx] = 1000; + can_io_addr = ((io_addr>>3)&0x03)*0x20; + tscanio[candev->candev_idx] = can_io_addr; - io[candev->candev_idx] += TSXXX_BASE_IO; - candev->io_addr = io[candev->candev_idx]; - canio[candev->candev_idx] += TSXXX_BASE_IO; + /* dev_base_addr address is used to store remapped PLD base address */ + candev->dev_base_addr = remap_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); + /* dev_base_addr address is used to store remapped slave window address */ + candev->io_addr = can_io_addr+tsxxx_base; + + /* 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; } @@ -313,13 +462,70 @@ 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]->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; +} + +int ts7kv_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 TS7KV CAN 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]); + + 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; return 0; @@ -376,17 +582,35 @@ 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 ts7kv_write_register(unsigned data, can_ioptr_t address) +{ + unsigned long addr=can_ioptr2ulong(address); + can_ioptr_t base = can_ulong2ioptr(addr & ~0x1f); + unsigned char nwin = 0x10; + unsigned char savewin; + + can_spin_irqflags_t flags; + + if((addr&0x1f) > 0x1d) { + nwin++; + address -= 0x10; + } + + can_spin_lock_irqsave(&ts7kv_win_lock,flags); + savewin = can_inb(base+TS7KV_WIN_REG); + if(nwin == savewin) { + can_outb(data, address); + }else{ + can_outb(nwin, base+TS7KV_WIN_REG); + can_outb(data, address); + can_outb(savewin, base+TS7KV_WIN_REG); } + can_spin_unlock_irqrestore(&ts7kv_win_lock,flags); } /** @@ -399,22 +623,40 @@ 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 can_inb(address); +} + +unsigned ts7kv_read_register(can_ioptr_t address) +{ + unsigned long addr=can_ioptr2ulong(address); + can_ioptr_t base = can_ulong2ioptr(addr & ~0x1f); + unsigned char nwin = 0x10; + unsigned char savewin; + unsigned val; + + can_spin_irqflags_t flags; + + if((addr&0x1f) > 0x1d) { + nwin++; + address -= 0x10; + } + + can_spin_lock_irqsave(&ts7kv_win_lock,flags); + savewin = can_inb(base+TS7KV_WIN_REG); + if(nwin == savewin) { + val = can_inb(address); + }else{ + can_outb(nwin, base+TS7KV_WIN_REG); + val = can_inb(address); + can_outb(savewin, base+TS7KV_WIN_REG); } - return data; + can_spin_unlock_irqrestore(&ts7kv_win_lock,flags); + + return val; } -/* !!! Don't change this function !!! */ int tscan1_register(struct hwspecops_t *hwspecops) { hwspecops->request_io = tscan1_request_io; @@ -429,64 +671,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) +extern int ts7kv_register(struct hwspecops_t *hwspecops) { - ///?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) -{ - 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 = ts7kv_request_io; + hwspecops->release_io = ts7kv_release_io; + hwspecops->reset = tscan1_reset; + hwspecops->init_hw_data = ts7kv_init_hw_data; + hwspecops->init_chip_data = ts7kv_init_chip_data; + hwspecops->init_obj_data = tscan1_init_obj_data; + hwspecops->write_register = ts7kv_write_register; + hwspecops->read_register = ts7kv_read_register; + hwspecops->program_irq = tscan1_program_irq; + return 0; }