Mercurial > pt1.oyama
comparison driver/pt1_pci.c @ 41:51a006a8d843
imported patch ringbuf-vmalloc
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 28 Apr 2009 17:16:50 +0900 |
parents | 8f30a05cded2 |
children | 07d71b1484a8 |
comparison
equal
deleted
inserted
replaced
40:8f30a05cded2 | 41:51a006a8d843 |
---|---|
70 #define MAX_READ_BLOCK 4 // 1度に読み出す最大DMAバッファ数 | 70 #define MAX_READ_BLOCK 4 // 1度に読み出す最大DMAバッファ数 |
71 #define MAX_PCI_DEVICE 128 // 最大64枚 | 71 #define MAX_PCI_DEVICE 128 // 最大64枚 |
72 #define DMA_SIZE 4096 // DMAバッファサイズ | 72 #define DMA_SIZE 4096 // DMAバッファサイズ |
73 #define DMA_RING_SIZE 128 // RINGサイズ | 73 #define DMA_RING_SIZE 128 // RINGサイズ |
74 #define DMA_RING_MAX 511 // 1RINGにいくつ詰めるか(1023はNGで511まで) | 74 #define DMA_RING_MAX 511 // 1RINGにいくつ詰めるか(1023はNGで511まで) |
75 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) | |
76 #define CHANEL_DMA_SIZE (2*1024*1024) // 地デジ用(16Mbps) | 75 #define CHANEL_DMA_SIZE (2*1024*1024) // 地デジ用(16Mbps) |
77 #define BS_CHANEL_DMA_SIZE (4*1024*1024) // BS用(32Mbps) | 76 #define BS_CHANEL_DMA_SIZE (4*1024*1024) // BS用(32Mbps) |
78 #else | |
79 #define CHANEL_DMA_SIZE (1*128*1024) // 地デジ用(1Mbps) | |
80 #define BS_CHANEL_DMA_SIZE (1*128*1024) // BS用(1Mbps) | |
81 #endif | |
82 | 77 |
83 typedef struct _DMA_CONTROL{ | 78 typedef struct _DMA_CONTROL{ |
84 dma_addr_t ring_dma[DMA_RING_MAX] ; // DMA情報 | 79 dma_addr_t ring_dma[DMA_RING_MAX] ; // DMA情報 |
85 __u32 *data[DMA_RING_MAX]; | 80 __u32 *data[DMA_RING_MAX]; |
86 }DMA_CONTROL; | 81 }DMA_CONTROL; |
123 __u32 overflow ; // オーバーフローエラー発生 | 118 __u32 overflow ; // オーバーフローエラー発生 |
124 __u32 counetererr ; // 転送カウンタ1エラー | 119 __u32 counetererr ; // 転送カウンタ1エラー |
125 __u32 transerr ; // 転送エラー | 120 __u32 transerr ; // 転送エラー |
126 __u32 minor ; // マイナー番号 | 121 __u32 minor ; // マイナー番号 |
127 __u8 *buf; // CH別受信メモリ | 122 __u8 *buf; // CH別受信メモリ |
123 __u32 pointer; | |
128 __u8 req_dma ; // 溢れたチャネル | 124 __u8 req_dma ; // 溢れたチャネル |
129 __u8 packet_buf[PACKET_SIZE] ; // 溢れたチャネル | 125 __u8 packet_buf[PACKET_SIZE] ; // 溢れたチャネル |
130 PT1_DEVICE *ptr ; // カード別情報 | 126 PT1_DEVICE *ptr ; // カード別情報 |
131 wait_queue_head_t wait_q ; // for poll on reading | 127 wait_queue_head_t wait_q ; // for poll on reading |
132 }; | 128 }; |
244 continue ; | 240 continue ; |
245 } | 241 } |
246 mutex_lock(&channel->lock); | 242 mutex_lock(&channel->lock); |
247 // あふれたら読み出すまで待つ | 243 // あふれたら読み出すまで待つ |
248 while(1){ | 244 while(1){ |
249 if(channel->size >= (channel->maxsize - 4)){ | 245 if(channel->size >= (channel->maxsize - PACKET_SIZE - 4)){ |
250 // 該当チャンネルのDMA読みだし待ちにする | 246 // 該当チャンネルのDMA読みだし待ちにする |
251 wake_up(&channel->wait_q); | 247 wake_up(&channel->wait_q); |
252 channel->req_dma = TRUE ; | 248 channel->req_dma = TRUE ; |
253 mutex_unlock(&channel->lock); | 249 mutex_unlock(&channel->lock); |
254 // タスクに時間を渡す為中断 | 250 // タスクに時間を渡す為中断 |
270 channel->packet_size += 1 ; | 266 channel->packet_size += 1 ; |
271 } | 267 } |
272 | 268 |
273 // パケットが出来たらコピーする | 269 // パケットが出来たらコピーする |
274 if(channel->packet_size >= PACKET_SIZE){ | 270 if(channel->packet_size >= PACKET_SIZE){ |
275 memcpy(&channel->buf[channel->size], | 271 if (channel->pointer + channel->size >= channel->maxsize) { |
276 channel->packet_buf, PACKET_SIZE); | 272 // リングバッファの境界を越えていてリングバッファの先頭に戻っている場合 |
273 // channel->pointer + channel->size - channel->maxsize でリングバッファ先頭からのアドレスになる | |
274 memcpy(&channel->buf[channel->pointer + channel->size - channel->maxsize], channel->packet_buf, PACKET_SIZE); | |
275 } else if (channel->pointer + channel->size + PACKET_SIZE > channel->maxsize) { | |
276 // リングバッファの境界をまたぐように書き込まれる場合 | |
277 // リングバッファの境界まで書き込み | |
278 __u32 tmp_size = channel->maxsize - (channel->pointer + channel->size); | |
279 memcpy(&channel->buf[channel->pointer + channel->size], channel->packet_buf, tmp_size); | |
280 // 先頭に戻って書き込み | |
281 memcpy(channel->buf, &channel->packet_buf[tmp_size], PACKET_SIZE - tmp_size); | |
282 } else { | |
283 // リングバッファ内で収まる場合 | |
284 // 通常の書き込み | |
285 memcpy(&channel->buf[channel->pointer + channel->size], channel->packet_buf, PACKET_SIZE); | |
286 } | |
277 channel->size += PACKET_SIZE ; | 287 channel->size += PACKET_SIZE ; |
278 channel->packet_size = 0 ; | 288 channel->packet_size = 0 ; |
279 } | 289 } |
280 mutex_unlock(&channel->lock); | 290 mutex_unlock(&channel->lock); |
281 } | 291 } |
383 } | 393 } |
384 mutex_lock(&channel->lock); | 394 mutex_lock(&channel->lock); |
385 if(!channel->size){ | 395 if(!channel->size){ |
386 size = 0 ; | 396 size = 0 ; |
387 }else{ | 397 }else{ |
388 if(cnt < channel->size){ | 398 __u32 tmp_size = 0; |
389 // バッファが足りない場合は残りを移動する | 399 if (cnt < channel->size) { |
390 size = cnt ; | 400 // バッファにあるデータより小さい読み込みの場合 |
391 dummy = copy_to_user(buf, channel->buf, cnt); | 401 size = cnt; |
392 memmove(channel->buf, &channel->buf[cnt], (channel->size - cnt)); | 402 } else { |
393 channel->size -= cnt ; | 403 // バッファにあるデータ以上の読み込みの場合 |
394 }else{ | 404 size = channel->size; |
395 size = channel->size ; | 405 } |
396 dummy = copy_to_user(buf, channel->buf, size); | 406 if (channel->maxsize <= size + channel->pointer) { |
397 channel->size = 0 ; | 407 // リングバッファの境界を越える場合 |
398 } | 408 tmp_size = channel->maxsize - channel->pointer; |
409 // 境界までコピー | |
410 copy_to_user(buf, &channel->buf[channel->pointer], tmp_size); | |
411 // 残りをコピー | |
412 copy_to_user(&buf[tmp_size], channel->buf, size - tmp_size); | |
413 channel->pointer = size - tmp_size; | |
414 } else { | |
415 // 普通にコピー | |
416 copy_to_user(buf, &channel->buf[channel->pointer], size); | |
417 channel->pointer += size; | |
418 } | |
419 channel->size -= size; | |
399 } | 420 } |
400 // 読み終わったかつ使用しているのがが4K以下 | 421 // 読み終わったかつ使用しているのがが4K以下 |
401 if(channel->req_dma == TRUE){ | 422 if(channel->req_dma == TRUE){ |
402 channel->req_dma = FALSE ; | 423 channel->req_dma = FALSE ; |
403 wake_up(&channel->ptr->dma_wait_q); | 424 wake_up(&channel->ptr->dma_wait_q); |
731 init_waitqueue_head(&channel->wait_q); | 752 init_waitqueue_head(&channel->wait_q); |
732 | 753 |
733 switch(channel->type){ | 754 switch(channel->type){ |
734 case CHANNEL_TYPE_ISDB_T: | 755 case CHANNEL_TYPE_ISDB_T: |
735 channel->maxsize = CHANEL_DMA_SIZE ; | 756 channel->maxsize = CHANEL_DMA_SIZE ; |
736 channel->buf = kzalloc(CHANEL_DMA_SIZE, GFP_KERNEL); | 757 channel->buf = vmalloc(CHANEL_DMA_SIZE); |
758 channel->pointer = 0; | |
737 break ; | 759 break ; |
738 case CHANNEL_TYPE_ISDB_S: | 760 case CHANNEL_TYPE_ISDB_S: |
739 channel->maxsize = BS_CHANEL_DMA_SIZE ; | 761 channel->maxsize = BS_CHANEL_DMA_SIZE ; |
740 channel->buf = kzalloc(BS_CHANEL_DMA_SIZE, GFP_KERNEL); | 762 channel->buf = vmalloc(BS_CHANEL_DMA_SIZE); |
763 channel->pointer = 0; | |
741 break ; | 764 break ; |
742 } | 765 } |
743 if(channel->buf == NULL){ | 766 if(channel->buf == NULL){ |
744 goto out_err_v4l; | 767 goto out_err_v4l; |
745 } | 768 } |
783 pt1_dma_free(pdev, dev_conf); | 806 pt1_dma_free(pdev, dev_conf); |
784 out_err_v4l: | 807 out_err_v4l: |
785 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ | 808 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ |
786 if(dev_conf->channel[lp] != NULL){ | 809 if(dev_conf->channel[lp] != NULL){ |
787 if(dev_conf->channel[lp]->buf != NULL){ | 810 if(dev_conf->channel[lp]->buf != NULL){ |
788 kfree(dev_conf->channel[lp]->buf); | 811 vfree(dev_conf->channel[lp]->buf); |
789 } | 812 } |
790 kfree(dev_conf->channel[lp]); | 813 kfree(dev_conf->channel[lp]); |
791 } | 814 } |
792 } | 815 } |
793 out_err_fpga: | 816 out_err_fpga: |
829 } | 852 } |
830 pt1_dma_free(pdev, dev_conf); | 853 pt1_dma_free(pdev, dev_conf); |
831 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ | 854 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ |
832 if(dev_conf->channel[lp] != NULL){ | 855 if(dev_conf->channel[lp] != NULL){ |
833 cdev_del(&dev_conf->cdev[lp]); | 856 cdev_del(&dev_conf->cdev[lp]); |
834 kfree(dev_conf->channel[lp]->buf); | 857 vfree(dev_conf->channel[lp]->buf); |
835 kfree(dev_conf->channel[lp]); | 858 kfree(dev_conf->channel[lp]); |
836 } | 859 } |
837 device_destroy(pt1video_class, | 860 device_destroy(pt1video_class, |
838 MKDEV(MAJOR(dev_conf->dev), | 861 MKDEV(MAJOR(dev_conf->dev), |
839 (MINOR(dev_conf->dev) + lp))); | 862 (MINOR(dev_conf->dev) + lp))); |