CAM_CDBPARSE(3)

명칭
csio_build, csio_build_visit, csio_decode, csio_decode_visit, buff_decode, buff_decode_visit, csio_encode, csio_encode_visit, buff_encode_visit - CAM 유저 프로그램 라이브러리 SCSI 버퍼 파스 routine

프로그램 라이브러리
libcam

서식
<stdio.h> <camlib.h> int csio_build(struct ccb_scsiio *csio, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t flags, int retry_count, int timeout, char *cmd_spec, ...) int csio_build_visit(struct ccb_scsiio *csio, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t flags, int retry_count, int timeout, char *cmd_spec, int (*arg_get)(void *hook, char *field_name), void *gethook) int csio_decode(struct ccb_scsiio *csio, char *fmt, ...) int csio_decode_visit(struct ccb_scsiio *csio, char *fmt, void (*arg_put)(void *hook, int letter, void *val, int count, char *name), void *puthook) int buff_decode(u_int8_t *buff, size_t len, char *fmt, ...) int buff_decode_visit(u_int8_t *buff, size_t len, char *fmt, void (*arg_put)(void *, int, void *, int, char *), void *puthook) int csio_encode(struct ccb_scsiio *csio, char *fmt, ...) int csio_encode_visit(struct ccb_scsiio *csio, char *fmt, int (*arg_get)(void *hook, char *field_name), void *gethook) int buff_encode_visit(u_int8_t *buff, size_t len, char *fmt, int (*arg_get)(void *hook, char *field_name), void *gethook)

해설
CAM 버퍼 /CDB encode 및 디코드 routine는, 낡다 FreeBSD SCSI 레이어의, 유사한 이름의 scsireq_* 함수로 쓰여진 유저 랜드 SCSI 어플리케이션에 대해, 비교적 간단하게 새로운 인터페이스에의 이행 할 수 있는 이치를 제공합니다.

이러한 함수는, 새로운 어플리케이션으로 사용해도 상관하지 않습니다만, 유저는, cam(3) 프로그램 라이브러리에 집어 넣을 수 있었던 함수를 구축하는 각종 SCSI CCB 구축 함수를 사용하는 (분)편이 간단하다고 하는 것에 눈치채겠지요 ( 예를 들어, cam_fill_csio(), scsi_start_stop(), csi_read_write() 입니다).

csio_build() (은)는, 변수 인수 리스트에 제공된 정보를 기초로 해 ccb_scsiio 구조체를 구축합니다. 이 함수는, 이 함수에게 건네지는 NULL 의 data_ptrt 인수를 정연하게 처리합니다.

dxfer_len (은)는, 데이터 국면의 길이입니다. 데이터 전송의 방향은 flags 인수에 의해 정해집니다.

data_ptr (은)는, SCSI 데이터 국면의 사이에 사용되는 데이터 버퍼입니다. 문제의 SCSI 명령에 대해 데이터가 전송 되지 않는 경우는, 이것을 NULL 로 설정한다 필요가 있습니다. 명령에 대해 전송 하는 데이터가 있는 경우는, 이 버퍼는 적어도 dxfer_len 의 길이가 아니면 않으면 안됩니다.

flags 하 <cam/cam_ccb.h> 에 정의된 플래그가 아니면 안됩니다.

    /* 공통의 CCB 헤더 */
    /* CAM CCB 플래그 */
    typedef enum {
         CAM_CDB_POINTER       = 0x00000001,/* CDB 필드는 포인터이다 */
         CAM_QUEUE_ENABLE      = 0x00000002,/* SIM 기다리는 행렬 처치는 유효하다 */
         CAM_CDB_LINKED        = 0x00000004,/* CCB 는 링크 한 CDB 를 포함한다 */
         CAM_SCATTER_VALID     = 0x00000010,/* 분산/수집 리스트는 유효하다 */
         CAM_DIS_AUTOSENSE     = 0x00000020,/* 자동 탐지 기능을 무효로 한다 */
         CAM_DIR_RESV          = 0x00000000,/* 데이터 방향 (00:예약이 끝난 상태) */
         CAM_DIR_IN            = 0x00000040,/* 데이터 방향 (01:DATA IN) */
         CAM_DIR_OUT           = 0x00000080,/* 데이터 방향 (10:DATA OUT) */
         CAM_DIR_NONE          = 0x000000C0,/* 데이터 방향 (11:데이터 없음) */
         CAM_DIR_MASK          = 0x000000C0,/* 데이터 방향 마스크 */
         CAM_SOFT_RST_OP       = 0x00000100,/* 대신에 소프트 리셋트를 사용한다 */
         CAM_ENG_SYNC          = 0x00000200,/* 완료시에 잉여 바이트를 플래시 한다 */
         CAM_DEV_QFRZDIS       = 0x00000400,/* DEV Q 동결을 무효로 한다 */
         CAM_DEV_QFREEZE       = 0x00000800,/* 실행시에 DEV Q 를 동결한다 */
         CAM_HIGH_POWER        = 0x00001000,/* 명령은 대량의 능력을 얻는다 */
         CAM_SENSE_PTR         = 0x00002000,/* 센스 데이터는 포인터이다 */
         CAM_SENSE_PHYS        = 0x00004000,/* 센스 포인터는 물리적인 주소 */
         CAM_TAG_ACTION_VALID  = 0x00008000,/* 이 ccb 내에서는 태그 처치를 사용한다 */
         CAM_PASS_ERR_RECOVER  = 0x00010000,/* 수수 드라이버 에러. 회복 */
         CAM_DIS_DISCONNECT    = 0x00020000,/* 절단을 무효로 한다 */
         CAM_SG_LIST_PHYS      = 0x00040000,/* SG 리스트에 물리 주소가 있다 */
         CAM_MSG_BUF_PHYS      = 0x00080000,/* 메세지 버퍼 ptr 가 물리적이다 */
         CAM_SNS_BUF_PHYS      = 0x00100000,/* 자동 탐지 데이터 ptr 가 물리적이다 */
         CAM_DATA_PHYS         = 0x00200000,/* SG/버퍼 데이터 ptr 가 물리적이다 */
         CAM_CDB_PHYS          = 0x00400000,/* CDB 포인터가 물리적이다 */
         CAM_ENG_SGLIST        = 0x00800000,/* SG 리스트는 HBA 엔진용이다 */
    /* 국면 인식 모드 플래그 */
         CAM_DIS_AUTOSRP       = 0x01000000,/* 자동 보존/복원 포인터를 무효로 한다 */
         CAM_DIS_AUTODISC      = 0x02000000,/* 자동 절단을 무효로 한다 */
         CAM_TGT_CCB_AVAIL     = 0x04000000,/* 타겟의 CCB 가 이용 가능 */
         CAM_TGT_PHASE_MODE    = 0x08000000,/* SIM 가 국면 모드로 실행된다 */
         CAM_MSGB_VALID        = 0x20000000,/* 메세지 버퍼가 유효 */
         CAM_STATUS_VALID      = 0x40000000,/* 스테이터스 버퍼가 유효 */
         CAM_DATAB_VALID       = 0x80000000,/* 데이터 버퍼가 유효 */
    /* 호스트 타겟 모드 플래그 */
         CAM_TERM_IO           = 0x20000000,/* 입출력 메세지 보충을 종료 */
         CAM_DISCONNECT        = 0x40000000,/* 절단은 필수이다 */
         CAM_SEND_STATUS       = 0x80000000,/* 데이터 국면의 뒤에 스테이터스를 송신 */
    } ccb_flags;

복수의 플래그를 지정하는 경우, OR (논리합)를 취할 필요가 있습니다. 어느 CCB 플래그를 사용할 수도 있습니다. 이후의 중요한 몇개의 플래그에 대해서는 특별히 설명해 두는 가치가 있습니다.

CAM_DIR_IN
    문제의 조작이 읽어내 조작인 것을 나타냅니다. 즉, 데이터는 SCSI 디바이스로부터 유저 지정 버퍼에 읽어내지고 있습니다.

CAM_DIR_OUT
    조작이 기입해 조작인 것을 나타냅니다. 즉, 데이터는 유저 지정 버퍼로부터 디바이스에 기입해지고 있습니다.

CAM_DIR_NONE
    이 명령에 대해 전송 되는 데이터는 없는 것을 나타냅니다.

CAM_DEV_QFRZDIS
    디바이스 기다리는 행렬의, 에러 회복 메카니즘으로서의 동결을 무효로 합니다.

CAM_PASS_ERR_RECOVER
    pass(4) 드라이버에 에러 회복을 유효하게 하도록(듯이) 통지합니다. 디폴트에서는 에러 회복이 실행되지 않습니다. 즉, 이 플래그 하지만 없는 경우는 재시행 카운트는 의미를 가지지 않습니다.

CAM_DATA_PHYS
    data_ptr 에 들어가 있는 주소가, 가상 주소는 아니고 물리 주소인 것을 나타냅니다.

retry_count (은)는, 문제의 명령을 몇회재시행할까를 커널에 통지합니다. pass(4) 드라이버가 CAM_PASS_ERR_RECOVER 플래그에 의해 회복을 유효하게 하는 듯 지시받지 않은 한, 재시행 카운트는 무시됩니다.

timeout (은)는, 지정의 명령이 완료할 때까지 어느 정도 대기할까를 커널에 통지합니다. 시간이 끊어져 게다가 명령이 완료하고 있지 않으면 CCB (은)는, 해당한다 에러 스테이터스로 커널로부터 돌아갑니다.

cmd_specis (은)는 SCSI CDB 를 구축하는데 사용되는 CDB 형식 지시자입니다. 이 텍스트 string는, 필드 지시자의 리스트로 구성됩니다. 필드 지시자는, 각 CDB 필드용의 값 (값을 변수 인수 리스트내의 다음의 인수로부터 취해야 할 일을 나타내는 일도 포함한다), 필드의 폭 (비트 단위 또는 바이트 단위), 및 옵션의 이름을 지정합니다. 스페이스는 무시되어 샤프 기호 ('#')는, 현재의 행의 말미로 종료하는 코멘트의 선두를 나타냅니다.

옵션의 이름은, 필드 지정자의 최초의 부분이며, 안괄호로 둘러싸입니다. 다음의 예로 안괄호로 둘러싸인 텍스트는 이름입니다.
    {PS} v:b1 {Reserved} 0:b1 {Page Code} v:b6 # Mode select page

이 필드 지정자에게는, 3 개의 필드가 있습니다. 1 비트의 필드가 2 개(살)과 6 비트의 필드가 1 개(살)입니다. 2 번째의 1 비트 필드는 정수치 0 이며, 최초의 1 비트 필드와 6 비트 필드는, 변수 인수 리스트로부터 놓칩니다. 복수 바이트의 필드는 SCSI 의 아르바이트 순서로 CDB 내에 스왑 되어 스페이스는 무시됩니다.

필드가 16 진수치 또는 캐릭터 v 때 ( 예를 들어, 1A 또는 v) , 1 바이트치가 CDB 안의 다음의 미사용 바이트에 카피됩니다. 캐릭터 v 하지만 사용되고 있을 때, 다음의 정수 인수가 변수 인수 리스트로부터 놓쳐 그 값이 사용됩니다.

정수의 16 진수치에 필드폭의 지정자, 또는 캐릭터 v 에 필드폭지정자 필드가 계속된 것 ( 예를 들어, 3:4, 3:b4, 3:i3, v:i3) (은)는, 지정의 비트 또는 바이트폭의 필드를 지정합니다. 정수치, 또는 (V 지정자의 경우) 가변 인수 리스트의 다음의 정수치가, CDB 의 다음의 미사용 비트 또는 바이트에 카피됩니다.

10 진수 또는 캐릭터 b 에 10 진수 필드폭이 계속된 것은, 그 폭의 비트 필드를 나타냅니다. 비트 필드는, 가능한 한 긴밀히 팩 되어 상위 비트로 개시해 (SCSI 사양과 같은 것을 읽어내지도록(듯이)입니다 ) , 1 바이트가 완전하게 가득하게 될 때는 언제라도, 또는 i 필드가 검출되었을 때는, CDB 의 새로운 바이트가 개시됩니다.

캐릭터 i 의 후에 1, 2, 3, 또는 4 가 계속된 필드폭지시자는, SCSI 바이트순서 (MSB 가 선두)에 스왑 해야 한다 1, 2, 3, 또는 4 바이트의 정수치를 나타냅니다.

v 필드 지시자에 대해서는, 다음의 정수 인수가, 변수 인수 리스트로부터 놓쳐 그 값이 SCSI 순서에 스왑 하는데 사용됩니다.

csio_build_visit() 하 csio_build() (와)과 동작이 유사하고 있습니다만, cmd_spec 안의 변수 인수에 옮겨지는 값이, stdarg(3) 에 의해서가 아니라, csio_build_visit() 에 건네받는다 arg_get() 함수에 의해 꺼내지는 점이 다릅니다. arg_get() 함수는 다음의 2 개의 인수를 취합니다.

gethook
    (은)는 함수 호출마다 arg_get() 함수에게 건네집니다. 이것에 의해, arg_get() 함수는, 글로벌 변수 또는 정적 변수를 사용하지 않고 , 사이의 호출동안에 상태의 얼마인지를 보관 유지할 수가 있습니다.

field_name
    (은)는, fmt (이)가 있는 경우는 거기에 따라 주어지는 이름입니다.

csio_decode() (은)는, SCSI 전송의 국면으로 데이터의 정보를 디코드하는데 사용됩니다.

디코드는, csio_build() 의 명령 지시자 처리에 유사하고 있습니다만, csio->data_ptr 에 의해 가리켜지는 데이터로부터 데이타를 뽑기 시작하는 점이 다릅니다. stdarg 리스트는, 정수치는 아니고 정수를 가리키는 포인터입니다. 시크 field type와 억제 수식자가 추가됩니다. * 억제 수식자 ( 예를 들어, *i3 또는 *b4) (은)는, 필드로부터의 할당을 억제해, 데이터내의 바이트 또는 비트를 스킵 하는데 사용할 수 있습니다. 이것에 의해 arg 리스트내의 더미 변수에 카피할 필요가 없어집니다.

시크 field type s 에 의해, 데이터를 스킵 할 수 있습니다. 이것은, '+'부호의 존재의 유무에 근거해, 데이터내의 절대 위치 (s3) 또는 상대 위치 (s+3) (을)를 찾습니다. 시크치는 v (으)로서 지정할 수가 있어 인수 리스트 의 다음의 정수치가 시크치로서 사용됩니다.

csio_decode_visit() (은)는, csio_decode() (와)과 같이 동작합니다만, 디코드 한 버퍼의 내용을 가변장 인수에 배치하는 대신에, 디코드한 버퍼 의 내용은, 건네받았다 arg_put() 함수를 통해서 유저에게 돌려주어지는 점이 다릅니다. arg_put() 함수는, 다음의 몇개의 인수를 취합니다.

hook
    "hook" 는, arg_put() 함수가 호출동안에서 상태를 보존할 수 있도록(듯이) 한다 메카니즘입니다.

letter
    함수에게 건네지는 인수의 형식을 기술하는 캐릭터입니다.

val 함수에게 건네지는 값을 가리키는 void 포인터입니다.

count
    arg_put() 함수에게 건네지는 값의 사이즈입니다. 인수의 포맷에 의해 크기의 단위가 정해집니다.

name
    필드의 텍스트 기술입니다. 다만 fmt 안에 그것이 준비되어 있다 경우입니다.

buff_decode() (은)는, csio_decode() 에 붙어 전술한 방식을 사용해 임의의 데이터 버퍼를 디코드합니다.

buff_decode_visit() (은)는, csio_decode_visit() 에 붙어 전술한 방식을 사용해 임의의 데이터 버퍼를 디코드합니다.

csio_encode() (은)는, csio_build() 에 붙어 전술한 방식을 사용해, ccb_scsiio 의 구조 data_ptr 부분 (CDB (은)는 아니다 ) (을)를 encode 합니다.

csio_encode_visit() (은)는, csio_build_visit() 에 붙어 전술한 방식을 사용해, ccb_scsiio 구조의 data_ptr 부분 (CDB (은)는 아니다 ) (을)를 encode 합니다.

buff_encode_visit() (은)는, csio_build_visit() 에 붙어 전술한 방식을 사용해, 임의의 데이터 포인터를 encode 합니다.

반환값
csio_build(), csio_build_visit(), csio_encode(), csio_encode_visit() 및 buff_encode_visit() (은)는, 처리필 보고의 필드의 수를 돌려줍니다.

csio_decode(), csio_decode_visit(), buff_decode() 및 buff_decode_visit() (은)는, 실행된 할당의 수를 돌려줍니다.

관련 항목
cam(3), pass(4), camcontrol(8)

역사
이러한 함수의 CAM 버젼은, 낡다 FreeBSD 의 SCSI 레이어용으로 실현된 유사한 함수를 기초로 하고 있습니다. SCSI 의 낡은 코드내의 encode/디코드 함수는 Peter Dufault 가 작성한 것입니다.

다수의 시스템에, 유저 공간에서 SCSI 명령을 유저가 구축할 수 있는, 이것과 필적하는 인터페이스가 있습니다.

낡다 scsireq 데이터 구조는, SGI 의 /dev/scsi 데이터 구조와 거의 같았습니다. 저자의 이름을 알고 있는 사람은 여기에 연락해 주세요. Peter Dufault 는, 1989 년의 「Sun Expert」잡지로, 최초로 이것에 대해 읽었습니다.

새로운 CCB 데이터 구조는, CAM-2 및 CAM-3 사양에 유래하고 있습니다.

Peter Dufault (은)는, 386BSD 그리고 SGI 의 인터페이스의 클론을 실현했습니다. 이것이 오리지날의 FreeBSD SCSI 프로그램 라이브러리와 관련 커널 ioctl 에 이르는 것이 되었습니다. 호환성의 필요가 있는 경우는, dufault@hda.com 에 연락해 주세요.

저자
Kenneth Merry 가, 이러한 encode 및 디코드의 함수의 CAM 버젼을 실현했습니다. 이 현재의 작업은, Peter Dufault 에 의하기 이전의 작업을 기초로 하고 있습니다.

버그
CDB 및 SCSI CCB 의 데이터 버퍼 부분의 양쪽 모두를 encode 하는 함수는 아마 필요하겠지요. camcontrol(8) 그리고 임의의 명령 실행 코드를 실현하고 있는 동안에 나는 이 필요성에 눈치챘습니다만, 그러한 함수를 실현하는 시간이 아직 없습니다.

CCB 플래그의 설명에는 사실은 여기에 속하지 않는 것이 있습니다. 그것들은 일반의 CCB 메뉴얼 페이지에 속합니다. 그 메뉴얼 페이지는 아직 쓰여지지 않기 때문에, 여기서의 짧은 설명으로 도움이 되게 하지 않을 수 없습니다.