<!-- $FreeBSD$ -->
<!-- The FreeBSD Documentation Project -->
<!-- Translate into Chinese by ijliao@dragon2.net -->
<!-- English Version: 1.4 -->

  <sect>
    <heading>Serial 通訊<label id="serial"></heading>

    <p>這一章主要是在討論 FreeBSD 上有關 serial 通訊的問題。有關 PPP 以及
      SLIP 的問題是放在 <ref id="networking" name="網路"> 這一節。

    <sect1>
      <heading>我要怎麼知道 FreeBSD 是不是有抓到我的 serial port？</heading>

      <p>當 FreeBSD 開機的時候，它會根據您在 kernel 中的設定來偵測您的
        serial port。您可以在這些訊息出現的時候檢查，也可以在系統開機之後用
        下面的指令來觀察：

      <verb>
        dmesg | grep sio
      </verb>

      <p>這裡有一些輸出的範例：

      <verb>
        sio0 at 0x3f8-0x3ff irq 4 on isa
        sio0: type 16550A
        sio1 at 0x2f8-0x2ff irq 3 on isa
        sio1: type 16550A
      </verb>

      <p>這代表您有兩個 serial port。第一個 port 佔用 irq 4，port address 是
        <tt/0x3f8/ ，而且用的是 16550A 型的 UART 晶片。第二個 port 用的是同
        型的晶片，不過它佔用的是 irq 3 ，它的 port address 在 <tt/0x2f8/ 。
        內接式 modem 卡會被辨識成是 serial port -- 唯一的差別就是該 port 上
        總是接上 modem 而已。

      <p><tt/GENERIC/ kernel 支援兩個 serial port ，它們的設定值就如同上面的
        範例一樣。如果您系統上的設定不一樣，或者您另外接了內接式 modem 卡，
        或是您系統的實際 serial port 數比您在 kernel 設定中的還要多的話，您
        只要重新建立 kernel 就好了。詳情請看 <ref id="make-kernel"
        name="如何建立 kernel"> 。

    <sect1>
      <heading>我要怎麼知道 FreeBSD 是不是有抓到我的 modem 卡？</heading>

      <p>請看上一個問題。

    <sect1>
      <heading>我升級到 2.0.5 以後我的 <tt/tty0X/ 居然不見了！</heading>

      <p>不要緊張，它們已經被併到 <tt/ttydX/ 裝置下去了。不過您還是得到自己
        修改設定檔才能讓它們正常工作。

    <sect1>
      <heading>我要如何在 FreeBSD 下存取 seral ports？</heading>

      <p>第三個 serial port，<htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?sio" name="sio2"> (就是 DOS
        下的 COM3) ，以 dial-out 裝置來看是位於 <tt>/dev/cuaa2</tt> ，而以
        dial-in 裝置來看則是位於 <tt>/dev/ttyd2</tt> 。這兩個裝置有什麼不同
        呢？

      <p>您在 dial-in 時使用的是 <tt/ttydX/ 。當您用 block 模式開啟
        <tt>/dev/ttydX</tt> 時，會有一隻 process 在對應的 <tt/cuaaX/ 上等它
        變成 inactive ，然後一直等到 carrier detect line 變成 active 為止。
        當您開啟 <tt/cuaaX/ 裝置時，它會去確定目前 <tt/ttydX/ 裝置是不是正
        在使用 serial port。如果它可以用的話，它就會把 serial port 從
        <tt/ttydX/ 裝置手中搶過來。同樣的，<tt/cuaXX/ 裝置不會去管 carrier
        detect。有了這樣的設計，再加上一台會自動回應的 modem，您就可以令同
        一台 modem 可以被遠端使用者拿來登入，您自己也可以拿來 dialout，系統
        會自動檢查是否有衝突的現象。

    <sect1>
      <heading>我要如何啟動對 serial 多埠卡的支援？</heading>

      <p>同樣的，在 kernel 設定那一節有提到有關設定 kernel 的資訊。要設定一
        張 serial 多埠卡，您必需在您的 kernel 設定檔中為每一個 serial port
        都設一行 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?sio"
        name="sio"> 的設定。但是您只能在它們之中選一個來設定 irq 以及
        vector 。卡上的所有 port 會共享同一個 irq 。一般來說我們都把它設在最
        後一個 serial port 上。不要忘了指定 <tt/COM&lowbar;MULTIPORT/ 這個
        option 。

      <p>下面是一個把 AST 4-port 卡 設在 irq 7 的例子：

      <verb>
        options "COM_MULTIPORT"
        device sio4 at isa? port 0x2a0 tty flags 0x781
        device sio5 at isa? port 0x2a8 tty flags 0x781
        device sio6 at isa? port 0x2b0 tty flags 0x781
        device sio7 at isa? port 0x2b8 tty flags 0x781 irq 7 vector siointr
      </verb>

      <p>這裡的 flags 設定是指 master port 的 minor number 是 7
        (<tt/0x700/)，在偵測時做檢查 (<tt/0x080/)，以及所有的 port 共享一個
        irq (<tt/0x001/) 。

    <sect1>
      <heading>FreeBSD 可以控制多張 serial 多埠卡使用同一個 irq 嗎？</heading>

      <p>還沒支援。您必需為每張卡設定不同的 irq 。

    <sect1>
      <heading>我可以為 port 設定預設參數嗎？</heading>

      <p>通常您會想為您的應用程式開啟 <tt/ttydX/ (或是 <tt/cuaaX/) 裝置。當
        一個 process 開啟裝置以後，它會有一組預設的終端機 I/O 設定。您可以用
        下面這個指令來觀察這些設定

      <verb>
        stty -a -f /dev/ttyd1
      </verb>

      <p>當您改變了某個裝置的設定後，這些設定會一直作用，直到這個裝置被關閉
        了為止。當它被重開啟後，又回到原先的預設值了。如果想要改變預設值，您
        可以開啟並修改 ``初始狀態'' 裝置的設定。舉例來說，如果您想改變 ttyd5
        的預設值，把 <tt/CLOCAL/ 模式打開，8 bits，並且使用
        <tt>XON/XOFF</tt> 流量控制，您可以這樣做：

      <verb>
        stty -f /dev/ttyid5 clocal cs8 ixon ixoff
      </verb>

      <p>您可以在 <tt>/etc/rc.serial</tt> 裡做這樣的設定。現在每一個開啟
        <tt/ttyd5/ 的應用程式都會預設使用這些設定了。您依然可以用同樣的方法
        去改變這些設定。

      <p>您也可以藉由設定 ``鎖定狀態'' 裝置來防止其他應用程式去更動這些設定
        。舉例來說，想要把 <tt/ttyd5/ 的速度鎖定在 57600 bps，您要這樣做

      <verb>
        stty -f /dev/ttyld5 57600
      </verb>

      <p>這樣一來，每一個開啟 <tt/ttyd5/ 的應用程式都只能使用 57600 bps 的速
        度了。

      <p>當然，您必需確定您的初始狀態以及鎖定狀態的裝置只能被 <tt/root/ 寫入
        。<htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?MAKEDEV"
        name="MAKEDEV"> 這個 script 並 <bf/不會/ 在建立這些裝置時自動幫您設
        定好。

    <sect1>
      <heading>我要怎樣才能讓 modem 接受 dialup 登入呢？</heading>

      <p>您是不是想當 ISP？首先，您要有一部以上可以自動接聽的 modem。您的
        modem 必須要有 carrier-detect 的功能。它也要能夠在 data terminal
        ready (<tt/DTR/) 由開轉為關時重新設定自己。它或許也要能夠使用
        <tt>RTS/CTS</tt> 流量控制或是不做任何流量控制。最後，它必須能夠在電
        腦和它自己的傳輸中使用定速，但是在它和遠端 modem 的連線方面則要有協
        商傳輸速度的能力。

      <p>對 Hayes 指令集相容 modem 來說，下面的指令會把上一段所講的全部設好
        並存在非揮發性記憶體中：

      <verb>
        AT &amp;C1 &amp;D3 &amp;K3 &amp;Q6 S0=1 &amp;W
      </verb>

      <p>看看下面的 <ref id="direct-at" name="傳送 AT 指令集"> 這一節可以得
        更多有關如何不利用 MS-DOS 終端程式來做這些設定的資料。

      <p>接下來，在 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?ttys"
        name="/etc/ttys"> 為您的 modem 做設定。列在這個檔案中的是所有系統會
        待 login 的 ports 。像下面這樣加入一行：

      <verb>
        ttyd1 "/usr/libexec/getty std.57600" dialup on insecure
      </verb>

      <p>這一行指令第二個 serial port (<tt>/dev/ttyd1</tt>) 是一個以 57600
        bps 速度在傳輸的 modem，並且不做同位檢查 (<tt/std.57600/ 是在
        <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?gettytab"
        name="/etc/gettytab"> 檔裡指定的) 。這個 port 的終端機型態是
        ``dialup'' 。這個 port 設成 ``on'' 而且是 ``insecure'' 的 --- 意思是
        root 不能從這裡連線進來。您必需為每個 dialin port 都做類似
        <tt/ttydX/ 的設定。

      <p>通常我們會用 ``dialup'' 來做為終端機型態。如果使用者登入時的啟始型
        態是 dialup 的話，很多使用者都會在他們的 .profile 或是 .login 檔中設
        定他們真正的終端機型態。上面的例子中我們舉的是 insecure 的例子。如果
        您想要在這個 port 變成 root 的話，您必須用一般使用者的身份登入，然後
        ``<htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?su" name="su">''
        成 <tt/root/ 。如果您用的是 ``secure'' 的話，則 <tt/root/ 可以直接登
        入。

      <p>在對 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?ttys"
        name="/etc/ttys"> 做過修改之後，您必須送一個 hangup 或是 <tt/HUP/
        的 signal 給 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?init"
        name="init"> process：

      <verb>
        kill -HUP 1
      </verb>

      <p>這樣會強迫 init process 去重讀 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?ttys" name="/etc/ttys"> 。
        然後 init process 就會在所有的 ``on'' port 上重新啟動 getty
        process 。您可以用下列指令來檢查您的 port 是不是可以 login 了

      <verb>
        ps -ax | grep '[t]tyd1'
      </verb>

      <p>您會見到類似這樣的結果：

      <verb>
        747 ??  I      0:00.04 /usr/libexec/getty std.57600 ttyd1
      </verb>

    <sect1>
      <heading>我要怎麼把 dumb terminal 連上 FreeBSD？</heading>

      <p>如果您要把別的電腦當成是 FreeBSD 的終端機的話，您只需要在兩者的
        serial port 之間牽一條 null modem 排線即可。如果您有一個真的終端機
        的話，看看它的指令集吧。

      <p>然後，像上一個問題一樣修改
        <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?ttys"
        name="/etc/ttys"> 。舉例來說，如果您把一個 WYSE-50 終端機接在第五個
        serial port 上的話，就要用這樣的設定：

      <verb>
        ttyd4 "/usr/libexec/getty std.38400" wyse50 on secure
      </verb>

      <p>這個例子示範的是 <tt>/dev/ttyd4</tt> 所代表的 port 用的是 wyse50 終
        端機，連線速度 38400 bps，不使用同位檢查 (<tt/std.38400/ 是從
        <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?gettytab"
        name="/etc/gettytab"> 設定的) 而且 <tt/root/ 可以 login (secure) 。

    <sect1>
      <heading>為什麼我不能執行 <tt/tip/ 及 <tt/cu/ 呢？</heading>

      <p>在您的系統中，<htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?tip"
        name="tip"> 和 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?cu"
        name="cu"> 很可能只能由 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?uucp" name="uucp"> 使用者和
        <tt/dialer/ 群組才能執行。您可以用 <tt/dialer/ 群組來控制到底有誰可
        以存取您的 modem 以及遠端系統。您只要把您自己加到 dialer 群組中就可
        以了。

      <p>另外一種方法是，您可以讓您系統上所有使用者都可以執行 <tt/tip/ 和
        <tt/cu/ ，只要您

      <verb>
        # chmod 4511 /usr/bin/cu
        # chmod 4511 /usr/bin/tip
      </verb>

    <sect1>
      <heading>FreeBSD 不支援我的 stock Hayes modem --- 我要怎麼辦？</heading>

      <p>事實上，<htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?tip"
        name="tip"> 的 man page 已經過時了。一般的 Hayes dialer 已經內建在系
        統內。您只要在 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?remote" name="/etc/remote">
        指定 ``<tt/at=hayes/'' 就可以了。

      <p>可惜的是，Hayes 的驅動程式不夠聰明，有些新 modem 上的進階功能它無法
        辨識出來 --- 例如 <tt/BUSY/ ，<tt/NO DIALTONE/ ，或是
        <tt/CONNECT 115200/ 這類的訊息它就會搞混。您在使用 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?tip" name="tip"> 的時候必須
        把它們關掉 (用 <tt/ATX0&amp;W/) 。

      <p>還有，<tt/tip/ 的 dial 逾時時間是 60 秒。您的 modem 可能要設得更短，
        否則 tip 會認為發生了通訊上的問題。試試看<tt/ATS7=45&amp;W/ 。

      <p>事實上 <tt/tip/ 還沒有完全支援它。解決方法是去修改
        <tt>/usr/src/usr.bin/tip/tip</tt> 目錄裡的 <tt/tipconf.h/ 。很顯然您
        必須要有原始程式碼才能這麼做。

      <p>把 ``<tt/#define HAYES 0/'' 改成 ``<tt/#define HAYES 1/'' 。然後
        ``<tt/make/'' 並 ``<tt/make install/'' 。之後一切都會恢復正常了。

    <sect1>
      <heading>
        我什麼時候要直接鍵入 AT 指令？<label id="direct-at">
      </heading>

      <p>在您的 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?remote"
        name="/etc/remote"> 檔裡加一個 ``<tt/direct/'' 。舉例來說，如果您的
        modem 連接在第一個 serial port，<tt>/dev/cuaa0</tt>，則您要加入下面
        這一行：

      <verb>
        cuaa0:dv=/dev/cuaa0:br#19200:pa=none
      </verb>

      <p>在 br 欄中設定您 modem 所支援的最高速。之後，鍵入 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?tip" name="tip cuaa0"> 之後
        您就連上您的 modem 了。

      <p>如果您的系統上沒有 <tt>/dev/cuaa0</tt> ，您就先這樣：

      <verb>
        # cd /dev
        # ./MAKEDEV cuaa0
      </verb>

      <p>或是您可以用 root 執行 cu 指令，像這樣：

      <verb>
        # cu -l``line'' -s``speed''
      </verb>

      <p>這裡的 line 是指您的 serial port (例如 <tt>/dev/cuaa0</tt>) ，speed
        是指您的傳輸速度 (例如 <tt>57600</tt>) 。如果您下完 AT 指令後，鍵入
        <tt>~.</tt> 可以離開。

    <sect1>
      <heading>pn 欄中的 <tt/@/ 不能用了！</heading>

      <p>電話號碼欄中的 <tt/@/ 記號是用來告訴 tip 去 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?phones(5)"
        name="/etc/phones"> 找電話號碼。但是 <tt/@/ 同時也是 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?remote" name="/etc/remote">
        這類檔案中的特殊字元。您可以加上反斜線：

      <verb>
        pn=\@
      </verb>

    <sect1>
      <heading>我要怎麼在命令列下撥電話呢？</heading>

      <p>在您的 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?remote"
        name="/etc/remote"> 放一個 ``<tt/generic/''。舉例來說：

      <verb>
        tip115200|Dial any phone number at 115200 bps:\
        :dv=/dev/cuaa0:br#115200:at=hayes:pa=none:du:
        tip57600|Dial any phone number at 57600 bps:\
        :dv=/dev/cuaa0:br#57600:at=hayes:pa=none:du:
      </verb>

      <p>然後您就可以像 ``<tt/tip -115200 5551234/'' 這樣用了。如果您比較喜
        歡用 <htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?cu" name="cu">
        的話，使用 generic cu 欄位：

      <verb>
        cu115200|Use cu to dial any number at 115200bps:\
        :dv=/dev/cuaa1:br#57600:at=hayes:pa=none:du:
      </verb>

      <p>然後輸入 ``<tt/cu 5551234 -s 115200/'' 。

    <sect1>
      <heading>我每次用的時候都要輸入 bps 速度嗎？</heading>

      <p>您可以使用類似 <tt/tip1200/ 或是 <tt/cu1200/ 的欄位，不過在您使用之
        前請先確定您的 br 欄可以支援這個速度。<htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?tip" name="tip"> 認為 1200
        bps 是一個很好的預設值，這也就是為什麼要叫做 ``<tt/tip1200/'' 的原因
        了。當然您也可以不要用 1200 bps 。

    <sect1>
      <heading>透過一台 terminal server 來存取主機。</heading>

      <p>除了每次等您連上 server 並鍵入 ``<tt/CONNECT &lt;host&gt;/'' 以外，
        比較好的方法是用 tip 的 <tt/cm/ 。舉例來說，看看 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?remote" name="/etc/remote">：

      <verb>
        pain|pain.deep13.com|Forrester's machine:\
        :cm=CONNECT pain\n:tc=deep13:
        muffin|muffin.deep13.com|Frank's machine:\
        :cm=CONNECT muffin\n:tc=deep13:
        deep13:Gizmonics Institute terminal server:\
        :dv=/dev/cua02:br#38400:at=hayes:du:pa=none:pn=5551234:
      </verb>

      <p>可以讓您只打 ``<tt/tip pain/'' 或是 ``<tt/tip muffin/'' 就可以連上
        pain 或 muffin；然後 ``<tt/tip deep13/'' 可以連上 terminal server。

    <sect1>
      <heading>tip 可以在一次連線中選擇多台機器嗎？</heading>

      <p>通常這個問題發生在：一間大學有一些 modem ，而且有上千名學生要用...

      <p>在 <htmlurl  url="http://www.FreeBSD.org/cgi/man.cgi?remote"
        name="/etc/remote"> 裡為您的大學設一個欄位，並使用  <tt>\@</tt> 作為
        它的  <tt/pn/：

      <verb>
        big-university:\
        :pn=\@:tc=dialout
        dialout:\
        :dv=/dev/cuaa3:br#9600:at=courier:du:pa=none:
      </verb>

      <p>然後，把大學的撥接電話放在 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?phones" name="/etc/phones">
        中：

      <verb>
        big-university 5551111
        big-university 5551112
        big-university 5551113
        big-university 5551114
      </verb>

      <p><htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?tip" name="tip">
        會依照表列的順序依次嚐試，最後放棄。如果您要一直試的話，您可以在
        while 迴圈裡執行  <tt/tip/ 。

    <sect1>
      <heading>為什麼我按兩次 CTRL+P，可是卻只送出了一個 CTRL+P？</heading>

      <p>CTRL+P 是內定的 ``force'' 字元，用來告訴 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?tip" name="tip"> 下一個字元
        是一般字元。您可以藉由 <tt/~s/ (代表 ``設定變數'') 把其他字元設成強
        迫字元。

      <p>鍵入 ``<tt/~sforce=&lt;single-char&gt;/'' 後面接一個 newline 。
        <tt/&lt;single-char&gt;/ 可以是任意單一字元。如果您只打
        <tt/&lt;single-char&gt;/ ，則 nul 就被設成是 force character，您可
        以藉由按 CTRL+2 或是 CTRL+SPACE 來按出 nul 。SHIFT+CTRL+6 是一個不
        錯的 <tt/&lt;single-char&gt;/ ，我看過一些終端機都是這麼設定。

      <p>您也可以在 <tt>&dollar;HOME/.tiprc</tt> 中設定 force character：

      <verb>
        force=<single-char>
      </verb>

    <sect1>
      <heading>突然間我打的東西都變成大寫了？？</heading>

      <p>您應該是按到了 CTRL+A，在 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?tip" name="tip"> 中為沒有
        caps-lock 鍵的使用者所設計的 ``raise character''。您可以像上個問題
        一樣利用 <tt/~s/ 來把 ``raisechar'' 這個變數改成合理的值。事實上，
        如果您認為您永遠都不會用到這兩個功能的話，您可以把它設成跟 force
        character 一樣。

      <p>下面是一個為 Emacs 使用者所設定的 .tiprc ，Emacs 使用者常常會用到
        CTRL+2 和 CTRL+A：

      <verb>
        force=^^
        raisechar=^^
      </verb>

      <p>^^ 就是 SHIFT+CTRL+6 。

    <sect1>
      <heading>我要如何使用 <tt/tip/ 來傳檔案呢？</heading>

      <p>如果您的對像也是 UNIX 系統的話，您可以用 <tt/~p/ (put) 和 <tt/~t/
        (take) 來收送資料。這兩個命令會在遠端機器執行 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?cat" name="cat"> 和 <htmlurl
        url="http://www.FreeBSD.org/cgi/man.cgi?echo" name="echo"> 來收送檔
        案。用法是：

      <verb>
        ~p <local-file> [<remote-file>]
        ~t <remote-file> [<local-file>]
      </verb>

      <p>它不會做錯誤檢查，所以您最好用別的通訊協定，例如 zmodem 。

    <sect1>
      <heading>我要怎麼用 <tt/tip/ 來跑 zmodem 呢？</heading>

      <p>首先，從 ports 中選一個 zmodem 程式來安 裝 (例如在 comms 目錄下的
        <htmlurl url="http://www.FreeBSD.org/cgi/ports.cgi?^lrzsz"
        name="lrzsz"> 或是 <htmlurl
        url="http://www.FreeBSD.org/cgi/ports.cgi?^rzsz" name="rzsz">) 。

      <p>在接收檔案方面，您要先在遠端啟動傳送程式。然後按 enter 再鍵入
        ``<tt/~C rz/'' (如果您安裝 lrzsz 的話就要打 ``<tt/~C lrz/'') 就可以
        開始接收了。

      <p>在傳送檔案方面，您要先在遠端啟動傳送程式。然後按 enter 再鍵入
        ``<tt/~C sz &lt;files&gt;/'' (或是 ``<tt/~C lsz &lt;files&gt;/'') 就
        可以把檔案送到遠端系統了。

    <sect1>
     <heading>就算我設定無誤，FreeBSD 好像還是找不到我的 serial port？</heading>

     <p>如果您的主機板或是卡上有用到 Acer 的 UART 晶片的話，FreeBSD 在開機時
       的 sio 偵測可能會不正確。您可以從 <url
       url="http://www.lemis.com/serial-port-patch.html" name="www.lemis.com">
       找到 patch 來修正這個問題。

  </sect>
