📄 ohci1394.c
字号:
== 0x11) ? 1 : 0; hpsb_packet_received(ohci->host, buf_ptr, length, ack); } else PRINT(KERN_INFO, ohci->id, "Got phy packet ctx=%d ... discarded", d->ctx); offset += length; buf_ptr += length/4; if (offset==d->buf_size) { insert_dma_buffer(d, idx); idx = (idx+1) % d->num_desc; buf_ptr = d->buf_cpu[idx]; offset=0; } } rescount = d->prg_cpu[idx]->status & 0xffff; bytes_left = d->buf_size - rescount - offset; } d->buf_ind = idx; d->buf_offset = offset; spin_unlock(&d->lock);}/* Bottom half that processes sent packets */static void dma_trm_bh(void *data){ struct dma_trm_ctx *d = (struct dma_trm_ctx*)data; struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); struct hpsb_packet *packet, *nextpacket; unsigned long flags; u32 ack; size_t datasize; spin_lock_irqsave(&d->lock, flags); if (d->fifo_first==NULL) {#if 0 ohci1394_stop_context(ohci, d->ctrlClear, "Packet sent ack received but queue is empty");#endif spin_unlock_irqrestore(&d->lock, flags); return; } while (d->fifo_first) { packet = d->fifo_first; datasize = d->fifo_first->data_size; if (datasize) ack = d->prg_cpu[d->sent_ind]->end.status>>16; else ack = d->prg_cpu[d->sent_ind]->begin.status>>16; if (ack==0) /* this packet hasn't been sent yet*/ break;#ifdef OHCI1394_DEBUG if (datasize) DBGMSG(ohci->id, "Packet sent to node %d tcode=0x%X tLabel=" "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d", (d->prg_cpu[d->sent_ind]->data[1]>>16)&0x3f, (d->prg_cpu[d->sent_ind]->data[0]>>4)&0xf, (d->prg_cpu[d->sent_ind]->data[0]>>10)&0x3f, ack&0x1f, (ack>>5)&0x3, d->prg_cpu[d->sent_ind]->data[3]>>16, d->ctx); else DBGMSG(ohci->id, "Packet sent to node %d tcode=0x%X tLabel=" "0x%02X ack=0x%X spd=%d data=0x%08X ctx=%d", (d->prg_cpu[d->sent_ind]->data[1]>>16)&0x3f, (d->prg_cpu[d->sent_ind]->data[0]>>4)&0xf, (d->prg_cpu[d->sent_ind]->data[0]>>10)&0x3f, ack&0x1f, (ack>>5)&0x3, d->prg_cpu[d->sent_ind]->data[3], d->ctx);#endif nextpacket = packet->xnext; hpsb_packet_sent(ohci->host, packet, ack&0xf); if (datasize) pci_unmap_single(ohci->dev, d->prg_cpu[d->sent_ind]->end.address, datasize, PCI_DMA_TODEVICE); d->sent_ind = (d->sent_ind+1)%d->num_desc; d->free_prgs++; d->fifo_first = nextpacket; } if (d->fifo_first==NULL) d->fifo_last=NULL; dma_trm_flush(ohci, d); spin_unlock_irqrestore(&d->lock, flags);}static int free_dma_rcv_ctx(struct dma_rcv_ctx **d){ int i; struct ti_ohci *ohci; if (*d==NULL) return -1; ohci = (struct ti_ohci *)(*d)->ohci; DBGMSG(ohci->id, "Freeing dma_rcv_ctx %d",(*d)->ctx); ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL); if ((*d)->buf_cpu) { for (i=0; i<(*d)->num_desc; i++) if ((*d)->buf_cpu[i] && (*d)->buf_bus[i]) pci_free_consistent( ohci->dev, (*d)->buf_size, (*d)->buf_cpu[i], (*d)->buf_bus[i]); kfree((*d)->buf_cpu); kfree((*d)->buf_bus); } if ((*d)->prg_cpu) { for (i=0; i<(*d)->num_desc; i++) if ((*d)->prg_cpu[i] && (*d)->prg_bus[i]) pci_free_consistent( ohci->dev, sizeof(struct dma_cmd), (*d)->prg_cpu[i], (*d)->prg_bus[i]); kfree((*d)->prg_cpu); kfree((*d)->prg_bus); } if ((*d)->spb) kfree((*d)->spb); kfree(*d); *d = NULL; return 0;}static struct dma_rcv_ctx *alloc_dma_rcv_ctx(struct ti_ohci *ohci, int ctx, int num_desc, int buf_size, int split_buf_size, int ctrlSet, int ctrlClear, int cmdPtr){ struct dma_rcv_ctx *d=NULL; int i; d = (struct dma_rcv_ctx *)kmalloc(sizeof(struct dma_rcv_ctx), GFP_KERNEL); if (d==NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma_rcv_ctx"); return NULL; } d->ohci = (void *)ohci; d->ctx = ctx; d->num_desc = num_desc; d->buf_size = buf_size; d->split_buf_size = split_buf_size; d->ctrlSet = ctrlSet; d->ctrlClear = ctrlClear; d->cmdPtr = cmdPtr; d->buf_cpu = NULL; d->buf_bus = NULL; d->prg_cpu = NULL; d->prg_bus = NULL; d->spb = NULL; d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); if (d->buf_cpu == NULL || d->buf_bus == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer"); free_dma_rcv_ctx(&d); return NULL; } memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*)); memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t)); d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*), GFP_KERNEL); d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); if (d->prg_cpu == NULL || d->prg_bus == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg"); free_dma_rcv_ctx(&d); return NULL; } memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*)); memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t)); d->spb = kmalloc(d->split_buf_size, GFP_KERNEL); if (d->spb == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate split buffer"); free_dma_rcv_ctx(&d); return NULL; } for (i=0; i<d->num_desc; i++) { d->buf_cpu[i] = pci_alloc_consistent(ohci->dev, d->buf_size, d->buf_bus+i); if (d->buf_cpu[i] != NULL) { memset(d->buf_cpu[i], 0, d->buf_size); } else { PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer"); free_dma_rcv_ctx(&d); return NULL; } d->prg_cpu[i] = pci_alloc_consistent(ohci->dev, sizeof(struct dma_cmd), d->prg_bus+i); if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd)); } else { PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg"); free_dma_rcv_ctx(&d); return NULL; } } spin_lock_init(&d->lock); /* initialize bottom handler */ d->task.sync = 0; INIT_LIST_HEAD(&d->task.list); d->task.routine = dma_rcv_bh; d->task.data = (void*)d; return d;}static int free_dma_trm_ctx(struct dma_trm_ctx **d){ struct ti_ohci *ohci; int i; if (*d==NULL) return -1; ohci = (struct ti_ohci *)(*d)->ohci; DBGMSG(ohci->id, "Freeing dma_trm_ctx %d",(*d)->ctx); ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL); if ((*d)->prg_cpu) { for (i=0; i<(*d)->num_desc; i++) if ((*d)->prg_cpu[i] && (*d)->prg_bus[i]) pci_free_consistent( ohci->dev, sizeof(struct at_dma_prg), (*d)->prg_cpu[i], (*d)->prg_bus[i]); kfree((*d)->prg_cpu); kfree((*d)->prg_bus); } kfree(*d); *d = NULL; return 0;}static struct dma_trm_ctx *alloc_dma_trm_ctx(struct ti_ohci *ohci, int ctx, int num_desc, int ctrlSet, int ctrlClear, int cmdPtr){ struct dma_trm_ctx *d=NULL; int i; d = (struct dma_trm_ctx *)kmalloc(sizeof(struct dma_trm_ctx), GFP_KERNEL); if (d==NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma_trm_ctx"); return NULL; } d->ohci = (void *)ohci; d->ctx = ctx; d->num_desc = num_desc; d->ctrlSet = ctrlSet; d->ctrlClear = ctrlClear; d->cmdPtr = cmdPtr; d->prg_cpu = NULL; d->prg_bus = NULL; d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*), GFP_KERNEL); d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); if (d->prg_cpu == NULL || d->prg_bus == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate at dma prg"); free_dma_trm_ctx(&d); return NULL; } memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*)); memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t)); for (i=0; i<d->num_desc; i++) { d->prg_cpu[i] = pci_alloc_consistent(ohci->dev, sizeof(struct at_dma_prg), d->prg_bus+i); if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg)); } else { PRINT(KERN_ERR, ohci->id, "failed to allocate at dma prg"); free_dma_trm_ctx(&d); return NULL; } } spin_lock_init(&d->lock); /* initialize bottom handler */ d->task.routine = dma_trm_bh; d->task.data = (void*)d; return d;}static u32 ohci_crc16(unsigned *data, int length){ int check=0, i; int shift, sum, next=0; for (i = length; i; i--) { for (next = check, shift = 28; shift >= 0; shift -= 4 ) { sum = ((next >> 12) ^ (*data >> shift)) & 0xf; next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); } check = next & 0xffff; data++; } return check;}static void ohci_init_config_rom(struct ti_ohci *ohci){ int i; ohci_csr_rom[3] = reg_read(ohci, OHCI1394_GUIDHi); ohci_csr_rom[4] = reg_read(ohci, OHCI1394_GUIDLo); ohci_csr_rom[0] = 0x04040000 | ohci_crc16(ohci_csr_rom+1, 4); for (i=0;i<sizeof(ohci_csr_rom)/4;i++) ohci->csr_config_rom_cpu[i] = cpu_to_be32(ohci_csr_rom[i]);}static int add_card(struct pci_dev *dev){ struct ti_ohci *ohci; /* shortcut to currently handled device */ if (num_of_cards == MAX_OHCI1394_CARDS) { PRINT_G(KERN_WARNING, "cannot handle more than %d cards. " "Adjust MAX_OHCI1394_CARDS in ti_ohci1394.h.", MAX_OHCI1394_CARDS); return 1; } if (pci_enable_device(dev)) { PRINT_G(KERN_NOTICE, "failed to enable OHCI hardware %d", num_of_cards); return 1; } pci_set_master(dev); ohci = &cards[num_of_cards++]; ohci->id = num_of_cards-1; ohci->dev = dev; ohci->state = 0; /* csr_config rom allocation */ ohci->csr_config_rom_cpu = pci_alloc_consistent(ohci->dev, sizeof(ohci_csr_rom), &ohci->csr_config_rom_bus); if (ohci->csr_config_rom_cpu == NULL) { FAIL("failed to allocate buffer config rom"); } /* * self-id dma buffer allocation * FIXME: some early chips may need 8KB alignment for the * selfid buffer... if you have problems a temporary fic * is to allocate 8192 bytes instead of 2048 */ ohci->selfid_buf_cpu = pci_alloc_consistent(ohci->dev, 8192, &ohci->selfid_buf_bus); if (ohci->selfid_buf_cpu == NULL) { FAIL("failed to allocate DMA buffer for self-id packets"); } if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff) PRINT(KERN_INFO, ohci->id, "Selfid buffer %p not aligned on " "8Kb boundary... may cause pb on some CXD3222 chip", ohci->selfid_buf_cpu); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) ohci->registers = ioremap_nocache(dev->base_address[0], OHCI1394_REGISTER_SIZE);#else ohci->registers = ioremap_nocache(dev->resource[0].start, OHCI1394_REGISTER_SIZE);#endif if (ohci->registers == NULL) { FAIL("failed to remap registers - card not accessible"); } PRINT(KERN_INFO, ohci->id, "remapped memory spaces reg 0x%p", ohci->registers); ohci->ar_req_context = alloc_dma_rcv_ctx(ohci, 0, AR_REQ_NUM_DESC, AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE, OHCI1394_AsReqRcvContextControlSet, OHCI1394_AsReqRcvContextControlClear, OHCI1394_AsReqRcvCommandPtr); if (ohci->ar_req_context == NULL) { FAIL("failed to allocate AR Req context"); } ohci->ar_resp_context = alloc_dma_rcv_ctx(ohci, 1, AR_RESP_NUM_DESC, AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE, OHCI1394_AsRspRcvContextControlSet, OHCI1394_AsRspRcvContextControlClear, OHCI1394_AsRspRcvCommandPtr); if (ohci->ar_resp_context == NULL) { FAIL("failed to allocate AR Resp context"); } ohci->at_req_context = alloc_dma_trm_ctx(ohci, 0, AT_REQ_NUM_DESC, OHCI1394_AsReqTrContextControlSet, OHCI1394_AsReqTrContextControlClear, OHCI1394_AsReqTrCommandPtr); if (ohci->at_req_context == NULL) { FAIL("failed to allocate AT Req context"); } ohci->at_resp_context = alloc_dma_trm_ctx(ohci, 1, AT_RESP_NUM_DESC, OHCI1394_AsRspTrContextControlSet, OHCI1394_AsRspTrContextControlClear, OHCI1394_AsRspTrCommandPtr); if (ohci->at_resp_context == NULL) { FAIL("failed to allocate AT Resp context");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -