aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/cyclades.c302
1 files changed, 108 insertions, 194 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e2f731b70763..9e0cd7020aef 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2172,199 +2172,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
2172 * ------------------------------------------------------------ 2172 * ------------------------------------------------------------
2173 */ 2173 */
2174 2174
2175static int
2176block_til_ready(struct tty_struct *tty, struct file *filp,
2177 struct cyclades_port *info)
2178{
2179 DECLARE_WAITQUEUE(wait, current);
2180 struct cyclades_card *cinfo;
2181 unsigned long flags;
2182 int chip, channel, index;
2183 int retval;
2184 void __iomem *base_addr;
2185
2186 cinfo = info->card;
2187 channel = info->line - cinfo->first_line;
2188
2189 /*
2190 * If the device is in the middle of being closed, then block
2191 * until it's done, and then try again.
2192 */
2193 if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
2194 wait_event_interruptible(info->port.close_wait,
2195 !(info->port.flags & ASYNC_CLOSING));
2196 return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
2197 }
2198
2199 /*
2200 * If non-blocking mode is set, then make the check up front
2201 * and then exit.
2202 */
2203 if ((filp->f_flags & O_NONBLOCK) ||
2204 (tty->flags & (1 << TTY_IO_ERROR))) {
2205 info->port.flags |= ASYNC_NORMAL_ACTIVE;
2206 return 0;
2207 }
2208
2209 /*
2210 * Block waiting for the carrier detect and the line to become
2211 * free (i.e., not in use by the callout). While we are in
2212 * this loop, info->port.count is dropped by one, so that
2213 * cy_close() knows when to free things. We restore it upon
2214 * exit, either normal or abnormal.
2215 */
2216 retval = 0;
2217 add_wait_queue(&info->port.open_wait, &wait);
2218#ifdef CY_DEBUG_OPEN
2219 printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, "
2220 "count = %d\n", info->line, info->port.count);
2221#endif
2222 spin_lock_irqsave(&cinfo->card_lock, flags);
2223 if (!tty_hung_up_p(filp))
2224 info->port.count--;
2225 spin_unlock_irqrestore(&cinfo->card_lock, flags);
2226#ifdef CY_DEBUG_COUNT
2227 printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to "
2228 "%d\n", current->pid, info->port.count);
2229#endif
2230 info->port.blocked_open++;
2231
2232 if (!cy_is_Z(cinfo)) {
2233 chip = channel >> 2;
2234 channel &= 0x03;
2235 index = cinfo->bus_index;
2236 base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
2237
2238 while (1) {
2239 spin_lock_irqsave(&cinfo->card_lock, flags);
2240 if ((tty->termios->c_cflag & CBAUD)) {
2241 cy_writeb(base_addr + (CyCAR << index),
2242 (u_char) channel);
2243 cy_writeb(base_addr + (CyMSVR1 << index),
2244 CyRTS);
2245 cy_writeb(base_addr + (CyMSVR2 << index),
2246 CyDTR);
2247#ifdef CY_DEBUG_DTR
2248 printk(KERN_DEBUG "cyc:block_til_ready raising "
2249 "DTR\n");
2250 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
2251 readb(base_addr + (CyMSVR1 << index)),
2252 readb(base_addr + (CyMSVR2 << index)));
2253#endif
2254 }
2255 spin_unlock_irqrestore(&cinfo->card_lock, flags);
2256
2257 set_current_state(TASK_INTERRUPTIBLE);
2258 if (tty_hung_up_p(filp) ||
2259 !(info->port.flags & ASYNC_INITIALIZED)) {
2260 retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
2261 -EAGAIN : -ERESTARTSYS);
2262 break;
2263 }
2264
2265 spin_lock_irqsave(&cinfo->card_lock, flags);
2266 cy_writeb(base_addr + (CyCAR << index),
2267 (u_char) channel);
2268 if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
2269 (readb(base_addr +
2270 (CyMSVR1 << index)) & CyDCD))) {
2271 spin_unlock_irqrestore(&cinfo->card_lock, flags);
2272 break;
2273 }
2274 spin_unlock_irqrestore(&cinfo->card_lock, flags);
2275
2276 if (signal_pending(current)) {
2277 retval = -ERESTARTSYS;
2278 break;
2279 }
2280#ifdef CY_DEBUG_OPEN
2281 printk(KERN_DEBUG "cyc block_til_ready blocking: "
2282 "ttyC%d, count = %d\n",
2283 info->line, info->port.count);
2284#endif
2285 schedule();
2286 }
2287 } else {
2288 struct FIRM_ID __iomem *firm_id;
2289 struct ZFW_CTRL __iomem *zfw_ctrl;
2290 struct BOARD_CTRL __iomem *board_ctrl;
2291 struct CH_CTRL __iomem *ch_ctrl;
2292
2293 base_addr = cinfo->base_addr;
2294 firm_id = base_addr + ID_ADDRESS;
2295 if (!cyz_is_loaded(cinfo)) {
2296 __set_current_state(TASK_RUNNING);
2297 remove_wait_queue(&info->port.open_wait, &wait);
2298 return -EINVAL;
2299 }
2300
2301 zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)
2302 & 0xfffff);
2303 board_ctrl = &zfw_ctrl->board_ctrl;
2304 ch_ctrl = zfw_ctrl->ch_ctrl;
2305
2306 while (1) {
2307 if ((tty->termios->c_cflag & CBAUD)) {
2308 cy_writel(&ch_ctrl[channel].rs_control,
2309 readl(&ch_ctrl[channel].rs_control) |
2310 C_RS_RTS | C_RS_DTR);
2311 retval = cyz_issue_cmd(cinfo,
2312 channel, C_CM_IOCTLM, 0L);
2313 if (retval != 0) {
2314 printk(KERN_ERR "cyc:block_til_ready "
2315 "retval on ttyC%d was %x\n",
2316 info->line, retval);
2317 }
2318#ifdef CY_DEBUG_DTR
2319 printk(KERN_DEBUG "cyc:block_til_ready raising "
2320 "Z DTR\n");
2321#endif
2322 }
2323
2324 set_current_state(TASK_INTERRUPTIBLE);
2325 if (tty_hung_up_p(filp) ||
2326 !(info->port.flags & ASYNC_INITIALIZED)) {
2327 retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
2328 -EAGAIN : -ERESTARTSYS);
2329 break;
2330 }
2331 if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
2332 (readl(&ch_ctrl[channel].rs_status) &
2333 C_RS_DCD))) {
2334 break;
2335 }
2336 if (signal_pending(current)) {
2337 retval = -ERESTARTSYS;
2338 break;
2339 }
2340#ifdef CY_DEBUG_OPEN
2341 printk(KERN_DEBUG "cyc block_til_ready blocking: "
2342 "ttyC%d, count = %d\n",
2343 info->line, info->port.count);
2344#endif
2345 schedule();
2346 }
2347 }
2348 __set_current_state(TASK_RUNNING);
2349 remove_wait_queue(&info->port.open_wait, &wait);
2350 if (!tty_hung_up_p(filp)) {
2351 info->port.count++;
2352#ifdef CY_DEBUG_COUNT
2353 printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing "
2354 "count to %d\n", current->pid, info->port.count);
2355#endif
2356 }
2357 info->port.blocked_open--;
2358#ifdef CY_DEBUG_OPEN
2359 printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, "
2360 "count = %d\n", info->line, info->port.count);
2361#endif
2362 if (retval)
2363 return retval;
2364 info->port.flags |= ASYNC_NORMAL_ACTIVE;