Blame view

drivers/parisc/ccio-rm-dma.c 5.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  /*
   * ccio-rm-dma.c:
   *	DMA management routines for first generation cache-coherent machines.
   *	"Real Mode" operation refers to U2/Uturn chip operation. The chip
   *      can perform coherency checks w/o using the I/O MMU. That's all we
   *      need until support for more than 4GB phys mem is needed.
   * 
   *	This is the trivial case - basically what x86 does.
   *
   *	Drawbacks of using Real Mode are:
   *	o outbound DMA is slower since one isn't using the prefetching
   *	  U2 can do for outbound DMA.
   *	o Ability to do scatter/gather in HW is also lost.
   *      o only known to work with PCX-W processor. (eg C360)
   *        (PCX-U/U+ are not coherent with U2 in real mode.)
   *
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   *
   * Original version/author:
   *      CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc
   *      cvs -z3 co linux/arch/parisc/kernel/dma-rm.c
   *
   *	(C) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
   *
   *
   * Adopted for The Puffin Group's parisc-linux port by Grant Grundler.
   *	(C) Copyright 2000 Grant Grundler <grundler@puffin.external.hp.com>
   *	
   */
  
  #include <linux/types.h>
  #include <linux/init.h>
  #include <linux/mm.h>
  #include <linux/string.h>
  #include <linux/pci.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
41
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  
  #include <asm/uaccess.h>
  
  #include <asm/io.h>
  #include <asm/hardware.h>
  #include <asm/page.h>
  
  /* Only chose "ccio" since that's what HP-UX calls it....
  ** Make it easier for folks to migrate from one to the other :^)
  */
  #define MODULE_NAME "ccio"
  
  #define U2_IOA_RUNWAY 0x580
  #define U2_BC_GSC     0x501
  #define UTURN_IOA_RUNWAY 0x581
  #define UTURN_BC_GSC     0x502
  
  #define IS_U2(id) ( \
      (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
      (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC))  \
  )
  
  #define IS_UTURN(id) ( \
      (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \
      (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC))  \
  )
  
  static int ccio_dma_supported( struct pci_dev *dev, u64 mask)
  {
  	if (dev == NULL) {
  		printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported
  ");
  		BUG();
  		return(0);
  	}
  
  	/* only support 32-bit devices (ie PCI/GSC) */
  	return((int) (mask >= 0xffffffffUL));
  }
  
  
  static void *ccio_alloc_consistent(struct pci_dev *dev, size_t size,
  				 dma_addr_t *handle)
  {
  	void *ret;
  	
  	ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
  
  	if (ret != NULL) {
  		memset(ret, 0, size);
  		*handle = virt_to_phys(ret);
  	}
  	return ret;
  }
  	
  static void ccio_free_consistent(struct pci_dev *dev, size_t size,
  			       void *vaddr, dma_addr_t handle)
  {
  	free_pages((unsigned long)vaddr, get_order(size));
  }
  
  static dma_addr_t ccio_map_single(struct pci_dev *dev, void *ptr, size_t size,
  			  int direction)
  {
  	return virt_to_phys(ptr);
  }
  
  static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t dma_addr,
  			    size_t size, int direction)
  {
  	/* Nothing to do */
  }
  
  
  static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
  {
  	int tmp = nents;
  
          /* KISS: map each buffer separately. */
  	while (nents) {
  		sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction);
  		sg_dma_len(sglist) = sglist->length;
  		nents--;
  		sglist++;
  	}
  
  	return tmp;
  }
  
  
  static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
  {
  #if 0
  	while (nents) {
  		ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
  		nents--;
  		sglist++;
  	}
  	return;
  #else
  	/* Do nothing (copied from current ccio_unmap_single()  :^) */
  #endif
  }
  
  
  static struct pci_dma_ops ccio_ops = {
  	ccio_dma_supported,
  	ccio_alloc_consistent,
  	ccio_free_consistent,
  	ccio_map_single,
  	ccio_unmap_single,
  	ccio_map_sg,
  	ccio_unmap_sg,
  	NULL,                   /* dma_sync_single_for_cpu : NOP for U2 */
  	NULL,                   /* dma_sync_single_for_device : NOP for U2 */
  	NULL,                   /* dma_sync_sg_for_cpu     : ditto */
  	NULL,                   /* dma_sync_sg_for_device     : ditto */
  };
  
  
  /*
  ** Determine if u2 should claim this chip (return 0) or not (return 1).
  ** If so, initialize the chip and tell other partners in crime they
  ** have work to do.
  */
  static int
  ccio_probe(struct parisc_device *dev)
  {
  	printk(KERN_INFO "%s found %s at 0x%lx
  ", MODULE_NAME,
  			dev->id.hversion == U2_BC_GSC ? "U2" : "UTurn",
53f01bba4   Matthew Wilcox   [PARISC] Convert ...
173
  			dev->hpa.start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  
  /*
  ** FIXME - should check U2 registers to verify it's really running
  ** in "Real Mode".
  */
  
  #if 0
  /* will need this for "Virtual Mode" operation */
  	ccio_hw_init(ccio_dev);
  	ccio_common_init(ccio_dev);
  #endif
  	hppa_dma_ops = &ccio_ops;
  	return 0;
  }
  
  static struct parisc_device_id ccio_tbl[] = {
  	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, U2_BC_GSC, 0xc },
  	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, UTURN_BC_GSC, 0xc },
  	{ 0, }
  };
  
  static struct parisc_driver ccio_driver = {
  	.name =		"U2/Uturn",
  	.id_table =	ccio_tbl,
  	.probe =	ccio_probe,
  };
  
  void __init ccio_init(void)
  {
  	register_parisc_driver(&ccio_driver);
  }