diff options
author | Jens Taprogge <jens.taprogge@taprogge.org> | 2012-09-12 08:55:26 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-12 12:54:15 -0400 |
commit | 70a32811e5d1c3a48d99088065ef74367221cde3 (patch) | |
tree | 51afeee436d785374ef7f6478ae3475b5177ea3f | |
parent | af2140ce288fcb12a3c30a69b6ba93fd64d0a861 (diff) |
Staging: ipack/devices/ipoctal: split ipoctal_channel from ipoctal.
By moving everything channel related into a separate struct we will be
able to clean up a lot of code. In the end tty->driver_data will no
longer need to point to ipoctal but instead can point to the respective
channel.
Signed-off-by: Jens Taprogge <jens.taprogge@taprogge.org>
Signed-off-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/ipack/devices/ipoctal.c | 286 |
1 files changed, 150 insertions, 136 deletions
diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index 35513d9e013a..9ab0e8082565 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c | |||
@@ -30,22 +30,26 @@ | |||
30 | 30 | ||
31 | static const struct tty_operations ipoctal_fops; | 31 | static const struct tty_operations ipoctal_fops; |
32 | 32 | ||
33 | struct ipoctal_channel { | ||
34 | struct ipoctal_stats stats; | ||
35 | unsigned int nb_bytes; | ||
36 | unsigned int count_wr; | ||
37 | wait_queue_head_t queue; | ||
38 | spinlock_t lock; | ||
39 | unsigned int pointer_read; | ||
40 | unsigned int pointer_write; | ||
41 | atomic_t open; | ||
42 | struct tty_port tty_port; | ||
43 | union scc2698_channel __iomem *regs; | ||
44 | union scc2698_block __iomem *block_regs; | ||
45 | }; | ||
46 | |||
33 | struct ipoctal { | 47 | struct ipoctal { |
34 | struct list_head list; | 48 | struct list_head list; |
35 | struct ipack_device *dev; | 49 | struct ipack_device *dev; |
36 | unsigned int board_id; | 50 | unsigned int board_id; |
37 | union scc2698_channel __iomem *chan_regs; | 51 | struct ipoctal_channel channel[NR_CHANNELS]; |
38 | union scc2698_block __iomem *block_regs; | ||
39 | struct ipoctal_stats chan_stats[NR_CHANNELS]; | ||
40 | unsigned int nb_bytes[NR_CHANNELS]; | ||
41 | unsigned int count_wr[NR_CHANNELS]; | ||
42 | wait_queue_head_t queue[NR_CHANNELS]; | ||
43 | spinlock_t lock[NR_CHANNELS]; | ||
44 | unsigned int pointer_read[NR_CHANNELS]; | ||
45 | unsigned int pointer_write[NR_CHANNELS]; | ||
46 | atomic_t open[NR_CHANNELS]; | ||
47 | unsigned char write; | 52 | unsigned char write; |
48 | struct tty_port tty_port[NR_CHANNELS]; | ||
49 | struct tty_driver *tty_drv; | 53 | struct tty_driver *tty_drv; |
50 | }; | 54 | }; |
51 | 55 | ||
@@ -87,7 +91,7 @@ static struct ipoctal *ipoctal_find_board(struct tty_struct *tty) | |||
87 | static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) | 91 | static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) |
88 | { | 92 | { |
89 | struct ipoctal *ipoctal; | 93 | struct ipoctal *ipoctal; |
90 | int channel = tty->index; | 94 | struct ipoctal_channel *channel; |
91 | 95 | ||
92 | ipoctal = ipoctal_find_board(tty); | 96 | ipoctal = ipoctal_find_board(tty); |
93 | 97 | ||
@@ -96,17 +100,18 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) | |||
96 | tty->driver->major); | 100 | tty->driver->major); |
97 | return -ENODEV; | 101 | return -ENODEV; |
98 | } | 102 | } |
103 | channel = &ipoctal->channel[tty->index]; | ||
99 | 104 | ||
100 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 105 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.cr, |
101 | CR_ENABLE_RX); | 106 | CR_ENABLE_RX); |
102 | return 0; | 107 | return 0; |
103 | } | 108 | } |
104 | 109 | ||
105 | static int ipoctal_open(struct tty_struct *tty, struct file *file) | 110 | static int ipoctal_open(struct tty_struct *tty, struct file *file) |
106 | { | 111 | { |
107 | int channel = tty->index; | ||
108 | int res; | 112 | int res; |
109 | struct ipoctal *ipoctal; | 113 | struct ipoctal *ipoctal; |
114 | struct ipoctal_channel *channel; | ||
110 | 115 | ||
111 | ipoctal = ipoctal_find_board(tty); | 116 | ipoctal = ipoctal_find_board(tty); |
112 | 117 | ||
@@ -115,17 +120,18 @@ static int ipoctal_open(struct tty_struct *tty, struct file *file) | |||
115 | tty->driver->major); | 120 | tty->driver->major); |
116 | return -ENODEV; | 121 | return -ENODEV; |
117 | } | 122 | } |
123 | channel = &ipoctal->channel[tty->index]; | ||
118 | 124 | ||
119 | if (atomic_read(&ipoctal->open[channel])) | 125 | if (atomic_read(&channel->open)) |
120 | return -EBUSY; | 126 | return -EBUSY; |
121 | 127 | ||
122 | tty->driver_data = ipoctal; | 128 | tty->driver_data = ipoctal; |
123 | 129 | ||
124 | res = tty_port_open(&ipoctal->tty_port[channel], tty, file); | 130 | res = tty_port_open(&channel->tty_port, tty, file); |
125 | if (res) | 131 | if (res) |
126 | return res; | 132 | return res; |
127 | 133 | ||
128 | atomic_inc(&ipoctal->open[channel]); | 134 | atomic_inc(&channel->open); |
129 | return 0; | 135 | return 0; |
130 | } | 136 | } |
131 | 137 | ||
@@ -141,26 +147,27 @@ static void ipoctal_reset_stats(struct ipoctal_stats *stats) | |||
141 | 147 | ||
142 | static void ipoctal_free_channel(struct tty_struct *tty) | 148 | static void ipoctal_free_channel(struct tty_struct *tty) |
143 | { | 149 | { |
144 | int channel = tty->index; | ||
145 | struct ipoctal *ipoctal = tty->driver_data; | 150 | struct ipoctal *ipoctal = tty->driver_data; |
151 | struct ipoctal_channel *channel; | ||
146 | 152 | ||
147 | if (ipoctal == NULL) | 153 | if (ipoctal == NULL) |
148 | return; | 154 | return; |
155 | channel = &ipoctal->channel[tty->index]; | ||
149 | 156 | ||
150 | ipoctal_reset_stats(&ipoctal->chan_stats[channel]); | 157 | ipoctal_reset_stats(&channel->stats); |
151 | ipoctal->pointer_read[channel] = 0; | 158 | channel->pointer_read = 0; |
152 | ipoctal->pointer_write[channel] = 0; | 159 | channel->pointer_write = 0; |
153 | ipoctal->nb_bytes[channel] = 0; | 160 | channel->nb_bytes = 0; |
154 | } | 161 | } |
155 | 162 | ||
156 | static void ipoctal_close(struct tty_struct *tty, struct file *filp) | 163 | static void ipoctal_close(struct tty_struct *tty, struct file *filp) |
157 | { | 164 | { |
158 | int channel = tty->index; | ||
159 | struct ipoctal *ipoctal = tty->driver_data; | 165 | struct ipoctal *ipoctal = tty->driver_data; |
166 | struct ipoctal_channel *channel = &ipoctal->channel[tty->index]; | ||
160 | 167 | ||
161 | tty_port_close(&ipoctal->tty_port[channel], tty, filp); | 168 | tty_port_close(&channel->tty_port, tty, filp); |
162 | 169 | ||
163 | if (atomic_dec_and_test(&ipoctal->open[channel])) | 170 | if (atomic_dec_and_test(&channel->open)) |
164 | ipoctal_free_channel(tty); | 171 | ipoctal_free_channel(tty); |
165 | } | 172 | } |
166 | 173 | ||
@@ -168,24 +175,23 @@ static int ipoctal_get_icount(struct tty_struct *tty, | |||
168 | struct serial_icounter_struct *icount) | 175 | struct serial_icounter_struct *icount) |
169 | { | 176 | { |
170 | struct ipoctal *ipoctal = tty->driver_data; | 177 | struct ipoctal *ipoctal = tty->driver_data; |
171 | int channel = tty->index; | 178 | struct ipoctal_channel *channel = &ipoctal->channel[tty->index]; |
172 | 179 | ||
173 | icount->cts = 0; | 180 | icount->cts = 0; |
174 | icount->dsr = 0; | 181 | icount->dsr = 0; |
175 | icount->rng = 0; | 182 | icount->rng = 0; |
176 | icount->dcd = 0; | 183 | icount->dcd = 0; |
177 | icount->rx = ipoctal->chan_stats[channel].rx; | 184 | icount->rx = channel->stats.rx; |
178 | icount->tx = ipoctal->chan_stats[channel].tx; | 185 | icount->tx = channel->stats.tx; |
179 | icount->frame = ipoctal->chan_stats[channel].framing_err; | 186 | icount->frame = channel->stats.framing_err; |
180 | icount->parity = ipoctal->chan_stats[channel].parity_err; | 187 | icount->parity = channel->stats.parity_err; |
181 | icount->brk = ipoctal->chan_stats[channel].rcv_break; | 188 | icount->brk = channel->stats.rcv_break; |
182 | return 0; | 189 | return 0; |
183 | } | 190 | } |
184 | 191 | ||
185 | static int ipoctal_irq_handler(void *arg) | 192 | static int ipoctal_irq_handler(void *arg) |
186 | { | 193 | { |
187 | unsigned int channel; | 194 | unsigned int ichannel; |
188 | unsigned int block; | ||
189 | unsigned char isr; | 195 | unsigned char isr; |
190 | unsigned char sr; | 196 | unsigned char sr; |
191 | unsigned char isr_tx_rdy, isr_rx_rdy; | 197 | unsigned char isr_tx_rdy, isr_rx_rdy; |
@@ -193,14 +199,16 @@ static int ipoctal_irq_handler(void *arg) | |||
193 | unsigned char flag; | 199 | unsigned char flag; |
194 | struct tty_struct *tty; | 200 | struct tty_struct *tty; |
195 | struct ipoctal *ipoctal = (struct ipoctal *) arg; | 201 | struct ipoctal *ipoctal = (struct ipoctal *) arg; |
202 | struct ipoctal_channel *channel; | ||
196 | 203 | ||
197 | /* Check all channels */ | 204 | /* Check all channels */ |
198 | for (channel = 0; channel < NR_CHANNELS; channel++) { | 205 | for (ichannel = 0; ichannel < NR_CHANNELS; ichannel++) { |
206 | channel = &ipoctal->channel[ichannel]; | ||
199 | /* If there is no client, skip the check */ | 207 | /* If there is no client, skip the check */ |
200 | if (!atomic_read(&ipoctal->open[channel])) | 208 | if (!atomic_read(&channel->open)) |
201 | continue; | 209 | continue; |
202 | 210 | ||
203 | tty = tty_port_tty_get(&ipoctal->tty_port[channel]); | 211 | tty = tty_port_tty_get(&channel->tty_port); |
204 | if (!tty) | 212 | if (!tty) |
205 | continue; | 213 | continue; |
206 | 214 | ||
@@ -208,13 +216,12 @@ static int ipoctal_irq_handler(void *arg) | |||
208 | * The HW is organized in pair of channels. | 216 | * The HW is organized in pair of channels. |
209 | * See which register we need to read from | 217 | * See which register we need to read from |
210 | */ | 218 | */ |
211 | block = channel / 2; | ||
212 | isr = ipoctal_read_io_reg(ipoctal, | 219 | isr = ipoctal_read_io_reg(ipoctal, |
213 | &ipoctal->block_regs[block].r.isr); | 220 | &channel->block_regs->r.isr); |
214 | sr = ipoctal_read_io_reg(ipoctal, | 221 | sr = ipoctal_read_io_reg(ipoctal, |
215 | &ipoctal->chan_regs[channel].r.sr); | 222 | &channel->regs->r.sr); |
216 | 223 | ||
217 | if ((channel % 2) == 1) { | 224 | if ((ichannel % 2) == 1) { |
218 | isr_tx_rdy = isr & ISR_TxRDY_B; | 225 | isr_tx_rdy = isr & ISR_TxRDY_B; |
219 | isr_rx_rdy = isr & ISR_RxRDY_FFULL_B; | 226 | isr_rx_rdy = isr & ISR_RxRDY_FFULL_B; |
220 | } else { | 227 | } else { |
@@ -227,47 +234,47 @@ static int ipoctal_irq_handler(void *arg) | |||
227 | */ | 234 | */ |
228 | if ((ipoctal->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) && | 235 | if ((ipoctal->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) && |
229 | (sr & SR_TX_EMPTY) && | 236 | (sr & SR_TX_EMPTY) && |
230 | (ipoctal->nb_bytes[channel] == 0)) { | 237 | (channel->nb_bytes == 0)) { |
231 | ipoctal_write_io_reg(ipoctal, | 238 | ipoctal_write_io_reg(ipoctal, |
232 | &ipoctal->chan_regs[channel].w.cr, | 239 | &channel->regs->w.cr, |
233 | CR_DISABLE_TX); | 240 | CR_DISABLE_TX); |
234 | ipoctal_write_cr_cmd(ipoctal, | 241 | ipoctal_write_cr_cmd(ipoctal, |
235 | &ipoctal->chan_regs[channel].w.cr, | 242 | &channel->regs->w.cr, |
236 | CR_CMD_NEGATE_RTSN); | 243 | CR_CMD_NEGATE_RTSN); |
237 | ipoctal_write_io_reg(ipoctal, | 244 | ipoctal_write_io_reg(ipoctal, |
238 | &ipoctal->chan_regs[channel].w.cr, | 245 | &channel->regs->w.cr, |
239 | CR_ENABLE_RX); | 246 | CR_ENABLE_RX); |
240 | ipoctal->write = 1; | 247 | ipoctal->write = 1; |
241 | wake_up_interruptible(&ipoctal->queue[channel]); | 248 | wake_up_interruptible(&channel->queue); |
242 | } | 249 | } |
243 | 250 | ||
244 | /* RX data */ | 251 | /* RX data */ |
245 | if (isr_rx_rdy && (sr & SR_RX_READY)) { | 252 | if (isr_rx_rdy && (sr & SR_RX_READY)) { |
246 | value = ipoctal_read_io_reg(ipoctal, | 253 | value = ipoctal_read_io_reg(ipoctal, |
247 | &ipoctal->chan_regs[channel].r.rhr); | 254 | &channel->regs->r.rhr); |
248 | flag = TTY_NORMAL; | 255 | flag = TTY_NORMAL; |
249 | 256 | ||
250 | /* Error: count statistics */ | 257 | /* Error: count statistics */ |
251 | if (sr & SR_ERROR) { | 258 | if (sr & SR_ERROR) { |
252 | ipoctal_write_cr_cmd(ipoctal, | 259 | ipoctal_write_cr_cmd(ipoctal, |
253 | &ipoctal->chan_regs[channel].w.cr, | 260 | &channel->regs->w.cr, |
254 | CR_CMD_RESET_ERR_STATUS); | 261 | CR_CMD_RESET_ERR_STATUS); |
255 | 262 | ||
256 | if (sr & SR_OVERRUN_ERROR) { | 263 | if (sr & SR_OVERRUN_ERROR) { |
257 | ipoctal->chan_stats[channel].overrun_err++; | 264 | channel->stats.overrun_err++; |
258 | /* Overrun doesn't affect the current character*/ | 265 | /* Overrun doesn't affect the current character*/ |
259 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 266 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
260 | } | 267 | } |
261 | if (sr & SR_PARITY_ERROR) { | 268 | if (sr & SR_PARITY_ERROR) { |
262 | ipoctal->chan_stats[channel].parity_err++; | 269 | channel->stats.parity_err++; |
263 | flag = TTY_PARITY; | 270 | flag = TTY_PARITY; |
264 | } | 271 | } |
265 | if (sr & SR_FRAMING_ERROR) { | 272 | if (sr & SR_FRAMING_ERROR) { |
266 | ipoctal->chan_stats[channel].framing_err++; | 273 | channel->stats.framing_err++; |
267 | flag = TTY_FRAME; | 274 | flag = TTY_FRAME; |
268 | } | 275 | } |
269 | if (sr & SR_RECEIVED_BREAK) { | 276 | if (sr & SR_RECEIVED_BREAK) { |
270 | ipoctal->chan_stats[channel].rcv_break++; | 277 | channel->stats.rcv_break++; |
271 | flag = TTY_BREAK; | 278 | flag = TTY_BREAK; |
272 | } | 279 | } |
273 | } | 280 | } |
@@ -277,30 +284,29 @@ static int ipoctal_irq_handler(void *arg) | |||
277 | 284 | ||
278 | /* TX of each character */ | 285 | /* TX of each character */ |
279 | if (isr_tx_rdy && (sr & SR_TX_READY)) { | 286 | if (isr_tx_rdy && (sr & SR_TX_READY)) { |
280 | unsigned int *pointer_write = | 287 | unsigned int *pointer_write = &channel->pointer_write; |
281 | &ipoctal->pointer_write[channel]; | ||
282 | 288 | ||
283 | if (ipoctal->nb_bytes[channel] <= 0) { | 289 | if (channel->nb_bytes <= 0) { |
284 | ipoctal->nb_bytes[channel] = 0; | 290 | channel->nb_bytes = 0; |
285 | continue; | 291 | continue; |
286 | } | 292 | } |
287 | 293 | ||
288 | value = ipoctal->tty_port[channel].xmit_buf[*pointer_write]; | 294 | value = channel->tty_port.xmit_buf[*pointer_write]; |
289 | ipoctal_write_io_reg(ipoctal, | 295 | ipoctal_write_io_reg(ipoctal, |
290 | &ipoctal->chan_regs[channel].w.thr, | 296 | &channel->regs->w.thr, |
291 | value); | 297 | value); |
292 | ipoctal->chan_stats[channel].tx++; | 298 | channel->stats.tx++; |
293 | ipoctal->count_wr[channel]++; | 299 | channel->count_wr++; |
294 | (*pointer_write)++; | 300 | (*pointer_write)++; |
295 | *pointer_write = *pointer_write % PAGE_SIZE; | 301 | *pointer_write = *pointer_write % PAGE_SIZE; |
296 | ipoctal->nb_bytes[channel]--; | 302 | channel->nb_bytes--; |
297 | 303 | ||
298 | if ((ipoctal->nb_bytes[channel] == 0) && | 304 | if ((channel->nb_bytes == 0) && |
299 | (waitqueue_active(&ipoctal->queue[channel]))) { | 305 | (waitqueue_active(&channel->queue))) { |
300 | 306 | ||
301 | if (ipoctal->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) { | 307 | if (ipoctal->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) { |
302 | ipoctal->write = 1; | 308 | ipoctal->write = 1; |
303 | wake_up_interruptible(&ipoctal->queue[channel]); | 309 | wake_up_interruptible(&channel->queue); |
304 | } | 310 | } |
305 | } | 311 | } |
306 | } | 312 | } |
@@ -348,6 +354,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, | |||
348 | struct tty_driver *tty; | 354 | struct tty_driver *tty; |
349 | char name[20]; | 355 | char name[20]; |
350 | unsigned char board_id; | 356 | unsigned char board_id; |
357 | struct ipoctal_channel *channel; | ||
358 | union scc2698_channel __iomem *chan_regs; | ||
359 | union scc2698_block __iomem *block_regs; | ||
351 | 360 | ||
352 | res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, | 361 | res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, |
353 | IPACK_ID_SPACE); | 362 | IPACK_ID_SPACE); |
@@ -385,41 +394,45 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, | |||
385 | } | 394 | } |
386 | 395 | ||
387 | /* Save the virtual address to access the registers easily */ | 396 | /* Save the virtual address to access the registers easily */ |
388 | ipoctal->chan_regs = | 397 | chan_regs = |
389 | (union scc2698_channel __iomem *) ipoctal->dev->io_space.address; | 398 | (union scc2698_channel __iomem *) ipoctal->dev->io_space.address; |
390 | ipoctal->block_regs = | 399 | block_regs = |
391 | (union scc2698_block __iomem *) ipoctal->dev->io_space.address; | 400 | (union scc2698_block __iomem *) ipoctal->dev->io_space.address; |
392 | 401 | ||
393 | /* Disable RX and TX before touching anything */ | 402 | /* Disable RX and TX before touching anything */ |
394 | for (i = 0; i < NR_CHANNELS ; i++) { | 403 | for (i = 0; i < NR_CHANNELS ; i++) { |
395 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].w.cr, | 404 | struct ipoctal_channel *channel = &ipoctal->channel[i]; |
405 | channel->regs = chan_regs + i; | ||
406 | channel->block_regs = block_regs + (i >> 1); | ||
407 | |||
408 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.cr, | ||
396 | CR_DISABLE_RX | CR_DISABLE_TX); | 409 | CR_DISABLE_RX | CR_DISABLE_TX); |
397 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].w.cr, | 410 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
398 | CR_CMD_RESET_RX); | 411 | CR_CMD_RESET_RX); |
399 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].w.cr, | 412 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
400 | CR_CMD_RESET_TX); | 413 | CR_CMD_RESET_TX); |
401 | ipoctal_write_io_reg(ipoctal, | 414 | ipoctal_write_io_reg(ipoctal, |
402 | &ipoctal->chan_regs[i].w.mr, | 415 | &channel->regs->w.mr, |
403 | MR1_CHRL_8_BITS | MR1_ERROR_CHAR | | 416 | MR1_CHRL_8_BITS | MR1_ERROR_CHAR | |
404 | MR1_RxINT_RxRDY); /* mr1 */ | 417 | MR1_RxINT_RxRDY); /* mr1 */ |
405 | ipoctal_write_io_reg(ipoctal, | 418 | ipoctal_write_io_reg(ipoctal, |
406 | &ipoctal->chan_regs[i].w.mr, | 419 | &channel->regs->w.mr, |
407 | 0); /* mr2 */ | 420 | 0); /* mr2 */ |
408 | ipoctal_write_io_reg(ipoctal, | 421 | ipoctal_write_io_reg(ipoctal, |
409 | &ipoctal->chan_regs[i].w.csr, | 422 | &channel->regs->w.csr, |
410 | TX_CLK_9600 | RX_CLK_9600); | 423 | TX_CLK_9600 | RX_CLK_9600); |
411 | } | 424 | } |
412 | 425 | ||
413 | for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) { | 426 | for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) { |
414 | ipoctal_write_io_reg(ipoctal, | 427 | ipoctal_write_io_reg(ipoctal, |
415 | &ipoctal->block_regs[i].w.acr, | 428 | &block_regs[i].w.acr, |
416 | ACR_BRG_SET2); | 429 | ACR_BRG_SET2); |
417 | ipoctal_write_io_reg(ipoctal, | 430 | ipoctal_write_io_reg(ipoctal, |
418 | &ipoctal->block_regs[i].w.opcr, | 431 | &block_regs[i].w.opcr, |
419 | OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | | 432 | OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | |
420 | OPCR_MPOb_RTSN); | 433 | OPCR_MPOb_RTSN); |
421 | ipoctal_write_io_reg(ipoctal, | 434 | ipoctal_write_io_reg(ipoctal, |
422 | &ipoctal->block_regs[i].w.imr, | 435 | &block_regs[i].w.imr, |
423 | IMR_TxRDY_A | IMR_RxRDY_FFULL_A | | 436 | IMR_TxRDY_A | IMR_RxRDY_FFULL_A | |
424 | IMR_DELTA_BREAK_A | IMR_TxRDY_B | | 437 | IMR_DELTA_BREAK_A | IMR_TxRDY_B | |
425 | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B); | 438 | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B); |
@@ -472,25 +485,26 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, | |||
472 | ipoctal->tty_drv = tty; | 485 | ipoctal->tty_drv = tty; |
473 | 486 | ||
474 | for (i = 0; i < NR_CHANNELS; i++) { | 487 | for (i = 0; i < NR_CHANNELS; i++) { |
475 | tty_port_init(&ipoctal->tty_port[i]); | 488 | channel = &ipoctal->channel[i]; |
476 | tty_port_alloc_xmit_buf(&ipoctal->tty_port[i]); | 489 | tty_port_init(&channel->tty_port); |
477 | ipoctal->tty_port[i].ops = &ipoctal_tty_port_ops; | 490 | tty_port_alloc_xmit_buf(&channel->tty_port); |
478 | 491 | channel->tty_port.ops = &ipoctal_tty_port_ops; | |
479 | ipoctal_reset_stats(&ipoctal->chan_stats[i]); | 492 | |
480 | ipoctal->nb_bytes[i] = 0; | 493 | ipoctal_reset_stats(&channel->stats); |
481 | init_waitqueue_head(&ipoctal->queue[i]); | 494 | channel->nb_bytes = 0; |
482 | 495 | init_waitqueue_head(&channel->queue); | |
483 | spin_lock_init(&ipoctal->lock[i]); | 496 | |
484 | ipoctal->pointer_read[i] = 0; | 497 | spin_lock_init(&channel->lock); |
485 | ipoctal->pointer_write[i] = 0; | 498 | channel->pointer_read = 0; |
486 | ipoctal->nb_bytes[i] = 0; | 499 | channel->pointer_write = 0; |
500 | channel->nb_bytes = 0; | ||
487 | tty_register_device(tty, i, NULL); | 501 | tty_register_device(tty, i, NULL); |
488 | 502 | ||
489 | /* | 503 | /* |
490 | * Enable again the RX. TX will be enabled when | 504 | * Enable again the RX. TX will be enabled when |
491 | * there is something to send | 505 | * there is something to send |
492 | */ | 506 | */ |
493 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].w.cr, | 507 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.cr, |
494 | CR_ENABLE_RX); | 508 | CR_ENABLE_RX); |
495 | } | 509 | } |
496 | 510 | ||
@@ -505,23 +519,22 @@ out_unregister_id_space: | |||
505 | return res; | 519 | return res; |
506 | } | 520 | } |
507 | 521 | ||
508 | static inline int ipoctal_copy_write_buffer(struct ipoctal *ipoctal, | 522 | static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel, |
509 | unsigned int channel, | ||
510 | const unsigned char *buf, | 523 | const unsigned char *buf, |
511 | int count) | 524 | int count) |
512 | { | 525 | { |
513 | unsigned long flags; | 526 | unsigned long flags; |
514 | int i; | 527 | int i; |
515 | unsigned int *pointer_read = &ipoctal->pointer_read[channel]; | 528 | unsigned int *pointer_read = &channel->pointer_read; |
516 | 529 | ||
517 | /* Copy the bytes from the user buffer to the internal one */ | 530 | /* Copy the bytes from the user buffer to the internal one */ |
518 | for (i = 0; i < count; i++) { | 531 | for (i = 0; i < count; i++) { |
519 | if (i <= (PAGE_SIZE - ipoctal->nb_bytes[channel])) { | 532 | if (i <= (PAGE_SIZE - channel->nb_bytes)) { |
520 | spin_lock_irqsave(&ipoctal->lock[channel], flags); | 533 | spin_lock_irqsave(&channel->lock, flags); |
521 | ipoctal->tty_port[channel].xmit_buf[*pointer_read] = buf[i]; | 534 | channel->tty_port.xmit_buf[*pointer_read] = buf[i]; |
522 | *pointer_read = (*pointer_read + 1) % PAGE_SIZE; | 535 | *pointer_read = (*pointer_read + 1) % PAGE_SIZE; |
523 | ipoctal->nb_bytes[channel]++; | 536 | channel->nb_bytes++; |
524 | spin_unlock_irqrestore(&ipoctal->lock[channel], flags); | 537 | spin_unlock_irqrestore(&channel->lock, flags); |
525 | } else { | 538 | } else { |
526 | break; | 539 | break; |
527 | } | 540 | } |
@@ -529,21 +542,22 @@ static inline int ipoctal_copy_write_buffer(struct ipoctal *ipoctal, | |||
529 | return i; | 542 | return i; |
530 | } | 543 | } |
531 | 544 | ||
532 | static int ipoctal_write(struct ipoctal *ipoctal, unsigned int channel, | 545 | static int ipoctal_write(struct ipoctal *ipoctal, unsigned int ichannel, |
533 | const unsigned char *buf, int count) | 546 | const unsigned char *buf, int count) |
534 | { | 547 | { |
535 | ipoctal->nb_bytes[channel] = 0; | 548 | struct ipoctal_channel *channel = &ipoctal->channel[ichannel]; |
536 | ipoctal->count_wr[channel] = 0; | 549 | channel->nb_bytes = 0; |
550 | channel->count_wr = 0; | ||
537 | 551 | ||
538 | ipoctal_copy_write_buffer(ipoctal, channel, buf, count); | 552 | ipoctal_copy_write_buffer(channel, buf, count); |
539 | 553 | ||
540 | /* As the IP-OCTAL 485 only supports half duplex, do it manually */ | 554 | /* As the IP-OCTAL 485 only supports half duplex, do it manually */ |
541 | if (ipoctal->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { | 555 | if (ipoctal->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { |
542 | ipoctal_write_io_reg(ipoctal, | 556 | ipoctal_write_io_reg(ipoctal, |
543 | &ipoctal->chan_regs[channel].w.cr, | 557 | &channel->regs->w.cr, |
544 | CR_DISABLE_RX); | 558 | CR_DISABLE_RX); |
545 | ipoctal_write_cr_cmd(ipoctal, | 559 | ipoctal_write_cr_cmd(ipoctal, |
546 | &ipoctal->chan_regs[channel].w.cr, | 560 | &channel->regs->w.cr, |
547 | CR_CMD_ASSERT_RTSN); | 561 | CR_CMD_ASSERT_RTSN); |
548 | } | 562 | } |
549 | 563 | ||
@@ -552,40 +566,39 @@ static int ipoctal_write(struct ipoctal *ipoctal, unsigned int channel, | |||
552 | * operations | 566 | * operations |
553 | */ | 567 | */ |
554 | ipoctal_write_io_reg(ipoctal, | 568 | ipoctal_write_io_reg(ipoctal, |
555 | &ipoctal->chan_regs[channel].w.cr, | 569 | &channel->regs->w.cr, |
556 | CR_ENABLE_TX); | 570 | CR_ENABLE_TX); |
557 | wait_event_interruptible(ipoctal->queue[channel], ipoctal->write); | 571 | wait_event_interruptible(channel->queue, ipoctal->write); |
558 | ipoctal_write_io_reg(ipoctal, | 572 | ipoctal_write_io_reg(ipoctal, |
559 | &ipoctal->chan_regs[channel].w.cr, | 573 | &channel->regs->w.cr, |
560 | CR_DISABLE_TX); | 574 | CR_DISABLE_TX); |
561 | 575 | ||
562 | ipoctal->write = 0; | 576 | ipoctal->write = 0; |
563 | return ipoctal->count_wr[channel]; | 577 | return channel->count_wr; |
564 | } | 578 | } |
565 | 579 | ||
566 | static int ipoctal_write_tty(struct tty_struct *tty, | 580 | static int ipoctal_write_tty(struct tty_struct *tty, |
567 | const unsigned char *buf, int count) | 581 | const unsigned char *buf, int count) |
568 | { | 582 | { |
569 | unsigned int channel = tty->index; | ||
570 | struct ipoctal *ipoctal = tty->driver_data; | 583 | struct ipoctal *ipoctal = tty->driver_data; |
571 | 584 | ||
572 | return ipoctal_write(ipoctal, channel, buf, count); | 585 | return ipoctal_write(ipoctal, tty->index, buf, count); |
573 | } | 586 | } |
574 | 587 | ||
575 | static int ipoctal_write_room(struct tty_struct *tty) | 588 | static int ipoctal_write_room(struct tty_struct *tty) |
576 | { | 589 | { |
577 | int channel = tty->index; | ||
578 | struct ipoctal *ipoctal = tty->driver_data; | 590 | struct ipoctal *ipoctal = tty->driver_data; |
591 | struct ipoctal_channel *channel = &ipoctal->channel[tty->index]; | ||
579 | 592 | ||
580 | return PAGE_SIZE - ipoctal->nb_bytes[channel]; | 593 | return PAGE_SIZE - channel->nb_bytes; |
581 | } | 594 | } |
582 | 595 | ||
583 | static int ipoctal_chars_in_buffer(struct tty_struct *tty) | 596 | static int ipoctal_chars_in_buffer(struct tty_struct *tty) |
584 | { | 597 | { |
585 | int channel = tty->index; | ||
586 | struct ipoctal *ipoctal = tty->driver_data; | 598 | struct ipoctal *ipoctal = tty->driver_data; |
599 | struct ipoctal_channel *channel = &ipoctal->channel[tty->index]; | ||
587 | 600 | ||
588 | return ipoctal->nb_bytes[channel]; | 601 | return channel->nb_bytes; |
589 | } | 602 | } |
590 | 603 | ||
591 | static void ipoctal_set_termios(struct tty_struct *tty, | 604 | static void ipoctal_set_termios(struct tty_struct *tty, |
@@ -595,22 +608,22 @@ static void ipoctal_set_termios(struct tty_struct *tty, | |||
595 | unsigned char mr1 = 0; | 608 | unsigned char mr1 = 0; |
596 | unsigned char mr2 = 0; | 609 | unsigned char mr2 = 0; |
597 | unsigned char csr = 0; | 610 | unsigned char csr = 0; |
598 | unsigned int channel = tty->index; | ||
599 | struct ipoctal *ipoctal = tty->driver_data; | 611 | struct ipoctal *ipoctal = tty->driver_data; |
612 | struct ipoctal_channel *channel = &ipoctal->channel[tty->index]; | ||
600 | speed_t baud; | 613 | speed_t baud; |
601 | 614 | ||
602 | cflag = tty->termios->c_cflag; | 615 | cflag = tty->termios->c_cflag; |
603 | 616 | ||
604 | /* Disable and reset everything before change the setup */ | 617 | /* Disable and reset everything before change the setup */ |
605 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 618 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.cr, |
606 | CR_DISABLE_RX | CR_DISABLE_TX); | 619 | CR_DISABLE_RX | CR_DISABLE_TX); |
607 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 620 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
608 | CR_CMD_RESET_RX); | 621 | CR_CMD_RESET_RX); |
609 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 622 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
610 | CR_CMD_RESET_TX); | 623 | CR_CMD_RESET_TX); |
611 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 624 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
612 | CR_CMD_RESET_ERR_STATUS); | 625 | CR_CMD_RESET_ERR_STATUS); |
613 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 626 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
614 | CR_CMD_RESET_MR); | 627 | CR_CMD_RESET_MR); |
615 | 628 | ||
616 | /* Set Bits per chars */ | 629 | /* Set Bits per chars */ |
@@ -724,45 +737,45 @@ static void ipoctal_set_termios(struct tty_struct *tty, | |||
724 | mr1 |= MR1_RxINT_RxRDY; | 737 | mr1 |= MR1_RxINT_RxRDY; |
725 | 738 | ||
726 | /* Write the control registers */ | 739 | /* Write the control registers */ |
727 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].w.mr, mr1); | 740 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.mr, mr1); |
728 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].w.mr, mr2); | 741 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.mr, mr2); |
729 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].w.csr, csr); | 742 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.csr, csr); |
730 | 743 | ||
731 | /* Enable again the RX */ | 744 | /* Enable again the RX */ |
732 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 745 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.cr, |
733 | CR_ENABLE_RX); | 746 | CR_ENABLE_RX); |
734 | } | 747 | } |
735 | 748 | ||
736 | static void ipoctal_hangup(struct tty_struct *tty) | 749 | static void ipoctal_hangup(struct tty_struct *tty) |
737 | { | 750 | { |
738 | unsigned long flags; | 751 | unsigned long flags; |
739 | int channel = tty->index; | ||
740 | struct ipoctal *ipoctal = tty->driver_data; | 752 | struct ipoctal *ipoctal = tty->driver_data; |
753 | struct ipoctal_channel *channel = &ipoctal->channel[tty->index]; | ||
741 | 754 | ||
742 | if (ipoctal == NULL) | 755 | if (ipoctal == NULL) |
743 | return; | 756 | return; |
744 | 757 | ||
745 | spin_lock_irqsave(&ipoctal->lock[channel], flags); | 758 | spin_lock_irqsave(&channel->lock, flags); |
746 | ipoctal->nb_bytes[channel] = 0; | 759 | channel->nb_bytes = 0; |
747 | ipoctal->pointer_read[channel] = 0; | 760 | channel->pointer_read = 0; |
748 | ipoctal->pointer_write[channel] = 0; | 761 | channel->pointer_write = 0; |
749 | spin_unlock_irqrestore(&ipoctal->lock[channel], flags); | 762 | spin_unlock_irqrestore(&channel->lock, flags); |
750 | 763 | ||
751 | tty_port_hangup(&ipoctal->tty_port[channel]); | 764 | tty_port_hangup(&channel->tty_port); |
752 | 765 | ||
753 | ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 766 | ipoctal_write_io_reg(ipoctal, &channel->regs->w.cr, |
754 | CR_DISABLE_RX | CR_DISABLE_TX); | 767 | CR_DISABLE_RX | CR_DISABLE_TX); |
755 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 768 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
756 | CR_CMD_RESET_RX); | 769 | CR_CMD_RESET_RX); |
757 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 770 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
758 | CR_CMD_RESET_TX); | 771 | CR_CMD_RESET_TX); |
759 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 772 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
760 | CR_CMD_RESET_ERR_STATUS); | 773 | CR_CMD_RESET_ERR_STATUS); |
761 | ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[channel].w.cr, | 774 | ipoctal_write_cr_cmd(ipoctal, &channel->regs->w.cr, |
762 | CR_CMD_RESET_MR); | 775 | CR_CMD_RESET_MR); |
763 | 776 | ||
764 | clear_bit(ASYNCB_INITIALIZED, &ipoctal->tty_port[channel].flags); | 777 | clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags); |
765 | wake_up_interruptible(&ipoctal->tty_port[channel].open_wait); | 778 | wake_up_interruptible(&channel->tty_port.open_wait); |
766 | } | 779 | } |
767 | 780 | ||
768 | static const struct tty_operations ipoctal_fops = { | 781 | static const struct tty_operations ipoctal_fops = { |
@@ -806,8 +819,9 @@ static void __ipoctal_remove(struct ipoctal *ipoctal) | |||
806 | ipoctal->dev->bus->ops->free_irq(ipoctal->dev); | 819 | ipoctal->dev->bus->ops->free_irq(ipoctal->dev); |
807 | 820 | ||
808 | for (i = 0; i < NR_CHANNELS; i++) { | 821 | for (i = 0; i < NR_CHANNELS; i++) { |
822 | struct ipoctal_channel *channel = &ipoctal->channel[i]; | ||
809 | tty_unregister_device(ipoctal->tty_drv, i); | 823 | tty_unregister_device(ipoctal->tty_drv, i); |
810 | tty_port_free_xmit_buf(&ipoctal->tty_port[i]); | 824 | tty_port_free_xmit_buf(&channel->tty_port); |
811 | } | 825 | } |
812 | 826 | ||
813 | tty_unregister_driver(ipoctal->tty_drv); | 827 | tty_unregister_driver(ipoctal->tty_drv); |