1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2b285192aSMauro Carvalho Chehab /*
3b285192aSMauro Carvalho Chehab * Driver for the NXP SAA7164 PCIe bridge
4b285192aSMauro Carvalho Chehab *
563a412ecSSteven Toth * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
6b285192aSMauro Carvalho Chehab */
7b285192aSMauro Carvalho Chehab
8b285192aSMauro Carvalho Chehab #include <linux/slab.h>
9b285192aSMauro Carvalho Chehab
10b285192aSMauro Carvalho Chehab #include "saa7164.h"
11b285192aSMauro Carvalho Chehab
12b285192aSMauro Carvalho Chehab /* The PCI address space for buffer handling looks like this:
13b285192aSMauro Carvalho Chehab *
14b285192aSMauro Carvalho Chehab * +-u32 wide-------------+
15b285192aSMauro Carvalho Chehab * | +
16b285192aSMauro Carvalho Chehab * +-u64 wide------------------------------------+
17b285192aSMauro Carvalho Chehab * + +
18b285192aSMauro Carvalho Chehab * +----------------------+
19b285192aSMauro Carvalho Chehab * | CurrentBufferPtr + Pointer to current PCI buffer >-+
20b285192aSMauro Carvalho Chehab * +----------------------+ |
21b285192aSMauro Carvalho Chehab * | Unused + |
22b285192aSMauro Carvalho Chehab * +----------------------+ |
23b285192aSMauro Carvalho Chehab * | Pitch + = 188 (bytes) |
24b285192aSMauro Carvalho Chehab * +----------------------+ |
25b285192aSMauro Carvalho Chehab * | PCI buffer size + = pitch * number of lines (312) |
26b285192aSMauro Carvalho Chehab * +----------------------+ |
27b285192aSMauro Carvalho Chehab * |0| Buf0 Write Offset + |
28b285192aSMauro Carvalho Chehab * +----------------------+ v
29b285192aSMauro Carvalho Chehab * |1| Buf1 Write Offset + |
30b285192aSMauro Carvalho Chehab * +----------------------+ |
31b285192aSMauro Carvalho Chehab * |2| Buf2 Write Offset + |
32b285192aSMauro Carvalho Chehab * +----------------------+ |
33b285192aSMauro Carvalho Chehab * |3| Buf3 Write Offset + |
34b285192aSMauro Carvalho Chehab * +----------------------+ |
35b285192aSMauro Carvalho Chehab * ... More write offsets |
36b285192aSMauro Carvalho Chehab * +---------------------------------------------+ |
37b285192aSMauro Carvalho Chehab * +0| set of ptrs to PCI pagetables + |
38b285192aSMauro Carvalho Chehab * +---------------------------------------------+ |
39b285192aSMauro Carvalho Chehab * +1| set of ptrs to PCI pagetables + <--------+
40b285192aSMauro Carvalho Chehab * +---------------------------------------------+
41b285192aSMauro Carvalho Chehab * +2| set of ptrs to PCI pagetables +
42b285192aSMauro Carvalho Chehab * +---------------------------------------------+
43b285192aSMauro Carvalho Chehab * +3| set of ptrs to PCI pagetables + >--+
44b285192aSMauro Carvalho Chehab * +---------------------------------------------+ |
45b285192aSMauro Carvalho Chehab * ... More buffer pointers | +----------------+
46b285192aSMauro Carvalho Chehab * +->| pt[0] TS data |
47b285192aSMauro Carvalho Chehab * | +----------------+
48b285192aSMauro Carvalho Chehab * |
49b285192aSMauro Carvalho Chehab * | +----------------+
50b285192aSMauro Carvalho Chehab * +->| pt[1] TS data |
51b285192aSMauro Carvalho Chehab * | +----------------+
52b285192aSMauro Carvalho Chehab * | etc
53b285192aSMauro Carvalho Chehab */
54b285192aSMauro Carvalho Chehab
saa7164_buffer_display(struct saa7164_buffer * buf)55b285192aSMauro Carvalho Chehab void saa7164_buffer_display(struct saa7164_buffer *buf)
56b285192aSMauro Carvalho Chehab {
57b285192aSMauro Carvalho Chehab struct saa7164_dev *dev = buf->port->dev;
58b285192aSMauro Carvalho Chehab int i;
59b285192aSMauro Carvalho Chehab
60b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, "%s() buffer @ 0x%p nr=%d\n",
61b285192aSMauro Carvalho Chehab __func__, buf, buf->idx);
62b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " pci_cpu @ 0x%p dma @ 0x%08llx len = 0x%x\n",
63b285192aSMauro Carvalho Chehab buf->cpu, (long long)buf->dma, buf->pci_size);
64b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " pt_cpu @ 0x%p pt_dma @ 0x%08llx len = 0x%x\n",
65b285192aSMauro Carvalho Chehab buf->pt_cpu, (long long)buf->pt_dma, buf->pt_size);
66b285192aSMauro Carvalho Chehab
67b285192aSMauro Carvalho Chehab /* Format the Page Table Entries to point into the data buffer */
68b285192aSMauro Carvalho Chehab for (i = 0 ; i < SAA7164_PT_ENTRIES; i++) {
69b285192aSMauro Carvalho Chehab
70b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " pt[%02d] = 0x%p -> 0x%llx\n",
71b285192aSMauro Carvalho Chehab i, buf->pt_cpu, (u64)*(buf->pt_cpu));
72b285192aSMauro Carvalho Chehab
73b285192aSMauro Carvalho Chehab }
74b285192aSMauro Carvalho Chehab }
75b285192aSMauro Carvalho Chehab /* Allocate a new buffer structure and associated PCI space in bytes.
76b285192aSMauro Carvalho Chehab * len must be a multiple of sizeof(u64)
77b285192aSMauro Carvalho Chehab */
saa7164_buffer_alloc(struct saa7164_port * port,u32 len)78b285192aSMauro Carvalho Chehab struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
79b285192aSMauro Carvalho Chehab u32 len)
80b285192aSMauro Carvalho Chehab {
81b285192aSMauro Carvalho Chehab struct tmHWStreamParameters *params = &port->hw_streamingparams;
82b285192aSMauro Carvalho Chehab struct saa7164_buffer *buf = NULL;
83b285192aSMauro Carvalho Chehab struct saa7164_dev *dev = port->dev;
84b285192aSMauro Carvalho Chehab int i;
85b285192aSMauro Carvalho Chehab
86b285192aSMauro Carvalho Chehab if ((len == 0) || (len >= 65536) || (len % sizeof(u64))) {
87b285192aSMauro Carvalho Chehab log_warn("%s() SAA_ERR_BAD_PARAMETER\n", __func__);
88b285192aSMauro Carvalho Chehab goto ret;
89b285192aSMauro Carvalho Chehab }
90b285192aSMauro Carvalho Chehab
912d3da59fSMarkus Elfring buf = kzalloc(sizeof(*buf), GFP_KERNEL);
92c38e8657SMarkus Elfring if (!buf)
93b285192aSMauro Carvalho Chehab goto ret;
94b285192aSMauro Carvalho Chehab
95b285192aSMauro Carvalho Chehab buf->idx = -1;
96b285192aSMauro Carvalho Chehab buf->port = port;
97b285192aSMauro Carvalho Chehab buf->flags = SAA7164_BUFFER_FREE;
98b285192aSMauro Carvalho Chehab buf->pos = 0;
99b285192aSMauro Carvalho Chehab buf->actual_size = params->pitch * params->numberoflines;
100b285192aSMauro Carvalho Chehab buf->crc = 0;
101b285192aSMauro Carvalho Chehab /* TODO: arg len is being ignored */
102b285192aSMauro Carvalho Chehab buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
103b285192aSMauro Carvalho Chehab buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
104b285192aSMauro Carvalho Chehab
105b285192aSMauro Carvalho Chehab /* Allocate contiguous memory */
106*873a623fSChristophe JAILLET buf->cpu = dma_alloc_coherent(&port->dev->pci->dev, buf->pci_size,
107*873a623fSChristophe JAILLET &buf->dma, GFP_KERNEL);
108b285192aSMauro Carvalho Chehab if (!buf->cpu)
109b285192aSMauro Carvalho Chehab goto fail1;
110b285192aSMauro Carvalho Chehab
111*873a623fSChristophe JAILLET buf->pt_cpu = dma_alloc_coherent(&port->dev->pci->dev, buf->pt_size,
112*873a623fSChristophe JAILLET &buf->pt_dma, GFP_KERNEL);
113b285192aSMauro Carvalho Chehab if (!buf->pt_cpu)
114b285192aSMauro Carvalho Chehab goto fail2;
115b285192aSMauro Carvalho Chehab
116b285192aSMauro Carvalho Chehab /* init the buffers to a known pattern, easier during debugging */
117065e1477SHans Verkuil memset(buf->cpu, 0xff, buf->pci_size);
118b285192aSMauro Carvalho Chehab buf->crc = crc32(0, buf->cpu, buf->actual_size);
119065e1477SHans Verkuil memset(buf->pt_cpu, 0xff, buf->pt_size);
120b285192aSMauro Carvalho Chehab
121b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p (%d pageptrs)\n",
122b285192aSMauro Carvalho Chehab __func__, buf, params->numpagetables);
123b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " pci_cpu @ 0x%p dma @ 0x%08lx len = 0x%x\n",
124b285192aSMauro Carvalho Chehab buf->cpu, (long)buf->dma, buf->pci_size);
125b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n",
126b285192aSMauro Carvalho Chehab buf->pt_cpu, (long)buf->pt_dma, buf->pt_size);
127b285192aSMauro Carvalho Chehab
128b285192aSMauro Carvalho Chehab /* Format the Page Table Entries to point into the data buffer */
129b285192aSMauro Carvalho Chehab for (i = 0 ; i < params->numpagetables; i++) {
130b285192aSMauro Carvalho Chehab
131b285192aSMauro Carvalho Chehab *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */
132b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " pt[%02d] = 0x%p -> 0x%llx\n",
133b285192aSMauro Carvalho Chehab i, buf->pt_cpu, (u64)*(buf->pt_cpu));
134b285192aSMauro Carvalho Chehab
135b285192aSMauro Carvalho Chehab }
136b285192aSMauro Carvalho Chehab
137b285192aSMauro Carvalho Chehab goto ret;
138b285192aSMauro Carvalho Chehab
139b285192aSMauro Carvalho Chehab fail2:
140*873a623fSChristophe JAILLET dma_free_coherent(&port->dev->pci->dev, buf->pci_size, buf->cpu,
141*873a623fSChristophe JAILLET buf->dma);
142b285192aSMauro Carvalho Chehab fail1:
143b285192aSMauro Carvalho Chehab kfree(buf);
144b285192aSMauro Carvalho Chehab
145b285192aSMauro Carvalho Chehab buf = NULL;
146b285192aSMauro Carvalho Chehab ret:
147b285192aSMauro Carvalho Chehab return buf;
148b285192aSMauro Carvalho Chehab }
149b285192aSMauro Carvalho Chehab
saa7164_buffer_dealloc(struct saa7164_buffer * buf)150b285192aSMauro Carvalho Chehab int saa7164_buffer_dealloc(struct saa7164_buffer *buf)
151b285192aSMauro Carvalho Chehab {
152b285192aSMauro Carvalho Chehab struct saa7164_dev *dev;
153b285192aSMauro Carvalho Chehab
154b285192aSMauro Carvalho Chehab if (!buf || !buf->port)
155b285192aSMauro Carvalho Chehab return SAA_ERR_BAD_PARAMETER;
156b285192aSMauro Carvalho Chehab dev = buf->port->dev;
157b285192aSMauro Carvalho Chehab
158b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n",
159b285192aSMauro Carvalho Chehab __func__, buf);
160b285192aSMauro Carvalho Chehab
161b285192aSMauro Carvalho Chehab if (buf->flags != SAA7164_BUFFER_FREE)
162b285192aSMauro Carvalho Chehab log_warn(" freeing a non-free buffer\n");
163b285192aSMauro Carvalho Chehab
164*873a623fSChristophe JAILLET dma_free_coherent(&dev->pci->dev, buf->pci_size, buf->cpu, buf->dma);
165*873a623fSChristophe JAILLET dma_free_coherent(&dev->pci->dev, buf->pt_size, buf->pt_cpu,
166*873a623fSChristophe JAILLET buf->pt_dma);
167b285192aSMauro Carvalho Chehab
168b285192aSMauro Carvalho Chehab kfree(buf);
169b285192aSMauro Carvalho Chehab
170b285192aSMauro Carvalho Chehab return SAA_OK;
171b285192aSMauro Carvalho Chehab }
172b285192aSMauro Carvalho Chehab
saa7164_buffer_zero_offsets(struct saa7164_port * port,int i)173b285192aSMauro Carvalho Chehab int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i)
174b285192aSMauro Carvalho Chehab {
175b285192aSMauro Carvalho Chehab struct saa7164_dev *dev = port->dev;
176b285192aSMauro Carvalho Chehab
177b285192aSMauro Carvalho Chehab if ((i < 0) || (i >= port->hwcfg.buffercount))
178b285192aSMauro Carvalho Chehab return -EINVAL;
179b285192aSMauro Carvalho Chehab
180b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
181b285192aSMauro Carvalho Chehab
182b285192aSMauro Carvalho Chehab saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
183b285192aSMauro Carvalho Chehab
184b285192aSMauro Carvalho Chehab return 0;
185b285192aSMauro Carvalho Chehab }
186b285192aSMauro Carvalho Chehab
187b285192aSMauro Carvalho Chehab /* Write a buffer into the hardware */
saa7164_buffer_activate(struct saa7164_buffer * buf,int i)188b285192aSMauro Carvalho Chehab int saa7164_buffer_activate(struct saa7164_buffer *buf, int i)
189b285192aSMauro Carvalho Chehab {
190b285192aSMauro Carvalho Chehab struct saa7164_port *port = buf->port;
191b285192aSMauro Carvalho Chehab struct saa7164_dev *dev = port->dev;
192b285192aSMauro Carvalho Chehab
193b285192aSMauro Carvalho Chehab if ((i < 0) || (i >= port->hwcfg.buffercount))
194b285192aSMauro Carvalho Chehab return -EINVAL;
195b285192aSMauro Carvalho Chehab
196b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
197b285192aSMauro Carvalho Chehab
198b285192aSMauro Carvalho Chehab buf->idx = i; /* Note of which buffer list index position we occupy */
199b285192aSMauro Carvalho Chehab buf->flags = SAA7164_BUFFER_BUSY;
200b285192aSMauro Carvalho Chehab buf->pos = 0;
201b285192aSMauro Carvalho Chehab
202b285192aSMauro Carvalho Chehab /* TODO: Review this in light of 32v64 assignments */
203b285192aSMauro Carvalho Chehab saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
204b285192aSMauro Carvalho Chehab saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i), buf->pt_dma);
205b285192aSMauro Carvalho Chehab saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0);
206b285192aSMauro Carvalho Chehab
20724f711c1SMauro Carvalho Chehab dprintk(DBGLVL_BUF, " buf[%d] offset 0x%llx (0x%x) buf 0x%llx/%llx (0x%x/%x) nr=%d\n",
208b285192aSMauro Carvalho Chehab buf->idx,
209b285192aSMauro Carvalho Chehab (u64)port->bufoffset + (i * sizeof(u32)),
210b285192aSMauro Carvalho Chehab saa7164_readl(port->bufoffset + (sizeof(u32) * i)),
211b285192aSMauro Carvalho Chehab (u64)port->bufptr32h + ((sizeof(u32) * 2) * i),
212b285192aSMauro Carvalho Chehab (u64)port->bufptr32l + ((sizeof(u32) * 2) * i),
213b285192aSMauro Carvalho Chehab saa7164_readl(port->bufptr32h + ((sizeof(u32) * i) * 2)),
214b285192aSMauro Carvalho Chehab saa7164_readl(port->bufptr32l + ((sizeof(u32) * i) * 2)),
215b285192aSMauro Carvalho Chehab buf->idx);
216b285192aSMauro Carvalho Chehab
217b285192aSMauro Carvalho Chehab return 0;
218b285192aSMauro Carvalho Chehab }
219b285192aSMauro Carvalho Chehab
saa7164_buffer_cfg_port(struct saa7164_port * port)220b285192aSMauro Carvalho Chehab int saa7164_buffer_cfg_port(struct saa7164_port *port)
221b285192aSMauro Carvalho Chehab {
222b285192aSMauro Carvalho Chehab struct tmHWStreamParameters *params = &port->hw_streamingparams;
223b285192aSMauro Carvalho Chehab struct saa7164_dev *dev = port->dev;
224b285192aSMauro Carvalho Chehab struct saa7164_buffer *buf;
225b285192aSMauro Carvalho Chehab struct list_head *c, *n;
226b285192aSMauro Carvalho Chehab int i = 0;
227b285192aSMauro Carvalho Chehab
228b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, "%s(port=%d)\n", __func__, port->nr);
229b285192aSMauro Carvalho Chehab
230b285192aSMauro Carvalho Chehab saa7164_writel(port->bufcounter, 0);
231b285192aSMauro Carvalho Chehab saa7164_writel(port->pitch, params->pitch);
232b285192aSMauro Carvalho Chehab saa7164_writel(port->bufsize, params->pitch * params->numberoflines);
233b285192aSMauro Carvalho Chehab
234b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " configured:\n");
235b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " lmmio 0x%p\n", dev->lmmio);
236b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " bufcounter 0x%x = 0x%x\n", port->bufcounter,
237b285192aSMauro Carvalho Chehab saa7164_readl(port->bufcounter));
238b285192aSMauro Carvalho Chehab
239b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " pitch 0x%x = %d\n", port->pitch,
240b285192aSMauro Carvalho Chehab saa7164_readl(port->pitch));
241b285192aSMauro Carvalho Chehab
242b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " bufsize 0x%x = %d\n", port->bufsize,
243b285192aSMauro Carvalho Chehab saa7164_readl(port->bufsize));
244b285192aSMauro Carvalho Chehab
245b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " buffercount = %d\n", port->hwcfg.buffercount);
246b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " bufoffset = 0x%x\n", port->bufoffset);
247b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " bufptr32h = 0x%x\n", port->bufptr32h);
248b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, " bufptr32l = 0x%x\n", port->bufptr32l);
249b285192aSMauro Carvalho Chehab
250b285192aSMauro Carvalho Chehab /* Poke the buffers and offsets into PCI space */
251b285192aSMauro Carvalho Chehab mutex_lock(&port->dmaqueue_lock);
252b285192aSMauro Carvalho Chehab list_for_each_safe(c, n, &port->dmaqueue.list) {
253b285192aSMauro Carvalho Chehab buf = list_entry(c, struct saa7164_buffer, list);
254b285192aSMauro Carvalho Chehab
2552ad5e2e4SDaniel W. S. Almeida BUG_ON(buf->flags != SAA7164_BUFFER_FREE);
256b285192aSMauro Carvalho Chehab
257b285192aSMauro Carvalho Chehab /* Place the buffer in the h/w queue */
258b285192aSMauro Carvalho Chehab saa7164_buffer_activate(buf, i);
259b285192aSMauro Carvalho Chehab
260b285192aSMauro Carvalho Chehab /* Don't exceed the device maximum # bufs */
2612ad5e2e4SDaniel W. S. Almeida BUG_ON(i > port->hwcfg.buffercount);
2622ad5e2e4SDaniel W. S. Almeida i++;
263b285192aSMauro Carvalho Chehab
264b285192aSMauro Carvalho Chehab }
265b285192aSMauro Carvalho Chehab mutex_unlock(&port->dmaqueue_lock);
266b285192aSMauro Carvalho Chehab
267b285192aSMauro Carvalho Chehab return 0;
268b285192aSMauro Carvalho Chehab }
269b285192aSMauro Carvalho Chehab
saa7164_buffer_alloc_user(struct saa7164_dev * dev,u32 len)270b285192aSMauro Carvalho Chehab struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev,
271b285192aSMauro Carvalho Chehab u32 len)
272b285192aSMauro Carvalho Chehab {
273b285192aSMauro Carvalho Chehab struct saa7164_user_buffer *buf;
274b285192aSMauro Carvalho Chehab
2752d3da59fSMarkus Elfring buf = kzalloc(sizeof(*buf), GFP_KERNEL);
276b285192aSMauro Carvalho Chehab if (!buf)
277b285192aSMauro Carvalho Chehab return NULL;
278b285192aSMauro Carvalho Chehab
279b285192aSMauro Carvalho Chehab buf->data = kzalloc(len, GFP_KERNEL);
280b285192aSMauro Carvalho Chehab
281b285192aSMauro Carvalho Chehab if (!buf->data) {
282b285192aSMauro Carvalho Chehab kfree(buf);
283b285192aSMauro Carvalho Chehab return NULL;
284b285192aSMauro Carvalho Chehab }
285b285192aSMauro Carvalho Chehab
286b285192aSMauro Carvalho Chehab buf->actual_size = len;
287b285192aSMauro Carvalho Chehab buf->pos = 0;
288b285192aSMauro Carvalho Chehab buf->crc = 0;
289b285192aSMauro Carvalho Chehab
290b285192aSMauro Carvalho Chehab dprintk(DBGLVL_BUF, "%s() allocated user buffer @ 0x%p\n",
291b285192aSMauro Carvalho Chehab __func__, buf);
292b285192aSMauro Carvalho Chehab
293b285192aSMauro Carvalho Chehab return buf;
294b285192aSMauro Carvalho Chehab }
295b285192aSMauro Carvalho Chehab
saa7164_buffer_dealloc_user(struct saa7164_user_buffer * buf)296b285192aSMauro Carvalho Chehab void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf)
297b285192aSMauro Carvalho Chehab {
298b285192aSMauro Carvalho Chehab if (!buf)
299b285192aSMauro Carvalho Chehab return;
300b285192aSMauro Carvalho Chehab
301b285192aSMauro Carvalho Chehab kfree(buf->data);
302b285192aSMauro Carvalho Chehab buf->data = NULL;
303b285192aSMauro Carvalho Chehab
304b285192aSMauro Carvalho Chehab kfree(buf);
305b285192aSMauro Carvalho Chehab }
306