diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
commit | 6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch) | |
tree | 0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /drivers/ieee1394/pcilynx.c | |
parent | ecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff) |
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine
status unknown.
Diffstat (limited to 'drivers/ieee1394/pcilynx.c')
-rw-r--r-- | drivers/ieee1394/pcilynx.c | 286 |
1 files changed, 132 insertions, 154 deletions
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index 773d68983..368c5137b 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -99,6 +99,8 @@ static pcl_t alloc_pcl(struct ti_lynx *lynx) return -1; } + +#if 0 static void free_pcl(struct ti_lynx *lynx, pcl_t pclid) { int off, bit; @@ -145,6 +147,7 @@ static void print_pcl(const struct ti_lynx *lynx, pcl_t pclid) get_pcl(lynx, pclid, &pcl); pretty_print_pcl(&pcl); } +#endif static int add_card(struct pci_dev *dev); @@ -486,7 +489,8 @@ static int lynx_initialize(struct hpsb_host *host) put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl); /* 85 bytes for each FIFO - FIXME - optimize or make configurable */ - reg_write(lynx, FIFO_SIZES, 0x00555555); + /* reg_write(lynx, FIFO_SIZES, 0x00555555); */ + reg_write(lynx, FIFO_SIZES, 0x002020c0); /* 20 byte threshold before triggering PCI transfer */ reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24); /* 69 byte threshold on both send FIFOs before transmitting */ @@ -597,15 +601,16 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) } else { arg = 1 << 6; } - + + retval = get_phy_reg(lynx, 1); + arg |= (retval == -1 ? 63 : retval); + retval = 0; + PRINT(KERN_INFO, lynx->id, "resetting bus on request%s", (host->attempt_root ? " and attempting to become root" : "")); - spin_lock_irqsave(&lynx->phy_reg_lock, flags); - reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(1) - | LINK_PHY_WDATA(arg)); - spin_unlock_irqrestore(&lynx->phy_reg_lock, flags); + set_phy_reg(lynx, 1, arg); break; case GET_CYCLE_COUNTER: @@ -705,6 +710,7 @@ static ssize_t mem_write(struct file*, const char*, size_t, loff_t*); static struct file_operations aux_ops = { + owner: THIS_MODULE, /* FIXME: should have custom llseek with bounds checking */ read: mem_read, write: mem_write, @@ -717,61 +723,10 @@ static struct file_operations aux_ops = { static void aux_setup_pcls(struct ti_lynx *lynx) { struct ti_pcl pcl; - unsigned long membufbus = virt_to_bus(lynx->mem_dma_buffer); - int i; - /* This pcl is used to start any aux transfers, the pointer to next - points to itself to avoid a dummy pcl (the PCL engine only executes - the next pcl on startup. The real chain is done by branch */ - pcl.next = pcl_bus(lynx, lynx->mem_pcl.start); - pcl.buffer[0].control = PCL_CMD_BRANCH | PCL_COND_DMARDY_SET; - pcl.buffer[0].pointer = pcl_bus(lynx, lynx->mem_pcl.max); - pcl.buffer[1].control = PCL_CMD_BRANCH | PCL_COND_DMARDY_CLEAR; - pcl.buffer[1].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd); - put_pcl(lynx, lynx->mem_pcl.start, &pcl); - - /* let maxpcl transfer exactly 32kB */ pcl.next = PCL_NEXT_INVALID; - for (i=0; i<8; i++) { - pcl.buffer[i].control = 4000; - pcl.buffer[i].pointer = membufbus + i * 4000; - } - pcl.buffer[0].control |= PCL_CMD_LBUS_TO_PCI /*| PCL_GEN_INTR*/; - pcl.buffer[8].control = 768 | PCL_LAST_BUFF; - pcl.buffer[8].pointer = membufbus + 8 * 4000; - put_pcl(lynx, lynx->mem_pcl.max, &pcl); - - - /* magic stuff - self and modpcl modifying pcl */ - pcl.next = pcl_bus(lynx, lynx->mem_pcl.mod); - pcl.user_data = 4000; - pcl.buffer[0].control = PCL_CMD_LOAD; - pcl.buffer[0].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) - + pcloffs(user_data); - pcl.buffer[1].control = PCL_CMD_STOREQ; - pcl.buffer[1].pointer = pcl_bus(lynx, lynx->mem_pcl.mod) - + pcloffs(buffer[1].control); - pcl.buffer[2].control = PCL_CMD_LOAD; - pcl.buffer[2].pointer = membufbus; - pcl.buffer[3].control = PCL_CMD_STOREQ; - pcl.buffer[3].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) - + pcloffs(buffer[1].pointer); - pcl.buffer[4].control = PCL_CMD_STOREQ; - pcl.buffer[4].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) - + pcloffs(buffer[6].pointer); - pcl.buffer[5].control = PCL_CMD_LOAD; - pcl.buffer[5].pointer = membufbus + 4; - pcl.buffer[6].control = PCL_CMD_STOREQ | PCL_LAST_CMD; - put_pcl(lynx, lynx->mem_pcl.cmd, &pcl); - - /* modified by cmdpcl when actual transfer occurs */ - pcl.next = PCL_NEXT_INVALID; - pcl.buffer[0].control = PCL_CMD_LBUS_TO_PCI; /* null transfer */ - for (i=1; i<13; i++) { - pcl.buffer[i].control = 4000; - pcl.buffer[i].pointer = membufbus + (i-1) * 4000; - } - put_pcl(lynx, lynx->mem_pcl.mod, &pcl); + pcl.user_data = pcl_bus(lynx, lynx->dmem_pcl); + put_pcl(lynx, lynx->dmem_pcl, &pcl); } static int mem_open(struct inode *inode, struct file *file) @@ -779,24 +734,19 @@ static int mem_open(struct inode *inode, struct file *file) int cid = MINOR(inode->i_rdev); enum { rom, aux, ram } type; struct memdata *md; - - MOD_INC_USE_COUNT; if (cid < PCILYNX_MINOR_AUX_START) { /* just for completeness */ - MOD_DEC_USE_COUNT; return -ENXIO; } else if (cid < PCILYNX_MINOR_ROM_START) { cid -= PCILYNX_MINOR_AUX_START; if (cid >= num_of_cards || !cards[cid].aux_port) { - MOD_DEC_USE_COUNT; return -ENXIO; } type = aux; } else if (cid < PCILYNX_MINOR_RAM_START) { cid -= PCILYNX_MINOR_ROM_START; if (cid >= num_of_cards || !cards[cid].local_rom) { - MOD_DEC_USE_COUNT; return -ENXIO; } type = rom; @@ -805,7 +755,6 @@ static int mem_open(struct inode *inode, struct file *file) * It is currently used inside the driver! */ cid -= PCILYNX_MINOR_RAM_START; if (cid >= num_of_cards || !cards[cid].local_ram) { - MOD_DEC_USE_COUNT; return -ENXIO; } type = ram; @@ -813,7 +762,6 @@ static int mem_open(struct inode *inode, struct file *file) md = (struct memdata *)vmalloc(sizeof(struct memdata)); if (md == NULL) { - MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -828,7 +776,8 @@ static int mem_open(struct inode *inode, struct file *file) md->type = ram; break; case aux: - md->aux_intr_last_seen = atomic_read(&cards[cid].aux_intr_seen); + atomic_set(&md->aux_intr_last_seen, + atomic_read(&cards[cid].aux_intr_seen)); md->type = aux; break; } @@ -844,7 +793,6 @@ static int mem_release(struct inode *inode, struct file *file) vfree(md); - MOD_DEC_USE_COUNT; return 0; } @@ -862,11 +810,9 @@ static unsigned int aux_poll(struct file *file, poll_table *pt) poll_wait(file, &cards[cid].aux_intr_wait, pt); intr_seen = atomic_read(&cards[cid].aux_intr_seen); - if (md->aux_intr_last_seen != intr_seen) { + if (atomic_read(&md->aux_intr_last_seen) != intr_seen) { mask |= POLLPRI; - /* md->aux_intr_last_seen = intr_seen; */ - md->aux_intr_last_seen++; /* don't miss interrupts */ - /* FIXME - make ioctl for configuring this */ + atomic_inc(&md->aux_intr_last_seen); } } @@ -882,38 +828,104 @@ static unsigned int aux_poll(struct file *file, poll_table *pt) short mem_mindma = 2400; MODULE_PARM(mem_mindma, "h"); +static ssize_t mem_dmaread(struct memdata *md, u32 physbuf, ssize_t count, + int offset) +{ + pcltmp_t pcltmp; + struct ti_pcl *pcl; + size_t retval; + int i; + DECLARE_WAITQUEUE(wait, current); + + //printk("buf 0x%08x %x count %d offset %d\n", physbuf, physbuf % 3, count, offset); + + count &= ~3; + count = MIN(count, 53196); + retval = count; + + if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS)) + & DMA_CHAN_CTRL_BUSY) { + PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!"); + } + + switch (md->type) { + case rom: + reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_ROM | offset); + break; + case ram: + reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_RAM | offset); + break; + case aux: + reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_AUX | offset); + break; + } + + pcl = edit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp); + pcl->buffer[0].control = PCL_CMD_LBUS_TO_PCI | MIN(count, 4092); + pcl->buffer[0].pointer = physbuf; + count -= 4092; + + i = 0; + while (count > 0) { + i++; + pcl->buffer[i].control = MIN(count, 4092); + pcl->buffer[i].pointer = physbuf + i * 4092; + count -= 4092; + } + pcl->buffer[i].control |= PCL_LAST_BUFF; + commit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); + run_sub_pcl(md->lynx, md->lynx->dmem_pcl, 2, CHANNEL_LOCALBUS); + + schedule(); + while (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS)) + & DMA_CHAN_CTRL_BUSY) { + if (signal_pending(current)) { + retval = -EINTR; + break; + } + schedule(); + } + + reg_write(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS), 0); + remove_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); + + if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS)) + & DMA_CHAN_CTRL_BUSY) { + PRINT(KERN_ERR, md->lynx->id, "DMA STILL ACTIVE!"); + } + + return retval; +} + static ssize_t mem_read(struct file *file, char *buffer, size_t count, loff_t *offset) { struct memdata *md = (struct memdata *)file->private_data; - size_t bcount; + ssize_t bcount; size_t alignfix; int off = (int)*offset; /* avoid useless 64bit-arithmetic */ + ssize_t retval; void *membase; - DECLARE_WAITQUEUE(wait, current); - - if ((off + count) > PCILYNX_MAX_MEMORY+1) { - count = PCILYNX_MAX_MEMORY+1 - off; + if ((off + count) > PCILYNX_MAX_MEMORY + 1) { + count = PCILYNX_MAX_MEMORY + 1 - off; } if (count <= 0) { return 0; } - down(&md->lynx->mem_dma_mutex); - switch (md->type) { case rom: - reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_ROM | off); membase = md->lynx->local_rom; break; case ram: - reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_RAM | off); membase = md->lynx->local_ram; break; case aux: - reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_AUX | off); membase = md->lynx->aux_port; break; default: @@ -921,89 +933,49 @@ static ssize_t mem_read(struct file *file, char *buffer, size_t count, md->lynx->id, md->type); } + down(&md->lynx->mem_dma_mutex); + if (count < mem_mindma) { memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, count); - copy_to_user(buffer, md->lynx->mem_dma_buffer, count); - bcount = 0; - goto done; + goto out; } - + bcount = count; alignfix = 4 - (off % 4); if (alignfix != 4) { if (bcount < alignfix) { alignfix = bcount; } - memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, alignfix); - copy_to_user(buffer, md->lynx->mem_dma_buffer, alignfix); + memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, + alignfix); if (bcount == alignfix) { - goto done; + goto out; } bcount -= alignfix; - buffer += alignfix; off += alignfix; } - if (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) { - PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!"); - } - - add_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); - - if (bcount > 32768) { - current->state = TASK_INTERRUPTIBLE; + while (bcount >= 4) { + retval = mem_dmaread(md, virt_to_phys(md->lynx->mem_dma_buffer) + + count - bcount, bcount, off); + if (retval < 0) return retval; - reg_write(md->lynx, DMA0_READY, 1); /* select maxpcl */ - run_pcl(md->lynx, md->lynx->mem_pcl.start, 0); - - while (reg_read(md->lynx, DMA0_CHAN_CTRL) - & DMA_CHAN_CTRL_BUSY) { - if (signal_pending(current)) { - reg_write(md->lynx, DMA0_CHAN_CTRL, 0); - goto rmwait_done; - } - schedule(); - } - - copy_to_user(buffer, md->lynx->mem_dma_buffer, 32768); - buffer += 32768; - bcount -= 32768; - } - - *(u32 *)(md->lynx->mem_dma_buffer) = - pcl_bus(md->lynx, md->lynx->mem_pcl.mod) - + pcloffs(buffer[bcount/4000+1].control); - *(u32 *)(md->lynx->mem_dma_buffer+4) = PCL_LAST_BUFF | (bcount % 4000); - - current->state = TASK_INTERRUPTIBLE; - - reg_write(md->lynx, DMA0_READY, 0); - run_pcl(md->lynx, md->lynx->mem_pcl.start, 0); - - while (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) { - if (signal_pending(current)) { - reg_write(md->lynx, DMA0_CHAN_CTRL, 0); - goto rmwait_done; - } - schedule(); + bcount -= retval; + off += retval; } - copy_to_user(buffer, md->lynx->mem_dma_buffer, bcount); - bcount = 0; - - if (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) { - PRINT(KERN_ERR, md->lynx->id, "DMA STILL ACTIVE!"); + if (bcount) { + memcpy_fromio(md->lynx->mem_dma_buffer + count - bcount, + membase+off, bcount); } - rmwait_done: - reg_write(md->lynx, DMA0_CHAN_CTRL, 0); - remove_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); - done: + out: + retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count); up(&md->lynx->mem_dma_mutex); - count -= bcount; + if (retval < 0) return retval; *offset += count; - return (count ? count : -EINTR); + return count; } @@ -1200,6 +1172,12 @@ static void iso_rcv_bh(struct ti_lynx *lynx) data = lynx->iso_rcv.page[idx / ISORCV_PER_PAGE] + (idx % ISORCV_PER_PAGE) * MAX_ISORCV_SIZE; + if ((*data >> 16) + 4 != (lynx->iso_rcv.stat[idx] & 0x1fff)) { + PRINT(KERN_ERR, lynx->id, + "iso length mismatch 0x%08x/0x%08x", *data, + lynx->iso_rcv.stat[idx]); + } + if (lynx->iso_rcv.stat[idx] & (DMA_CHAN_STAT_PCIERR | DMA_CHAN_STAT_PKTERR)) { PRINT(KERN_INFO, lynx->id, @@ -1224,11 +1202,12 @@ static void iso_rcv_bh(struct ti_lynx *lynx) static int add_card(struct pci_dev *dev) { -#define FAIL(fmt, args...) \ +#define FAIL(fmt, args...) do { \ PRINT_G(KERN_ERR, fmt , ## args); \ num_of_cards--; \ remove_card(lynx); \ - return 1 + return 1; \ + } while (0) struct ti_lynx *lynx; /* shortcut to currently handled device */ unsigned long page; @@ -1246,6 +1225,9 @@ static int add_card(struct pci_dev *dev) lynx->id = num_of_cards-1; lynx->dev = dev; + if (pci_enable_device(dev)) { + FAIL("failed to enable PCILynx hardware %d", lynx->id); + } pci_set_master(dev); if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ, @@ -1271,7 +1253,7 @@ static int add_card(struct pci_dev *dev) } #endif - lynx->mem_dma_buffer = kmalloc(32768, GFP_KERNEL); + lynx->mem_dma_buffer = kmalloc(65536, GFP_KERNEL); if (lynx->mem_dma_buffer != NULL) { lynx->state = have_aux_buf; } else { @@ -1301,15 +1283,15 @@ static int add_card(struct pci_dev *dev) lynx->local_ram = ioremap(dev->base_address[1], PCILYNX_MAX_MEMORY); lynx->aux_port = ioremap(dev->base_address[2], PCILYNX_MAX_MEMORY); #else - lynx->registers = ioremap_nocache(dev->resource[0].start, + lynx->registers = ioremap_nocache(pci_resource_start(dev,0), PCILYNX_MAX_REGISTER); - lynx->local_ram = ioremap(dev->resource[1].start, PCILYNX_MAX_MEMORY); - lynx->aux_port = ioremap(dev->resource[2].start, PCILYNX_MAX_MEMORY); + lynx->local_ram = ioremap(pci_resource_start(dev,1), PCILYNX_MAX_MEMORY); + lynx->aux_port = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,15) lynx->local_rom = ioremap(dev->rom_address, PCILYNX_MAX_MEMORY); #else - lynx->local_rom = ioremap(dev->resource[PCI_ROM_RESOURCE].start, + lynx->local_rom = ioremap(pci_resource_start(dev,PCI_ROM_RESOURCE), PCILYNX_MAX_MEMORY); #endif lynx->state = have_iomappings; @@ -1328,12 +1310,8 @@ static int add_card(struct pci_dev *dev) /* alloc_pcl return values are not checked, it is expected that the * provided PCL space is sufficient for the initial allocations */ if (lynx->aux_port != NULL) { - lynx->mem_pcl.start = alloc_pcl(lynx); - lynx->mem_pcl.cmd = alloc_pcl(lynx); - lynx->mem_pcl.mod = alloc_pcl(lynx); - lynx->mem_pcl.max = alloc_pcl(lynx); + lynx->dmem_pcl = alloc_pcl(lynx); aux_setup_pcls(lynx); - sema_init(&lynx->mem_dma_mutex, 1); } lynx->rcv_pcl = alloc_pcl(lynx); |