/* * This routine sends a break character out the serial port. */ static void send_break( struct async_struct * info, int duration) { mach_port_t device_port = info->device_port; current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + duration; cli(); device_set_status(device_port, TTY_SET_BREAK, 0, 0); schedule(); device_set_status(device_port, TTY_CLEAR_BREAK, 0, 0); sti(); }
int set_promisc (char *dev_name, mach_port_t ether_port, int is_promisc) { #ifndef NET_FLAGS #define NET_FLAGS (('n'<<16) + 4) #endif int flags; int ret; size_t count; debug ("set_promisc is called, is_promisc: %d\n", is_promisc); count = 1; ret = device_get_status (ether_port, NET_FLAGS, (dev_status_t) &flags, &count); if (ret) { error (0, ret, "device_get_status"); return -1; } if (is_promisc) flags |= IFF_PROMISC; else flags &= ~IFF_PROMISC; ret = device_set_status(ether_port, NET_FLAGS, (dev_status_t) &flags, 1); if (ret) { error (0, ret, "device_set_status"); return -1; } return 0; }
static void flush(struct printf_state *state) { int amt; int done = 0; if(!standalone) return ; while (done != state->index) { if (device_write_inband(console_port, 0, 0, state->buf+done, state->index-done, &amt) != KERN_SUCCESS) done += state->index-done; else done += amt; } #ifdef TTY_DRAIN { int word; /* flush console output */ (void) device_set_status(console_port, TTY_DRAIN, &word, 0); } #endif /* TTY_DRAIN */ state->index = 0; }
int machine_disk_revalidate( kdev_t dev, mach_port_t device_port) { kern_return_t kr; int count; switch ((int) MAJOR(dev)) { case SCSI_DISK_MAJOR: case HD_MAJOR: case FLOPPY_MAJOR: count = 0; kr = device_set_status(device_port, OSFMACH3_V_REMOUNT, &count, count); if (kr != D_SUCCESS) { MACH3_DEBUG(2, kr, ("machine_disk_revalidate(%s): " "device_get_status(0x%x, V_REMOUNT)", kdevname(dev), device_port)); return -EINVAL; } break; default: return -EINVAL; } return 0; }
static int set_modem_info(struct async_struct * info, unsigned int cmd, unsigned int *value) { int error; unsigned int arg; long result = 0, cur; mach_msg_type_number_t count; kern_return_t kr; error = verify_area(VERIFY_READ, value, sizeof(int)); if (error) return error; arg = get_user(value); if (arg & TIOCM_RTS) result |= TM_RTS; if (arg & TIOCM_DTR) result |= TM_DTR; count = TTY_MODEM_COUNT; kr = device_get_status(info->device_port, TTY_MODEM, (dev_status_t)&cur, &count); if (kr != D_SUCCESS) return -EIO; switch (cmd) { case TIOCMBIS: cur = cur | result; break; case TIOCMBIC: cur = cur & ~result; break; case TIOCMSET: cur = result; break; default: return -EINVAL; } kr = device_set_status(info->device_port, TTY_MODEM, (dev_status_t)&cur, TTY_MODEM_COUNT); if (kr != D_SUCCESS) return -EIO; return 0; }
/* Set device flags (e.g. promiscuous) */ static int ethernet_change_flags (struct device *dev, short flags) { error_t err = 0; #ifdef NET_FLAGS int status = flags; struct ether_device *edev = (struct ether_device *) dev->priv; err = device_set_status (edev->ether_port, NET_FLAGS, &status, 1); if (err == D_INVALID_OPERATION) /* Not supported, ignore. */ err = 0; #endif return err; }
void awacs_mksound(unsigned int hz, unsigned int ticks) { kern_return_t kr; int speed; int count; if (_awacs_busy) return; /* 'Sound' driver using device */ if (_awacs_device_port == (mach_port_t)NULL) { kr = device_open( device_server_port, MACH_PORT_NULL, D_READ | D_WRITE, server_security_token, awacs_dev_name, &_awacs_device_port ); if ( kr != KERN_SUCCESS ) { /* Ignore errors, just 'bag' ringing the bell */ return; } device_reply_register( &_awacs_reply_port, (char *) &_awacs_param, (dev_reply_t) _awacs_read_reply, (dev_reply_t) _awacs_write_reply ); } /* Set port speed */ speed = KBEEP_SPEED; count = KBEEP_BUFSIZE; kr = device_set_status(_awacs_device_port, AWACS_DEVCMD_RATE, &speed, 1); if (kr != D_SUCCESS) { return; } /* Write the 'bell' data */ kr = serv_device_write_async((mach_port_t) _awacs_device_port, (mach_port_t) _awacs_reply_port, (dev_mode_t) D_WRITE, (recnum_t) 0, (caddr_t) kbeep_buf, (mach_msg_type_number_t) count, (boolean_t) FALSE); }
kern_return_t machine_disk_write_absolute( kdev_t dev, mach_port_t device_port, unsigned long recnum, char *data, unsigned long size) { kern_return_t kr; mach_msg_type_number_t count; int abs_sec; /* absolute sector to be written */ abs_sec = recnum; while (size > 0) { #ifdef GENDISK_DEBUG if (gendisk_debug) { printk("machine_disk_write_absolute(dev=%s, " "recnum=0x%lx, size=0x%lx): WRABS(0x%x,0x%x)\n", kdevname(dev), recnum, size, abs_sec, OSFMACH3_DEV_BSIZE); } #endif /* GENDISK_DEBUG */ /* * Tell the micro-kernel which sector to write. */ count = 1; kr = device_set_status(device_port, OSFMACH3_V_ABS, (dev_status_t) &abs_sec, count); if (kr != KERN_SUCCESS) { MACH3_DEBUG(1, kr, ("machine_disk_write_absolute(%s): " "device_set_status(0x%x, V_ABS, 0x%x)", kdevname(dev), device_port, abs_sec)); return kr; } /* * Write the sector now. */ count = OSFMACH3_DEV_BSIZE / sizeof (int); server_thread_blocking(FALSE); kr = device_set_status(device_port, OSFMACH3_V_WRABS, (dev_status_t) data, count); server_thread_unblocking(FALSE); if (kr != D_SUCCESS) { if (kr != D_INVALID_RECNUM && kr != D_INVALID_SIZE) { MACH3_DEBUG(1, kr, ("machine_disk_write_absolute(%s):" " device_set_status(0x%x, " "V_WRABS(0x%x,%d)", kdevname(dev), device_port, abs_sec, count)); } return kr; } if ((count * sizeof (int)) > size) break; size -= count * sizeof (int); data += count * sizeof (int); abs_sec++; } return D_SUCCESS; }
/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ static void change_speed(struct async_struct *info) { unsigned cflag; int line; mach_port_t device_port; kern_return_t kr; struct tty_status ttstat; mach_msg_type_number_t ttstat_count; if (!info->tty || !info->tty->termios) return; cflag = info->tty->termios->c_cflag; line = MINOR(info->tty->device) - info->tty->driver.minor_start; device_port = info->device_port; ttstat_count = TTY_STATUS_COUNT; if (device_port != MACH_PORT_NULL) { kr = device_get_status(device_port, TTY_STATUS_NEW, (dev_status_t) &ttstat, &ttstat_count); if (kr != D_SUCCESS) { MACH3_DEBUG(1, kr, ("change_speed(dev 0x%x): " "device_get_status(TTY_STATUS_NEW)", info->tty->device)); return; } } /* Mach break handling is obsolete with "new" out-of-band. */ ttstat.tt_breakc = 0; ttstat.tt_flags &= ~(TF_ODDP | TF_EVENP | TF_LITOUT | TF_NOHANG | TF_8BIT | TF_READ | TF_HUPCLS | TF_OUT_OF_BAND | TF_INPCK | TF_CRTSCTS); ttstat.tt_flags |= TF_OUT_OF_BAND; /* we always want OUT_OF_BAND */ /* Convert from POSIX to MACH speed */ if ((cflag & CBAUD) < (sizeof(baud_table)/sizeof(baud_table[0]))) ttstat.tt_ispeed = ttstat.tt_ospeed = baud_table[cflag & CBAUD]; else /* Largest possible baud rate (for the moment) */ ttstat.tt_ispeed = ttstat.tt_ospeed = 230400; if (cflag & CRTSCTS) { info->flags |= ASYNC_CTS_FLOW; } else info->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) info->flags &= ~ASYNC_CHECK_CD; else { info->flags |= ASYNC_CHECK_CD; } #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) if (I_INPCK(info->tty)) info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) info->read_status_mask |= UART_LSR_BI; info->ignore_status_mask = 0; if (I_IGNPAR(info->tty)) { info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; info->read_status_mask |= UART_LSR_PE | UART_LSR_FE; } if (I_IGNBRK(info->tty)) { info->ignore_status_mask |= UART_LSR_BI; info->read_status_mask |= UART_LSR_BI; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (I_IGNPAR(info->tty)) { info->ignore_status_mask |= UART_LSR_OE; info->read_status_mask |= UART_LSR_OE; } } if (cflag & PARENB) { ttstat.tt_flags |= TF_INPCK; ttstat.tt_flags |= (cflag & PARODD) ? TF_ODDP : TF_EVENP; } if ((cflag & CSIZE) != CS7) { /* assume CS8 */ ttstat.tt_flags |= TF_LITOUT | TF_8BIT; } if (cflag & CLOCAL) ttstat.tt_flags |= TF_NOHANG; if (cflag & CREAD) ttstat.tt_flags |= TF_READ; if (cflag & HUPCL) ttstat.tt_flags |= TF_HUPCLS; if (cflag & CRTSCTS) ttstat.tt_flags |= TF_CRTSCTS; if (device_port != MACH_PORT_NULL) { kr = device_set_status(device_port, TTY_STATUS_NEW, (dev_status_t) &ttstat, ttstat_count); if (kr != D_SUCCESS) { MACH3_DEBUG(1, kr, ("change_speed(dev 0x%x): " "device_set_status(TTY_STATUS_NEW)", info->tty->device)); } } }
/* * This routine is called whenever a serial port is opened. It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain. It also performs the serial-specific * initialization for the tty structure. */ int rs_open(struct tty_struct *tty, struct file * filp) { struct async_struct *info; int retval, line; line = MINOR(tty->device) - tty->driver.minor_start; if ((line < 0) || (line >= NR_PORTS)) return -ENODEV; info = rs_table + line; if (serial_paranoia_check(info, tty->device, "rs_open")) return -ENODEV; #ifdef SERIAL_DEBUG_OPEN printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, info->count); #endif if (!(info->flags & ASYNC_INITIALIZED)) { char device_name[25]; mach_port_t device_port; dev_mode_t device_mode; kern_return_t kr; int word, count; sprintf(device_name, "com%d", line); device_mode = D_READ | D_WRITE; kr = device_open(device_server_port, MACH_PORT_NULL, device_mode, server_security_token, device_name, &device_port); if (kr != D_SUCCESS) { if (kr != D_NO_SUCH_DEVICE) { MACH3_DEBUG(2, kr, ("rs_open(dev 0x%x): " "device_open(\"%s\")", tty->device, device_name)); } return -ENODEV; } info->flags &= ~ASYNC_DCD_PRESENT; count = TTY_MODEM_COUNT; kr = device_get_status(device_port, TTY_MODEM, &word, &count); if (kr == D_SUCCESS && (word & TM_CAR) != 0) info->flags |= ASYNC_DCD_PRESENT; else info->flags &= ~ASYNC_DCD_PRESENT; /* Flush any garbage data which might be left over.. */ count = TTY_FLUSH_COUNT; word = D_READ|D_WRITE; kr = device_set_status(device_port, TTY_FLUSH, &word, count); info->device_port = device_port; tty->flip.char_buf_ptr = tty->flip.char_buf; tty->flip.flag_buf_ptr = tty->flip.flag_buf; tty->flip.count = 0; /* Now register a few asynchronous routines.. */ device_reply_register(&info->reply_port, (char *) info, serial_read_reply, serial_write_reply); } ASSERT(MACH_PORT_VALID(info->device_port)); info->count++; tty->driver_data = info; info->tty = tty; /* * Start up serial port */ retval = startup(info); if (retval) return retval; if (info->count == 1) server_thread_start(serial_read_thread, (void *) line); retval = block_til_ready(tty, filp, info); if (retval) { #ifdef SERIAL_DEBUG_OPEN printk("rs_open returning after block_til_ready with %d\n", retval); #endif return retval; } if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { if (tty->driver.subtype == SERIAL_TYPE_NORMAL) *tty->termios = info->normal_termios; else *tty->termios = info->callout_termios; change_speed(info); } info->session = current->session; info->pgrp = current->pgrp; #ifdef SERIAL_DEBUG_OPEN printk("rs_open ttys%d successful...", info->line); #endif return 0; }