drivers/char/ftape/lowlevel/ftape-buffer.c should #include "../lowlevel/ftape-buffer.h"
[linux-2.6] / drivers / char / ftape / lowlevel / ftape-buffer.c
1 /*
2  *      Copyright (C) 1997 Claus-Justus Heine
3
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2, or (at your option)
7  any later version.
8
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  GNU General Public License for more details.
13
14  You should have received a copy of the GNU General Public License
15  along with this program; see the file COPYING.  If not, write to
16  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18  *
19  * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $
20  * $Revision: 1.3 $
21  * $Date: 1997/10/16 23:33:11 $
22  *
23  *  This file contains the allocator/dealloctor for ftape's dynamic dma
24  *  buffer.
25  */
26
27 #include <linux/slab.h>
28 #include <linux/mm.h>
29 #include <linux/mman.h>
30 #include <asm/dma.h>
31
32 #include <linux/ftape.h>
33 #include "../lowlevel/ftape-rw.h"
34 #include "../lowlevel/ftape-read.h"
35 #include "../lowlevel/ftape-tracing.h"
36 #include "../lowlevel/ftape-buffer.h"
37
38 /*  DMA'able memory allocation stuff.
39  */
40
41 static inline void *dmaalloc(size_t size)
42 {
43         unsigned long addr;
44
45         if (size == 0) {
46                 return NULL;
47         }
48         addr = __get_dma_pages(GFP_KERNEL, get_order(size));
49         if (addr) {
50                 struct page *page;
51
52                 for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)
53                         SetPageReserved(page);
54         }
55         return (void *)addr;
56 }
57
58 static inline void dmafree(void *addr, size_t size)
59 {
60         if (size > 0) {
61                 struct page *page;
62
63                 for (page = virt_to_page((unsigned long)addr);
64                      page < virt_to_page((unsigned long)addr+size); page++)
65                         ClearPageReserved(page);
66                 free_pages((unsigned long) addr, get_order(size));
67         }
68 }
69
70 static int add_one_buffer(void)
71 {
72         TRACE_FUN(ft_t_flow);
73         
74         if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) {
75                 TRACE_EXIT -ENOMEM;
76         }
77         ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL);
78         if (ft_buffer[ft_nr_buffers] == NULL) {
79                 TRACE_EXIT -ENOMEM;
80         }
81         memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct));
82         ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE);
83         if (ft_buffer[ft_nr_buffers]->address == NULL) {
84                 kfree(ft_buffer[ft_nr_buffers]);
85                 ft_buffer[ft_nr_buffers] = NULL;
86                 TRACE_EXIT -ENOMEM;
87         }
88         ft_nr_buffers ++;
89         TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p",
90               ft_nr_buffers,
91               ft_buffer[ft_nr_buffers-1],
92               ft_buffer[ft_nr_buffers-1]->address);
93         TRACE_EXIT 0;
94 }
95
96 static void del_one_buffer(void)
97 {
98         TRACE_FUN(ft_t_flow);
99         if (ft_nr_buffers > 0) {
100                 TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p",
101                       ft_nr_buffers,
102                       ft_buffer[ft_nr_buffers-1],
103                       ft_buffer[ft_nr_buffers-1]->address);
104                 ft_nr_buffers --;
105                 dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE);
106                 kfree(ft_buffer[ft_nr_buffers]);
107                 ft_buffer[ft_nr_buffers] = NULL;
108         }
109         TRACE_EXIT;
110 }
111
112 int ftape_set_nr_buffers(int cnt)
113 {
114         int delta = cnt - ft_nr_buffers;
115         TRACE_FUN(ft_t_flow);
116
117         if (delta > 0) {
118                 while (delta--) {
119                         if (add_one_buffer() < 0) {
120                                 TRACE_EXIT -ENOMEM;
121                         }
122                 }
123         } else if (delta < 0) {
124                 while (delta++) {
125                         del_one_buffer();
126                 }
127         }
128         ftape_zap_read_buffers();
129         TRACE_EXIT 0;
130 }