Merge with Linux 2.4.0-test6-pre9.
[linux-2.6/linux-mips.git] / drivers / char / ftape / lowlevel / ftape-buffer.c
blob02fe29dac1cf85a9e6022c0fb567e80679caf6fe
1 /*
2 * Copyright (C) 1997 Claus-Justus Heine
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.
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.
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.
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-buffer.c,v $
20 * $Revision: 1.3 $
21 * $Date: 1997/10/16 23:33:11 $
23 * This file contains the allocator/dealloctor for ftape's dynamic dma
24 * buffer.
27 #include <asm/segment.h>
28 #include <linux/malloc.h>
29 #include <linux/mm.h>
30 #include <linux/mman.h>
31 #include <linux/wrapper.h>
32 #include <asm/dma.h>
34 #include <linux/ftape.h>
35 #include "../lowlevel/ftape-rw.h"
36 #include "../lowlevel/ftape-read.h"
37 #include "../lowlevel/ftape-tracing.h"
39 /* DMA'able memory allocation stuff.
42 static inline void *dmaalloc(size_t size)
44 unsigned long addr;
46 if (size == 0) {
47 return NULL;
49 addr = __get_dma_pages(GFP_KERNEL, get_order(size));
50 if (addr) {
51 struct page *page;
53 for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++)
54 mem_map_reserve(page);
56 return (void *)addr;
59 static inline void dmafree(void *addr, size_t size)
61 if (size > 0) {
62 struct page *page;
64 for (page = virt_to_page((unsigned long)addr);
65 page < virt_to_page((unsigned long)addr+size); page++)
66 mem_map_unreserve(page);
67 free_pages((unsigned long) addr, get_order(size));
71 static int add_one_buffer(void)
73 TRACE_FUN(ft_t_flow);
75 if (ft_nr_buffers >= FT_MAX_NR_BUFFERS) {
76 TRACE_EXIT -ENOMEM;
78 ft_buffer[ft_nr_buffers] = kmalloc(sizeof(buffer_struct), GFP_KERNEL);
79 if (ft_buffer[ft_nr_buffers] == NULL) {
80 TRACE_EXIT -ENOMEM;
82 memset(ft_buffer[ft_nr_buffers], 0, sizeof(buffer_struct));
83 ft_buffer[ft_nr_buffers]->address = dmaalloc(FT_BUFF_SIZE);
84 if (ft_buffer[ft_nr_buffers]->address == NULL) {
85 kfree(ft_buffer[ft_nr_buffers]);
86 ft_buffer[ft_nr_buffers] = NULL;
87 TRACE_EXIT -ENOMEM;
89 ft_nr_buffers ++;
90 TRACE(ft_t_info, "buffer nr #%d @ %p, dma area @ %p",
91 ft_nr_buffers,
92 ft_buffer[ft_nr_buffers-1],
93 ft_buffer[ft_nr_buffers-1]->address);
94 TRACE_EXIT 0;
97 static void del_one_buffer(void)
99 TRACE_FUN(ft_t_flow);
100 if (ft_nr_buffers > 0) {
101 TRACE(ft_t_info, "releasing buffer nr #%d @ %p, dma area @ %p",
102 ft_nr_buffers,
103 ft_buffer[ft_nr_buffers-1],
104 ft_buffer[ft_nr_buffers-1]->address);
105 ft_nr_buffers --;
106 dmafree(ft_buffer[ft_nr_buffers]->address, FT_BUFF_SIZE);
107 kfree(ft_buffer[ft_nr_buffers]);
108 ft_buffer[ft_nr_buffers] = NULL;
110 TRACE_EXIT;
113 int ftape_set_nr_buffers(int cnt)
115 int delta = cnt - ft_nr_buffers;
116 TRACE_FUN(ft_t_flow);
118 if (delta > 0) {
119 while (delta--) {
120 if (add_one_buffer() < 0) {
121 TRACE_EXIT -ENOMEM;
124 } else if (delta < 0) {
125 while (delta++) {
126 del_one_buffer();
129 ftape_zap_read_buffers();
130 TRACE_EXIT 0;