iPXE
ata.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stddef.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <assert.h>
00030 #include <errno.h>
00031 #include <byteswap.h>
00032 #include <ipxe/list.h>
00033 #include <ipxe/interface.h>
00034 #include <ipxe/blockdev.h>
00035 #include <ipxe/edd.h>
00036 #include <ipxe/ata.h>
00037 
00038 /** @file
00039  *
00040  * ATA block device
00041  *
00042  */
00043 
00044 /******************************************************************************
00045  *
00046  * Interface methods
00047  *
00048  ******************************************************************************
00049  */
00050 
00051 /**
00052  * Issue ATA command
00053  *
00054  * @v control           ATA control interface
00055  * @v data              ATA data interface
00056  * @v command           ATA command
00057  * @ret tag             Command tag, or negative error
00058  */
00059 int ata_command ( struct interface *control, struct interface *data,
00060                   struct ata_cmd *command ) {
00061         struct interface *dest;
00062         ata_command_TYPE ( void * ) *op =
00063                 intf_get_dest_op ( control, ata_command, &dest );
00064         void *object = intf_object ( dest );
00065         int tag;
00066 
00067         if ( op ) {
00068                 tag = op ( object, data, command );
00069         } else {
00070                 /* Default is to fail to issue the command */
00071                 tag = -EOPNOTSUPP;
00072         }
00073 
00074         intf_put ( dest );
00075         return tag;
00076 }
00077 
00078 /******************************************************************************
00079  *
00080  * ATA devices and commands
00081  *
00082  ******************************************************************************
00083  */
00084 
00085 /** List of all ATA commands */
00086 static LIST_HEAD ( ata_commands );
00087 
00088 /** An ATA device */
00089 struct ata_device {
00090         /** Reference count */
00091         struct refcnt refcnt;
00092         /** Block control interface */
00093         struct interface block;
00094         /** ATA control interface */
00095         struct interface ata;
00096 
00097         /** Device number
00098          *
00099          * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
00100          */
00101         unsigned int device;
00102         /** Maximum number of blocks per single transfer */
00103         unsigned int max_count;
00104         /** Device uses LBA48 extended addressing */
00105         int lba48;
00106 };
00107 
00108 /** An ATA command */
00109 struct ata_command {
00110         /** Reference count */
00111         struct refcnt refcnt;
00112         /** ATA device */
00113         struct ata_device *atadev;
00114         /** List of ATA commands */
00115         struct list_head list;
00116 
00117         /** Block data interface */
00118         struct interface block;
00119         /** ATA data interface */
00120         struct interface ata;
00121 
00122         /** Command type */
00123         struct ata_command_type *type;
00124         /** Command tag */
00125         uint32_t tag;
00126 
00127         /** Private data */
00128         uint8_t priv[0];
00129 };
00130 
00131 /** An ATA command type */
00132 struct ata_command_type {
00133         /** Name */
00134         const char *name;
00135         /** Additional working space */
00136         size_t priv_len;
00137         /** Command for non-LBA48-capable devices */
00138         uint8_t cmd_lba;
00139         /** Command for LBA48-capable devices */
00140         uint8_t cmd_lba48;
00141         /**
00142          * Calculate data-in buffer
00143          *
00144          * @v atacmd            ATA command
00145          * @v buffer            Available buffer
00146          * @v len               Available buffer length
00147          * @ret data_in         Data-in buffer
00148          * @ret data_in_len     Data-in buffer length
00149          */
00150         void ( * data_in ) ( struct ata_command *atacmd, userptr_t buffer,
00151                              size_t len, userptr_t *data_in,
00152                              size_t *data_in_len );
00153         /**
00154          * Calculate data-out buffer
00155          *
00156          *
00157          * @v atacmd            ATA command
00158          * @v buffer            Available buffer
00159          * @v len               Available buffer length
00160          * @ret data_out        Data-out buffer
00161          * @ret data_out_len    Data-out buffer length
00162          */
00163         void ( * data_out ) ( struct ata_command *atacmd, userptr_t buffer,
00164                               size_t len, userptr_t *data_out,
00165                               size_t *data_out_len );
00166         /**
00167          * Handle ATA command completion
00168          *
00169          * @v atacmd            ATA command
00170          * @v rc                Reason for completion
00171          */
00172         void ( * done ) ( struct ata_command *atacmd, int rc );
00173 };
00174 
00175 /**
00176  * Get reference to ATA device
00177  *
00178  * @v atadev            ATA device
00179  * @ret atadev          ATA device
00180  */
00181 static inline __attribute__ (( always_inline )) struct ata_device *
00182 atadev_get ( struct ata_device *atadev ) {
00183         ref_get ( &atadev->refcnt );
00184         return atadev;
00185 }
00186 
00187 /**
00188  * Drop reference to ATA device
00189  *
00190  * @v atadev            ATA device
00191  */
00192 static inline __attribute__ (( always_inline )) void
00193 atadev_put ( struct ata_device *atadev ) {
00194         ref_put ( &atadev->refcnt );
00195 }
00196 
00197 /**
00198  * Get reference to ATA command
00199  *
00200  * @v atacmd            ATA command
00201  * @ret atacmd          ATA command
00202  */
00203 static inline __attribute__ (( always_inline )) struct ata_command *
00204 atacmd_get ( struct ata_command *atacmd ) {
00205         ref_get ( &atacmd->refcnt );
00206         return atacmd;
00207 }
00208 
00209 /**
00210  * Drop reference to ATA command
00211  *
00212  * @v atacmd            ATA command
00213  */
00214 static inline __attribute__ (( always_inline )) void
00215 atacmd_put ( struct ata_command *atacmd ) {
00216         ref_put ( &atacmd->refcnt );
00217 }
00218 
00219 /**
00220  * Get ATA command private data
00221  *
00222  * @v atacmd            ATA command
00223  * @ret priv            Private data
00224  */
00225 static inline __attribute__ (( always_inline )) void *
00226 atacmd_priv ( struct ata_command *atacmd ) {
00227         return atacmd->priv;
00228 }
00229 
00230 /**
00231  * Free ATA command
00232  *
00233  * @v refcnt            Reference count
00234  */
00235 static void atacmd_free ( struct refcnt *refcnt ) {
00236         struct ata_command *atacmd =
00237                 container_of ( refcnt, struct ata_command, refcnt );
00238 
00239         /* Remove from list of commands */
00240         list_del ( &atacmd->list );
00241         atadev_put ( atacmd->atadev );
00242 
00243         /* Free command */
00244         free ( atacmd );
00245 }
00246 
00247 /**
00248  * Close ATA command
00249  *
00250  * @v atacmd            ATA command
00251  * @v rc                Reason for close
00252  */
00253 static void atacmd_close ( struct ata_command *atacmd, int rc ) {
00254         struct ata_device *atadev = atacmd->atadev;
00255 
00256         if ( rc != 0 ) {
00257                 DBGC ( atadev, "ATA %p tag %08x closed: %s\n",
00258                        atadev, atacmd->tag, strerror ( rc ) );
00259         }
00260 
00261         /* Shut down interfaces */
00262         intf_shutdown ( &atacmd->ata, rc );
00263         intf_shutdown ( &atacmd->block, rc );
00264 }
00265 
00266 /**
00267  * Handle ATA command completion
00268  *
00269  * @v atacmd            ATA command
00270  * @v rc                Reason for close
00271  */
00272 static void atacmd_done ( struct ata_command *atacmd, int rc ) {
00273 
00274         /* Hand over to the command completion handler */
00275         atacmd->type->done ( atacmd, rc );
00276 }
00277 
00278 /**
00279  * Use provided data buffer for ATA command
00280  *
00281  * @v atacmd            ATA command
00282  * @v buffer            Available buffer
00283  * @v len               Available buffer length
00284  * @ret data            Data buffer
00285  * @ret data_len        Data buffer length
00286  */
00287 static void atacmd_data_buffer ( struct ata_command *atacmd __unused,
00288                                  userptr_t buffer, size_t len,
00289                                  userptr_t *data, size_t *data_len ) {
00290         *data = buffer;
00291         *data_len = len;
00292 }
00293 
00294 /**
00295  * Use no data buffer for ATA command
00296  *
00297  * @v atacmd            ATA command
00298  * @v buffer            Available buffer
00299  * @v len               Available buffer length
00300  * @ret data            Data buffer
00301  * @ret data_len        Data buffer length
00302  */
00303 static void atacmd_data_none ( struct ata_command *atacmd __unused,
00304                                userptr_t buffer __unused, size_t len __unused,
00305                                userptr_t *data __unused,
00306                                size_t *data_len __unused ) {
00307         /* Nothing to do */
00308 }
00309 
00310 /**
00311  * Use private data buffer for ATA command
00312  *
00313  * @v atacmd            ATA command
00314  * @v buffer            Available buffer
00315  * @v len               Available buffer length
00316  * @ret data            Data buffer
00317  * @ret data_len        Data buffer length
00318  */
00319 static void atacmd_data_priv ( struct ata_command *atacmd,
00320                                userptr_t buffer __unused, size_t len __unused,
00321                                userptr_t *data, size_t *data_len ) {
00322         *data = virt_to_user ( atacmd_priv ( atacmd ) );
00323         *data_len = atacmd->type->priv_len;
00324 }
00325 
00326 /** ATA READ command type */
00327 static struct ata_command_type atacmd_read = {
00328         .name = "READ",
00329         .cmd_lba = ATA_CMD_READ,
00330         .cmd_lba48 = ATA_CMD_READ_EXT,
00331         .data_in = atacmd_data_buffer,
00332         .data_out = atacmd_data_none,
00333         .done = atacmd_close,
00334 };
00335 
00336 /** ATA WRITE command type */
00337 static struct ata_command_type atacmd_write = {
00338         .name = "WRITE",
00339         .cmd_lba = ATA_CMD_WRITE,
00340         .cmd_lba48 = ATA_CMD_WRITE_EXT,
00341         .data_in = atacmd_data_none,
00342         .data_out = atacmd_data_buffer,
00343         .done = atacmd_close,
00344 };
00345 
00346 /** ATA IDENTIFY private data */
00347 struct ata_identify_private {
00348         /** Identity data */
00349         struct ata_identity identity;
00350 };
00351 
00352 /**
00353  * Return ATA model string (for debugging)
00354  *
00355  * @v identify          ATA identity data
00356  * @ret model           Model string
00357  */
00358 static const char * ata_model ( struct ata_identity *identity ) {
00359         static union {
00360                 uint16_t words[ sizeof ( identity->model ) / 2 ];
00361                 char text[ sizeof ( identity->model ) + 1 /* NUL */ ];
00362         } buf;
00363         unsigned int i;
00364 
00365         for ( i = 0 ; i < ( sizeof ( identity->model ) / 2 ) ; i++ )
00366                 buf.words[i] = bswap_16 ( identity->model[i] );
00367 
00368         return buf.text;
00369 }
00370 
00371 /**
00372  * Handle ATA IDENTIFY command completion
00373  *
00374  * @v atacmd            ATA command
00375  * @v rc                Reason for completion
00376  */
00377 static void atacmd_identify_done ( struct ata_command *atacmd, int rc ) {
00378         struct ata_device *atadev = atacmd->atadev;
00379         struct ata_identify_private *priv = atacmd_priv ( atacmd );
00380         struct ata_identity *identity = &priv->identity;
00381         struct block_device_capacity capacity;
00382 
00383         /* Close if command failed */
00384         if ( rc != 0 ) {
00385                 atacmd_close ( atacmd, rc );
00386                 return;
00387         }
00388 
00389         /* Extract capacity */
00390         if ( identity->supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
00391                 atadev->lba48 = 1;
00392                 capacity.blocks = le64_to_cpu ( identity->lba48_sectors );
00393         } else {
00394                 capacity.blocks = le32_to_cpu ( identity->lba_sectors );
00395         }
00396         capacity.blksize = ATA_SECTOR_SIZE;
00397         capacity.max_count = atadev->max_count;
00398         DBGC ( atadev, "ATA %p is a %s\n", atadev, ata_model ( identity ) );
00399         DBGC ( atadev, "ATA %p has %#llx blocks (%ld MB) and uses %s\n",
00400                atadev, capacity.blocks,
00401                ( ( signed long ) ( capacity.blocks >> 11 ) ),
00402                ( atadev->lba48 ? "LBA48" : "LBA" ) );
00403 
00404         /* Return capacity to caller */
00405         block_capacity ( &atacmd->block, &capacity );
00406 
00407         /* Close command */
00408         atacmd_close ( atacmd, 0 );
00409 }
00410 
00411 /** ATA IDENTITY command type */
00412 static struct ata_command_type atacmd_identify = {
00413         .name = "IDENTIFY",
00414         .priv_len = sizeof ( struct ata_identify_private ),
00415         .cmd_lba = ATA_CMD_IDENTIFY,
00416         .cmd_lba48 = ATA_CMD_IDENTIFY,
00417         .data_in = atacmd_data_priv,
00418         .data_out = atacmd_data_none,
00419         .done = atacmd_identify_done,
00420 };
00421 
00422 /** ATA command block interface operations */
00423 static struct interface_operation atacmd_block_op[] = {
00424         INTF_OP ( intf_close, struct ata_command *, atacmd_close ),
00425 };
00426 
00427 /** ATA command block interface descriptor */
00428 static struct interface_descriptor atacmd_block_desc =
00429         INTF_DESC_PASSTHRU ( struct ata_command, block,
00430                              atacmd_block_op, ata );
00431 
00432 /** ATA command ATA interface operations */
00433 static struct interface_operation atacmd_ata_op[] = {
00434         INTF_OP ( intf_close, struct ata_command *, atacmd_done ),
00435 };
00436 
00437 /** ATA command ATA interface descriptor */
00438 static struct interface_descriptor atacmd_ata_desc =
00439         INTF_DESC_PASSTHRU ( struct ata_command, ata,
00440                              atacmd_ata_op, block );
00441 
00442 /**
00443  * Create ATA command
00444  *
00445  * @v atadev            ATA device
00446  * @v block             Block data interface
00447  * @v type              ATA command type
00448  * @v lba               Starting logical block address
00449  * @v count             Number of blocks to transfer
00450  * @v buffer            Data buffer
00451  * @v len               Length of data buffer
00452  * @ret rc              Return status code
00453  */
00454 static int atadev_command ( struct ata_device *atadev,
00455                             struct interface *block,
00456                             struct ata_command_type *type,
00457                             uint64_t lba, unsigned int count,
00458                             userptr_t buffer, size_t len ) {
00459         struct ata_command *atacmd;
00460         struct ata_cmd command;
00461         int tag;
00462         int rc;
00463 
00464         /* Allocate and initialise structure */
00465         atacmd = zalloc ( sizeof ( *atacmd ) + type->priv_len );
00466         if ( ! atacmd ) {
00467                 rc = -ENOMEM;
00468                 goto err_zalloc;
00469         }
00470         ref_init ( &atacmd->refcnt, atacmd_free );
00471         intf_init ( &atacmd->block, &atacmd_block_desc, &atacmd->refcnt );
00472         intf_init ( &atacmd->ata, &atacmd_ata_desc,
00473                     &atacmd->refcnt );
00474         atacmd->atadev = atadev_get ( atadev );
00475         list_add ( &atacmd->list, &ata_commands );
00476         atacmd->type = type;
00477 
00478         /* Sanity check */
00479         if ( len != ( count * ATA_SECTOR_SIZE ) ) {
00480                 DBGC ( atadev, "ATA %p tag %08x buffer length mismatch (count "
00481                        "%d len %zd)\n", atadev, atacmd->tag, count, len );
00482                 rc = -EINVAL;
00483                 goto err_len;
00484         }
00485 
00486         /* Construct command */
00487         memset ( &command, 0, sizeof ( command ) );
00488         command.cb.lba.native = lba;
00489         command.cb.count.native = count;
00490         command.cb.device = ( atadev->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
00491         command.cb.lba48 = atadev->lba48;
00492         if ( ! atadev->lba48 )
00493                 command.cb.device |= command.cb.lba.bytes.low_prev;
00494         command.cb.cmd_stat =
00495                 ( atadev->lba48 ? type->cmd_lba48 : type->cmd_lba );
00496         type->data_in ( atacmd, buffer, len,
00497                         &command.data_in, &command.data_in_len );
00498         type->data_out ( atacmd, buffer, len,
00499                          &command.data_out, &command.data_out_len );
00500 
00501         /* Issue command */
00502         if ( ( tag = ata_command ( &atadev->ata, &atacmd->ata,
00503                                    &command ) ) < 0 ) {
00504                 rc = tag;
00505                 DBGC ( atadev, "ATA %p tag %08x could not issue command: %s\n",
00506                        atadev, atacmd->tag, strerror ( rc ) );
00507                 goto err_command;
00508         }
00509         atacmd->tag = tag;
00510 
00511         DBGC2 ( atadev, "ATA %p tag %08x %s cmd %02x dev %02x LBA%s %08llx "
00512                 "count %04x\n", atadev, atacmd->tag, atacmd->type->name,
00513                 command.cb.cmd_stat, command.cb.device,
00514                 ( command.cb.lba48 ? "48" : "" ),
00515                 ( unsigned long long ) command.cb.lba.native,
00516                 command.cb.count.native );
00517 
00518         /* Attach to parent interface, mortalise self, and return */
00519         intf_plug_plug ( &atacmd->block, block );
00520         ref_put ( &atacmd->refcnt );
00521         return 0;
00522 
00523  err_command:
00524  err_len:
00525         atacmd_close ( atacmd, rc );
00526         ref_put ( &atacmd->refcnt );
00527  err_zalloc:
00528         return rc;
00529 }
00530 
00531 /**
00532  * Issue ATA block read
00533  *
00534  * @v atadev            ATA device
00535  * @v block             Block data interface
00536  * @v lba               Starting logical block address
00537  * @v count             Number of blocks to transfer
00538  * @v buffer            Data buffer
00539  * @v len               Length of data buffer
00540  * @ret rc              Return status code
00541 
00542  */
00543 static int atadev_read ( struct ata_device *atadev,
00544                          struct interface *block,
00545                          uint64_t lba, unsigned int count,
00546                          userptr_t buffer, size_t len ) {
00547         return atadev_command ( atadev, block, &atacmd_read,
00548                                 lba, count, buffer, len );
00549 }
00550 
00551 /**
00552  * Issue ATA block write
00553  *
00554  * @v atadev            ATA device
00555  * @v block             Block data interface
00556  * @v lba               Starting logical block address
00557  * @v count             Number of blocks to transfer
00558  * @v buffer            Data buffer
00559  * @v len               Length of data buffer
00560  * @ret rc              Return status code
00561  */
00562 static int atadev_write ( struct ata_device *atadev,
00563                           struct interface *block,
00564                           uint64_t lba, unsigned int count,
00565                           userptr_t buffer, size_t len ) {
00566         return atadev_command ( atadev, block, &atacmd_write,
00567                                 lba, count, buffer, len );
00568 }
00569 
00570 /**
00571  * Read ATA device capacity
00572  *
00573  * @v atadev            ATA device
00574  * @v block             Block data interface
00575  * @ret rc              Return status code
00576  */
00577 static int atadev_read_capacity ( struct ata_device *atadev,
00578                                   struct interface *block ) {
00579         struct ata_identity *identity;
00580 
00581         assert ( atacmd_identify.priv_len == sizeof ( *identity ) );
00582         assert ( atacmd_identify.priv_len == ATA_SECTOR_SIZE );
00583         return atadev_command ( atadev, block, &atacmd_identify,
00584                                 0, 1, UNULL, ATA_SECTOR_SIZE );
00585 }
00586 
00587 /**
00588  * Close ATA device
00589  *
00590  * @v atadev            ATA device
00591  * @v rc                Reason for close
00592  */
00593 static void atadev_close ( struct ata_device *atadev, int rc ) {
00594         struct ata_command *atacmd;
00595         struct ata_command *tmp;
00596 
00597         /* Shut down interfaces */
00598         intf_shutdown ( &atadev->block, rc );
00599         intf_shutdown ( &atadev->ata, rc );
00600 
00601         /* Shut down any remaining commands */
00602         list_for_each_entry_safe ( atacmd, tmp, &ata_commands, list ) {
00603                 if ( atacmd->atadev != atadev )
00604                         continue;
00605                 atacmd_get ( atacmd );
00606                 atacmd_close ( atacmd, rc );
00607                 atacmd_put ( atacmd );
00608         }
00609 }
00610 
00611 /**
00612  * Describe ATA device using EDD
00613  *
00614  * @v atadev            ATA device
00615  * @v type              EDD interface type
00616  * @v path              EDD device path
00617  * @ret rc              Return status code
00618  */
00619 static int atadev_edd_describe ( struct ata_device *atadev,
00620                                  struct edd_interface_type *type,
00621                                  union edd_device_path *path ) {
00622 
00623         type->type = cpu_to_le64 ( EDD_INTF_TYPE_ATA );
00624         path->ata.slave = ( ( atadev->device == ATA_DEV_SLAVE ) ? 0x01 : 0x00 );
00625         return 0;
00626 }
00627 
00628 /** ATA device block interface operations */
00629 static struct interface_operation atadev_block_op[] = {
00630         INTF_OP ( block_read, struct ata_device *, atadev_read ),
00631         INTF_OP ( block_write, struct ata_device *, atadev_write ),
00632         INTF_OP ( block_read_capacity, struct ata_device *,
00633                   atadev_read_capacity ),
00634         INTF_OP ( intf_close, struct ata_device *, atadev_close ),
00635         INTF_OP ( edd_describe, struct ata_device *, atadev_edd_describe ),
00636 };
00637 
00638 /** ATA device block interface descriptor */
00639 static struct interface_descriptor atadev_block_desc =
00640         INTF_DESC_PASSTHRU ( struct ata_device, block,
00641                              atadev_block_op, ata );
00642 
00643 /** ATA device ATA interface operations */
00644 static struct interface_operation atadev_ata_op[] = {
00645         INTF_OP ( intf_close, struct ata_device *, atadev_close ),
00646 };
00647 
00648 /** ATA device ATA interface descriptor */
00649 static struct interface_descriptor atadev_ata_desc =
00650         INTF_DESC_PASSTHRU ( struct ata_device, ata,
00651                              atadev_ata_op, block );
00652 
00653 /**
00654  * Open ATA device
00655  *
00656  * @v block             Block control interface
00657  * @v ata               ATA control interface
00658  * @v device            ATA device number
00659  * @v max_count         Maximum number of blocks per single transfer
00660  * @ret rc              Return status code
00661  */
00662 int ata_open ( struct interface *block, struct interface *ata,
00663                unsigned int device, unsigned int max_count ) {
00664         struct ata_device *atadev;
00665 
00666         /* Allocate and initialise structure */
00667         atadev = zalloc ( sizeof ( *atadev ) );
00668         if ( ! atadev )
00669                 return -ENOMEM;
00670         ref_init ( &atadev->refcnt, NULL );
00671         intf_init ( &atadev->block, &atadev_block_desc, &atadev->refcnt );
00672         intf_init ( &atadev->ata, &atadev_ata_desc, &atadev->refcnt );
00673         atadev->device = device;
00674         atadev->max_count = max_count;
00675 
00676         /* Attach to ATA and parent and interfaces, mortalise self,
00677          * and return
00678          */
00679         intf_plug_plug ( &atadev->ata, ata );
00680         intf_plug_plug ( &atadev->block, block );
00681         ref_put ( &atadev->refcnt );
00682         return 0;
00683 }